Both look like "you can't have this". The difference is whether the server knows who you are.
| 401 Unauthorized | 403 Forbidden | |
|---|---|---|
| Means | Not authenticated. The request had no credentials, or they were wrong or expired. | Authenticated, but not allowed. Who you are is known; this action isn't yours to take. |
| Retrying with credentials | Can work | Won't help |
| Required header | WWW-Authenticate | None |
| Typical cause | Missing or expired token, wrong API key, expired session | Wrong role, another tenant's record, read-only key, IP or region rule |
| Good response body | "Authentication required" | "You don't have access to this project" |
The names are historical: 401 should have been called "Unauthenticated", and 403 "Unauthorized". Read them that way and the rest follows.
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="api", error="invalid_token"
Send it when no token arrived, the token is malformed, its signature fails, or it has expired. The WWW-Authenticate header is required by the specification and tells the client how to try again. Browsers show their own login box for Basic, which is why APIs normally use Bearer.
The credentials are good and the answer is still no: a viewer trying to delete, a key scoped to read-only, one customer's data asked for by another. Say which permission is missing, without leaking whether the record exists.
For "this doesn't exist, and I won't tell you whether it does", 404 is the honest choice, and many APIs return 404 instead of 403 for records in another account.
Authorization header actually there? A redirect, a service worker or a fetch without credentials can drop it.WWW-Authenticate header: real APIs put the reason in error=.OPTIONS without your token, and an authentication check rejects it. Let OPTIONS through.HeaderForge sets Authorization on the sites you choose, keeps the value in a variable so it stays out of exported rules, and shows whether the rule actually fired on this tab. Free, no analytics, no account.
Retry-After.More on this topic: Hard refresh in Chrome, and how to really bypass the cache · What is a HAR file, how to open one, and what it exposes · JWT errors: jwt malformed, invalid signature, jwt expired and more · UUID generator