401 Unauthorized 4xx
The request lacks valid authentication credentials for the requested resource.
What does 401 mean?
A 401 Unauthorized response means the request requires authentication, and either no credentials were provided, or the credentials provided are invalid or expired. Despite the name "Unauthorized," this code is really about authentication — proving who you are — not authorization (proving what you're allowed to do, which is 403's job).
A response with a 401 status must include a WWW-Authenticate header, telling the client what kind of authentication scheme is expected (e.g., Basic, Bearer, Digest). This is one of the few status codes with a required accompanying header — its absence technically makes the response non-compliant with the spec, though many APIs skip it in practice.
How a 401 behaves
- It requires the
WWW-Authenticateheader per spec, describing the authentication method the server expects - It's not cacheable — credentials and auth state are request-specific, so caching a 401 would be meaningless (and potentially leak auth requirements to other users in shared caches)
- It's safe to retry — once you have valid credentials, retrying the same request with proper authentication should succeed
- It applies to the request, not the resource — a 401 doesn't necessarily mean the resource exists or doesn't; it means "I don't know who you are, and I need to before I can tell you anything else"
Common causes
If you're building the API or website:
- An endpoint that requires authentication is missing a valid session, token, or API key check — or the check is failing due to a bug
- Token expiration logic is too aggressive, or clock skew between servers causes valid tokens to appear expired
- Authentication middleware is misconfigured or applied to the wrong routes
- A
WWW-Authenticateheader is missing, which can confuse clients about what auth method to use
If you're calling an API:
- Your access token or API key has expired and needs to be refreshed
- The
Authorizationheader is malformed — missing theBearerprefix, wrong casing, extra whitespace - You're using credentials for the wrong environment (e.g., a sandbox/test key against a production endpoint, or vice versa)
- The token was revoked — e.g., a user logged out elsewhere, or an admin revoked API access
If you're a website visitor:
- Your login session expired and you need to sign in again
- You're trying to access a members-only or account-specific page without being logged in
- Cookies are blocked or were cleared, so the server no longer recognizes your session
How to fix it
As an API/website builder:
- Always include a
WWW-Authenticateheader on 401 responses, specifying the expected scheme - Return 401 (not 403, and not a redirect) when authentication is missing or invalid — this gives clients a clear, programmatic signal to re-authenticate
- Implement token refresh flows so short-lived tokens don't force users to fully re-login constantly
- Double-check middleware ordering — authentication checks should run before authorization checks, so a 401 is returned before a 403 would even be evaluated
As an API consumer:
- Check whether your token has expired, and implement a refresh-token flow if the API supports one
- Verify the
Authorizationheader format exactly matches what the API expects (Authorization: Bearer <token>is the most common) - Confirm you're pointing at the right environment (sandbox vs. production) with the matching credentials
As a website visitor:
- Log in again — your session has likely expired
- Make sure cookies are enabled for the site
- If you just changed your password elsewhere, you may need to re-authenticate on this device
401 vs 403 — the classic confusion
This is the single most common point of confusion in all of HTTP, so it's worth being explicit:
| 401 Unauthorized | 403 Forbidden | |
|---|---|---|
| What it's really about | Authentication — "I don't know who you are" | Authorization — "I know who you are, but you can't do this" |
| Typical fix | Log in / provide valid credentials | Nothing the client can do — permissions need to change server-side |
| Required header | WWW-Authenticate |
None |
| Analogy | A locked door with no ID shown | Showing your ID, but it's not on the guest list |
A simple mental model: if logging in (or logging in again) could fix the problem, it's 401. If you're already logged in and the server still won't let you, it's 403.
Real-world examples
Most REST APIs use 401 consistently for missing or invalid API keys/tokens — GitHub's API returns a 401 with a WWW-Authenticate: Basic or similar header when a request is made without valid credentials. Many APIs deliberately distinguish this from 403: a 401 means "try authenticating," while a 403 from the same API means "you're authenticated, but this specific action isn't allowed for your account."
SEO implications
Pages that require authentication and correctly return 401 to unauthenticated crawlers are handled gracefully by search engines — they simply won't index content behind a login wall, which is usually the desired behavior. Problems arise when a site returns a 200 status for a login-required page but shows "please log in" content — this creates a soft-401 situation similar to a soft 404, where search engines may index a useless "please sign in" page instead of nothing at all.
FAQ
What's the difference between 401 and 403?
401 means the server doesn't know who you are (authentication problem) — logging in or providing valid credentials can fix it. 403 means the server knows who you are but won't let you do this (authorization problem) — no amount of re-authenticating with the same account will help.
Why is it called "Unauthorized" if it's really about authentication?
This is a long-standing naming quirk in the HTTP spec. The name predates the more precise authentication/authorization distinction that's now common in security discussions. By the time the terminology evolved, the status code name was already locked in.
Is 401 used for both API keys and user logins?
Yes — 401 is the generic "authentication required or failed" response, whether the credentials are a user's session/login, an API key, a bearer token, or HTTP Basic Auth credentials.
What is the WWW-Authenticate header for?
It tells the client what authentication method the server expects (e.g., Basic, Bearer, Digest), and sometimes additional context like the realm. Browsers use this header to show a native login prompt for Basic auth; APIs use it to tell client libraries how to format credentials.
If I get a 401, will retrying with the same request ever work?
Not with the same credentials — but retrying with updated credentials (a refreshed token, a fresh login) absolutely can and should work. The 401 is specifically inviting you to re-authenticate.
Fun fact
The 401 status code is closely tied to HTTP Basic Authentication, one of the oldest authentication mechanisms on the web — when you see a browser pop up a native username/password dialog box (rather than a styled login form), that's almost always triggered by a 401 response with a WWW-Authenticate: Basic header.