HTTP Status Codes 401 vs HTTP Status Codes 403
The difference
401 means the server does not know who you are; 403 means it knows and says no. Re-authenticating fixes a 401, never a 403.
| 401 HTTP Status Codes · Unauthorized | 403 HTTP Status Codes · Forbidden | |
|---|---|---|
| Meaning | Missing, invalid or expired credentials | Authenticated, but not permitted |
| Who is wrong | Client credentials | Client permissions (or server policy) |
| Retry? | Once, after refreshing the token | No — same request fails again |
| Typical trigger | Expired JWT, missing Authorization header | Missing scope/role, WAF or IP block, CSRF |
| Fix | Send Authorization: Bearer <valid token> | Grant the role/scope or change the target resource |
| Header to check | WWW-Authenticate (error, error_description) | Response body, cf-ray / server (edge vs app) |
Which one do I have?
- If the request has no or an expired token → it is 401.
- If the token is valid but the action needs a role you lack → it is 403.
- If a CDN/WAF page answers before your app runs → it is 403 at the edge, not your app.