401 Unauthorized: what it means, 401 vs 403, and how to fix it
Vikas Chamarthi, Founder · Updated
A 401 Unauthorized error means the request was not processed because it didn't carry valid authentication credentials. The resource may exist and you may be allowed to see it, but the server first needs to know who you are. Sign in, or send a valid API key or token, and the request can succeed. The name is misleading: 401 is about authentication (who you are), while 403 Forbidden is about authorization (what you may do).
The HTTP specification defines it this way: "The 401 (Unauthorized) status code indicates that the request has not been applied because it lacks valid authentication credentials for the target resource. The server generating a 401 response MUST send a WWW-Authenticate header field (Section 11.6.1) containing at least one challenge applicable to the target resource" (RFC 9110, section 15.5.2).
If credentials were sent, the 401 means "authorization has been refused for those credentials", and the client "MAY repeat the request with a new or replaced Authorization header field."
401 vs 403
| 401 Unauthorized | 403 Forbidden | |
|---|---|---|
| The question it answers | Who are you? | Are you allowed? |
| Credentials | Missing, invalid or expired | Understood, but insufficient, or the refusal has nothing to do with credentials |
| Will signing in help? | Usually yes | Usually no |
| Required header | WWW-Authenticate with at least one challenge | None |
| How Google Search treats it | Not indexed; removed if indexed | The same |
RFC 9110 describes 403 as a server that "understood the request but refuses to fulfill it", and says that if credentials were provided, "the server considers them insufficient to grant access" (section 15.5.4).
Common causes
- No credentials were sent. The user isn't signed in, or the client code forgot the
Authorizationheader. - The token or session expired. Access tokens and session cookies have lifetimes; the client needs to refresh them.
- The token is malformed. AWS lists the cases its Application Load Balancer rejects with 401 when it validates JWTs, including a header that "lacks the 'Bearer' prefix", one that "contains a different authentication type (e.g., 'Basic')", and a request with multiple tokens (ALB troubleshooting).
- The header was lost on the way. A proxy, a CDN rule or a redirect to another host can drop the
Authorizationheader before it reaches the application. - An access layer in front of the app. Cloudflare notes that a 401 on a website "usually comes from the origin server", but that Cloudflare Access can also return one in some cases, such as AJAX requests with expired sessions. To tell them apart, "check whether the request reached your origin server's logs" (Cloudflare error 401).
How to diagnose a 401, step by step
-
Look at the
WWW-Authenticateheader. It names the authentication scheme the server expects and often an error:curl -i https://api.example.com/v1/me -H "Authorization: Bearer $TOKEN"Cloudflare's advice for its own API applies to any API: if the error persists, "refer to the
WWW-Authenticateheader in the response for guidance." -
Confirm the header arrives. Log the incoming headers at the application, or call the application directly without the proxy in front of it. If the header is present at the edge but missing at the app, a proxy or redirect is dropping it.
-
Decode the token. For a JWT, check the expiry (
exp), audience (aud) and issuer (iss) against what the server expects. -
Check the clock. A server whose clock is wrong can reject tokens that are still valid.
How to return a 401 correctly
nginx with HTTP Basic authentication
nginx's auth_basic module "enables validation of user name and password using the 'HTTP Basic Authentication' protocol", and the example in its documentation is this (nginx auth_basic):
location / {
auth_basic "closed site";
auth_basic_user_file conf/htpasswd;
}
nginx sends the WWW-Authenticate challenge for you, so browsers show a sign-in prompt. This is a simple way to keep a staging site private.
Next.js (App Router)
Next.js has an unauthorized() function that "throws an error that renders a Next.js 401 page", and it "also injects a <meta name="robots" content="noindex" /> tag so the page is not indexed". It is experimental, so you have to enable authInterrupts in next.config.js first (Next.js docs):
// next.config.ts
const nextConfig = {
experimental: {
authInterrupts: true,
},
}
export default nextConfig
APIs
Return 401 when credentials are missing or invalid, and 403 when a signed-in user lacks permission for the action. Include a WWW-Authenticate header naming your scheme (for example Bearer), as RFC 9110 requires, so clients know how to authenticate.
How 401 errors affect Google Search
A page that returns 401 to Googlebot isn't indexed. Google's documentation lists 401 with the other client errors: "Google doesn't index URLs that return a 4xx status code", and URLs that were already indexed "are removed from the index" (Google Search Central). Search Console reports these URLs as "Blocked due to unauthorized request (401)" (Page indexing report).
That is what you want for dashboards, account pages and staging sites. Two cases cause problems:
- Public pages behind authentication by mistake. A staging password copied to production, or a plugin that protects more paths than intended. Check your important URLs from a logged-out browser or with
curl. - Using 401 to throttle crawlers. Google says "don't use
401and403status codes for limiting the crawl rate", because 4xx codes other than 429 have no effect on crawl rate. If you need Googlebot to slow down, see 429 Too Many Requests.
Check what your pages return to a client with no cookies using the redirect checker, which also shows whether a redirect chain ends at a login page.
For every status code and how Google handles it, see HTTP status codes.
Questions
- What is the difference between 401 and 403?
- 401 means the request has no valid credentials: sign in, or send a valid token, and you may get access. 403 means the server understood the request and refuses it; if credentials were sent, the server considers them insufficient. In short, 401 asks who you are, and 403 says you aren't allowed.
- Why does my API return 401 when I'm sending a token?
- The token is missing from the request the server actually receives, malformed, expired or signed for a different audience. Common causes are a header stripped by a proxy or redirect, a missing 'Bearer ' prefix, and a token copied with extra whitespace. Read the WWW-Authenticate header in the response, which often names the problem.
- Does a 401 hurt SEO?
- Pages that return 401 to Googlebot are not indexed, and indexed ones are removed. That is correct for account pages and staging sites. It is a problem when public pages return 401 by mistake, which Search Console reports as 'Blocked due to unauthorized request (401)'.
- Can I use 401 to slow down Googlebot?
- No. Google says not to use 401 or 403 to limit crawl rate, because 4xx codes other than 429 have no effect on how fast it crawls. They only remove the URLs from the index.
- Is it safe to protect a staging site with HTTP authentication?
- Yes, and it is a good way to keep staging out of search. Crawlers don't have your credentials, so they get a 401 and the pages stay out of the index. Make sure the authentication isn't copied to production when you deploy.
Related
HTTP status codes explained: the five classes, the 16 codes you will actually see, and what Google Search does with each one when it crawls your site.
403 Forbidden: what it means, why it happens and how to fix it403 Forbidden means the server understood the request and refuses it. Find the cause (permissions, index file, firewall bot rules, IP blocks) and the fix.
400 Bad Request: what it means, why it happens and how to fix itA 400 Bad Request means the server won't process a request it sees as malformed. The usual causes are oversized cookies, bad URLs and invalid API calls.
429 Too Many Requests: what it means and how to fix itA 429 Too Many Requests means a client hit a rate limit. How to back off as an API client, how to set limits as a server, and how to avoid throttling Googlebot.
See where you stand in Google and AI answers
Starter is $19 a month for one site, with a 14-day free trial and no card to start.