HTTP 401 vs 403 vs 404 Explained

Published July 22, 2026By Samson PG

Quick answer

401 means “who are you?”, 403 means “I know you, but no,” and 404 means “nothing here (or I will not say).” Mixing them up sends you to the wrong layer of the stack.

HTTP Status Codes

An HTTP status code is the server’s short answer to a request. Three of the most confused codes sit in the 4xx client error class: 401 Unauthorized, 403 Forbidden, and 404 Not Found. They look similar in a red Network panel, but they point at different fixes — auth, authorization, or routing/existence.

401 vs 403 vs 404 at a glance

Code Meaning in practice Typical fix
401 Missing or invalid authentication Login, refresh token, fix Authorization header
403 Authenticated (or refused) but not allowed Roles, scopes, ACLs, feature flags
404 No matching resource (or hidden) Path, ID, deploy, CDN, soft-delete

Rule of thumb: if fixing the password or token would help, lean 401. If the user is already “in” and still blocked, lean 403. If the URL or resource ID is wrong, lean 404.

Why the names are misleading

401 Unauthorized is historically named poorly. In modern APIs it usually means unauthenticated — the server does not accept (or does not have) your credentials. A WWW-Authenticate challenge often accompanies it.

403 Forbidden means the server understood the request and still refuses. You may be logged in with the wrong role, missing an OAuth scope, or hitting an IP allowlist. Do not keep refreshing a token when the real issue is permissions.

404 Not Found means no resource matched the method and path. APIs also return 404 for “ID not in the database.” Some systems use 404 deliberately to avoid leaking whether a private object exists — that is a product choice, not a bug in HTTP.

Nearby codes you will hit next

While debugging auth and missing resources, two neighbors show up constantly:

A 500 that appears only after a bad token is still a server bug (it should usually be 401/403). A 429 that appears after a retry storm is often your client’s fault.

Debugging checklist

  1. Note method, path, status, and response body — not just the number.
  2. For 401: confirm scheme (Bearer, Basic, cookie), clock skew on JWTs, and that you are hitting the right environment.
  3. For 403: dump the user’s roles/scopes and the resource ACL; compare with a known-good account.
  4. For 404: verify routing, trailing slashes, case sensitivity, and that the ID was never soft-deleted.
  5. Confirm a CDN or gateway is not rewriting your status (edge 404 for a healthy origin is common after deploys).

Reference on TryDevSnip

Use the TryDevSnip HTTP Status Codes reference as a glossary, then jump to deep pages for 401, 403, 404, 429, and 500. Pages are static HTML; nothing you type into a tool on TryDevSnip is uploaded to our servers for processing.

Related: URL Encode when mangled query strings produce surprising 404s.

FAQ

Is 401 always “not logged in”?

Usually yes in APIs. Some older apps misuse 401 for permission failures — treat the body and your API docs as the source of truth.

Should missing IDs be 404 or 400?

Both appear in the wild. 404 is common for “resource not found”; 400 for validation of the ID format. Document one convention and stick to it.

Can 403 happen without authentication?

Yes. A server can refuse anonymously (or refuse to say whether you are authenticated) and still return 403.

Why do I see 404 after a successful deploy?

CDN path rules, case-sensitive object keys, or the edge never fetched the new object. Check origin first, then cache purge.

← More from the blog

TryDevSnip