devkult_
tools29converters34

401 Unauthorized

4xx client error

The request lacks valid authentication credentials — the server doesn't know who you are.

Despite its name, 401 is about authentication, not authorization: the server doesn't know who you are. Either no credentials were sent, or the ones sent — token, cookie, API key — are missing, expired or invalid. The response must include a WWW-Authenticate header describing how to authenticate.

Class4xx Client Error
Retry?No — change the request first
Cacheable by defaultNo — only with explicit Cache-Control
Response bodyAllowed
Defined inRFC 9110 §15.5.2 — 401 Unauthorized
Example response
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="api"
Content-Type: application/json
Content-Length: 24

{"error":"Unauthorized"}

Common causes

  • No Authorization header or session cookie was sent.
  • An expired or revoked access token (a JWT whose exp is in the past).
  • A token for the wrong environment or audience, such as a staging key on production.
  • A proxy, redirect or CORS configuration stripping the Authorization header.

How to fix it

  1. Decode the token and check its exp, aud and iss claims.
  2. Refresh the access token and retry once; if that fails, send the user to log in again.
  3. Check the header format: Authorization: Bearer <token>, with one space.
  4. For cross-origin calls, make sure the server allows Authorization in Access-Control-Allow-Headers.

Useful here: 401 vs 403 · JWT Decoder

Send a 401 from your server

Express
res.set("WWW-Authenticate", "Bearer realm=\"api\"");
res.status(401).json({ error: "Unauthorized" });
Next.js route handler
return Response.json({ error: "Unauthorized" }, { status: 401, headers: { "WWW-Authenticate": "Bearer realm=\"api\"" } });
Flask
return {"error": "Unauthorized"}, 401, {"WWW-Authenticate": "Bearer realm=\"api\""}
Go net/http
w.Header().Set("WWW-Authenticate", "Bearer realm=\"api\"")
http.Error(w, "Unauthorized", http.StatusUnauthorized)
nginx
add_header WWW-Authenticate "Bearer realm=\"api\"" always;
return 401;

Check what a URL returns

Print just the status line from the command line, or check a whole list of URLs at once, with their response headers, in the HTTP Status Checker.

curl -sI https://example.com/your-path | head -n 1

Frequently asked questions

401 vs 403 — what's the difference?

401: we don't know who you are — authenticate and try again. 403: we know who you are, and you're not allowed. Logging in again fixes a 401; it won't fix a 403.

Why does a 401 open a browser login popup?

The response carried WWW-Authenticate: Basic, and browsers show their native credential dialog for Basic auth. APIs should use the Bearer scheme to avoid it.

Headers used with 401
Related status codes