401 Unauthorized vs 403 Forbidden
401 means 'I don't know who you are (authenticate yourself)'. 403 means 'I know who you are, and you don't have permission'. The naming mistake in HTTP and how to use them.
The HTTP specification has a notorious historical naming bug: 401 Unauthorized is actually unauthenticated.
Because the status name says “Unauthorized”, developers constantly mix up 401 and 403 when building APIs.
401 Unauthorized ──> Missing or invalid identity ("Who are you?")
403 Forbidden ──> Known identity, lack of rights ("You may not do this")
401 Unauthorized: Authentication failure
Return 401 Unauthorized when the client has not provided valid credentials or their session/token has expired:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer error="invalid_token", error_description="The token has expired"
Content-Type: application/json
{
"error": "unauthenticated",
"message": "Authentication credentials were missing or expired."
}
The key property of a 401 response: The client can retry the exact same request with new credentials (e.g. log in, refresh their JWT) and succeed.
Per the RFC 9110 specification, a 401 response must also include a WWW-Authenticate header describing how to authenticate.
403 Forbidden: Authorization failure
Return 403 Forbidden when the server knows exactly who the user is, but their role or permissions do not allow them to perform the requested operation:
HTTP/1.1 403 Forbidden
Content-Type: application/json
{
"error": "forbidden",
"message": "User with role 'member' cannot access admin dashboard."
}
The key property of a 403 response: Re-authenticating with the same user credentials will not help. The server understood the identity and deliberately refuses to authorize the request.
When to return 404 instead of 403
In security-sensitive domains (e.g. multi-tenant SaaS, billing info, private repositories), returning 403 Forbidden can leak metadata by confirming that a secret resource ID exists.
If tenant A tries to fetch /api/organizations/tenant_b_id/invoices/99, returning 403 Forbidden confirms invoice 99 exists. Returning 404 Not Found hides the existence of the resource entirely.
Quick Decision Table
| Scenario | HTTP Status | Reason |
|---|---|---|
Request missing Authorization header | 401 Unauthorized | Identity is unknown |
| JWT signature is invalid or token expired | 401 Unauthorized | Credentials cannot be verified |
Regular user tries to DELETE /api/admin/users/4 | 403 Forbidden | Identity is verified, but lacks permission |
| Valid API key attempts to write to a read-only endpoint | 403 Forbidden | Known client lacks write scope |
| Resource belongs to another tenant and shouldn’t leak | 404 Not Found | Prevents resource enumeration |
Test Your Understanding
Quick architectural scenario challenge based on this breakdown.
An authenticated regular user attempts to access an admin-only endpoint: DELETE /api/v1/organizations/99.
Q1.When should an API return 401 Unauthorized vs 403 Forbidden?
Comments –
Sign in to share your thoughts
Nothing yet. Be the first.