OwlTheEngineer
How It Actually WorksEpisode 25 · Backend

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.

Owl · 1 min read · 6 views
– comments
Ep 25 · Backend
60s VISUAL BREAKDOWN
Episode 25
Watch the fast visual breakdown or discuss on social:

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

ScenarioHTTP StatusReason
Request missing Authorization header401 UnauthorizedIdentity is unknown
JWT signature is invalid or token expired401 UnauthorizedCredentials cannot be verified
Regular user tries to DELETE /api/admin/users/4403 ForbiddenIdentity is verified, but lacks permission
Valid API key attempts to write to a read-only endpoint403 ForbiddenKnown client lacks write scope
Resource belongs to another tenant and shouldn’t leak404 Not FoundPrevents resource enumeration
SYSTEM DESIGN CHECK

Test Your Understanding

Quick architectural scenario challenge based on this breakdown.

SCENARIO

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 –