HTTP 401 Unauthorized

Quick answer

HTTP 401 Unauthorized means the request lacks valid authentication credentials. The client must authenticate — log in or send a valid token — before the request will be accepted.

What HTTP 401 means

401 Unauthorized is, despite its name, about authentication: the server does not know who you are. No credentials were sent, or the ones sent are invalid or expired. The response should include a WWW-Authenticate header describing how to authenticate.

Common causes

Example JSON error response

{
  "error": "Unauthorized",
  "message": "Missing or invalid authentication token",
  "status": 401
}

Raw HTTP response

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer
Content-Type: application/json

How to troubleshoot HTTP 401

401 vs 403 — what's the difference?

401 Unauthorized means "who are you?" — you are not authenticated, so log in or send a valid token. 403 Forbidden means "I know who you are, but you can't do this" — you are authenticated but lack permission. If sending valid credentials fixes it, it was a 401; if you have valid credentials but still can't access the resource, it's a 403.

Handling 401 in client code: the token-refresh flow

The standard pattern is an interceptor: when a request comes back 401, try refreshing the access token once, then replay the original request. If the refresh itself 401s, the session is genuinely over — send the user to log in:

async function apiFetch(url, opts = {}) {
  let res = await fetch(url, withAuth(opts));
  if (res.status === 401) {
    const refreshed = await tryRefreshToken();   // exchange refresh token
    if (!refreshed) { redirectToLogin(); return; }
    res = await fetch(url, withAuth(opts));       // replay once
  }
  return res;
}

Guard against infinite loops — only retry once. To see why a token is rejected, decode the JWT and check its exp claim; for whether that's safe to do online, see is it safe to decode a JWT online?

The WWW-Authenticate header

A spec-compliant 401 includes a WWW-Authenticate header telling the client how to authenticate — e.g. WWW-Authenticate: Bearer for token auth or Basic realm="..." for basic auth. If your API omits it, clients (and browsers) can't tell what scheme to use; include it so the 401 is actionable.

Frequently Asked Questions

What is the difference between 401 and 403?

401 Unauthorized means you are not authenticated — no valid credentials were supplied. 403 Forbidden means you are authenticated but lack permission for this resource. 401 is "who are you?", 403 is "you can't do this."

How do I fix a 401 Unauthorized?

Make sure you send a valid Authorization header, that the token has not expired, and that the scheme is correct (usually Bearer). Decoding the token lets you check its expiry. If expired, re-authenticate to get a new one.

Why do I get a 401 with a token that worked yesterday?

The token has most likely expired. JWTs carry an exp claim — decode the token to check it. Tokens are short-lived by design; obtain a fresh one by re-authenticating or refreshing.

Should I retry a 401 automatically?

Retry once, and only after refreshing the token. The pattern is: on 401, exchange your refresh token for a new access token, then replay the original request a single time. If the refresh also fails, the session is over — send the user to log in. Never retry in a loop, or you'll hammer the auth endpoint.

Does a 401 response need a WWW-Authenticate header?

Per the HTTP spec, yes — a 401 should include a WWW-Authenticate header indicating the auth scheme (e.g. Bearer). Many JSON APIs omit it, which still works for custom clients but is technically non-compliant and leaves browsers unable to prompt for credentials.

Working with a JSON API response?

Format and inspect any response in your browser — nothing is uploaded.

JSON Formatter JSON Validator All HTTP Status Codes
About the author

Pasindu Ishan is a software developer based in Sri Lanka. He builds privacy-first developer tools at JSON Dev Tools.