HTTP 401 vs 403: what is the difference?

Both mean “you can’t have this”, and the names are famously confusing. The real difference is whether logging in again could help.

The difference in one table

401 Unauthorized403 Forbidden
Question the server is answeringWho are you?Are you allowed?
Typical causeMissing, expired or malformed token, wrong passwordValid login but wrong role, IP blocked, file permissions, firewall rule
Will logging in again help?Usually yesNo, unless you log in as someone else
Must includeA WWW-Authenticate header saying how to log inNothing special
What the client should doRefresh the token or ask the user to sign inShow “no access”; do not retry in a loop

The name “Unauthorized” is a historical accident. In HTTP, authentication is proving who you are and authorization is what you may do; 401 is about the first and 403 about the second. The current HTTP standard, RFC 9110, keeps the old names for compatibility.

Which one should my API return?

Looking up a code you don’t recognise? Anvil’s free HTTP status lookup gives the meaning, common causes and retry advice for every status code, including nginx 499 and Cloudflare 520–526.

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="api", error="invalid_token", error_description="The access token expired"

With WWW-Authenticate: Basic, browsers pop up their own username and password box. That is why a 401 from a page, rather than an API call, can suddenly show a login prompt.

Debugging a 401

Debugging a 403

Related

Designing share links you can revoke · Removed someone but they can still see the file · HTTP 429 Too Many Requests · download won't resume

Questions

Is 401 or 403 correct for an expired token?

401. The credentials are no longer valid, and getting a new token fixes it. Use 403 only when a valid identity lacks permission.

Should I return 403 or 404 for a resource the user cannot see?

If revealing that it exists would leak information, return 404. If the user knows it exists and simply lacks permission, 403 is clearer.

Why does my browser show a login popup?

The server returned 401 with WWW-Authenticate: Basic (or Digest). Browsers answer that with their built-in sign-in box.

Is a 403 always the server's fault?

No. It is a deliberate refusal. It may be a misconfiguration, such as file permissions or a firewall rule, but it can also be working exactly as intended.

Published · updated .

Try it

Related guides

Newest guides