401 Unauthorized & 401 Authorization Required: How to Fix
Key takeaway
HTTP 401 Unauthorized means the server needs you to prove who you are, and your request either didn't or used credentials it rejected. "401 Authorization Required" is the same code on nginx's default page, usually a password-protected area. As a visitor, sign in again with the right details, clear the site's cookies, or ask the owner for access. As a developer, check the Authorization header ("Bearer <token>"), that the key or token hasn't expired, and what the WWW-Authenticate header asks for.
Check it now

Start reading
- What Is a 401 Unauthorized Error?
- What a 401 Error Looks Like
- "401 Authorization Required" on nginx
- 401 vs 403: What's the Difference?
- Common Causes of 401 Errors
- How to Fix 401 as a Visitor
- 1. Check Your Login Credentials
- 2. Clear Browser Cache and Cookies
- 3. Try Incognito or Private Mode
- 4. Verify the URL
- How to Fix 401 as a Developer
- 5. Verify the Authorization Header
- 6. Check API Key Validity
- 7. Handle Token Expiry and Refresh
- 8. Fix CORS Preflight Issues
- How to Fix 401 as a Site Owner
- 9. Review Server Authentication Config
- 10. Check .htaccess Authentication Rules
- 11. Make Sure the Authorization Header Reaches Your App
- Debugging 401 Errors with HTTP Headers
- Does a 401 Error Affect SEO?
- How to Prevent 401 Errors
- Frequently Asked Questions
What Is a 401 Unauthorized Error?
A 401 Unauthorized error means the server needs you to prove who you are, and your request didn't, or the credentials it carried were rejected. No password, a wrong password, an expired token or a missing API key all end the same way.
The HTTP standard defines it as a request that "lacks valid authentication credentials for the target resource", and a server sending a 401 MUST include a WWW-Authenticate header that says which login scheme it accepts (RFC 9110 §15.5.2).
In plain terms, the server is asking "who are you?" before it lets you in.
See a URL's status code and WWW-Authenticate header
What a 401 Error Looks Like
The page you see depends on the server and the app:
- 401 Unauthorized — the standard status line, and most apps' wording
- 401 Authorization Required — the title of nginx's built-in 401 page, with "nginx" (usually with its version) underneath (nginx source); old Apache 2.2 servers use the same words
- Unauthorized · This server could not verify that you are authorized to access the document requested — Apache's default page
- 401 - Unauthorized: Access is denied due to invalid credentials — IIS; the detailed page (shown on the server itself) and the IIS log give the reason as 401.1, 401.2 or 401.3: logon failed, server configuration, or file permissions
- A sign-in box in the browser — when the server asks for HTTP Basic or Digest authentication, or (on IIS and company intranets) NTLM or Negotiate
- This page isn't working · HTTP ERROR 401 — Chrome, when the 401 response has no page of its own
- JSON from an API, such as
{"error":{"message":"Missing Authentication header","code":401}}
Browsers show the sign-in box only for those login schemes. Token-based APIs ("Bearer") never trigger it; their 401 comes back as JSON for the app to handle. Websites with a login form usually send a signed-out visitor to the login page with a 302 redirect instead of a 401.
"401 Authorization Required" on nginx
That title comes from nginx's built-in 401 page. You get it when a location is protected with auth_basic and the request carried no username and password, or the wrong ones; cancelling the browser's sign-in box shows this page too.
As a visitor, reload and enter the username and password the site's owner gave you. They're separate from any account on the site: Basic authentication checks a password file on the server.
As the site's owner, this is how the protection is set up, and how to keep a path public:
# Create the password file (htpasswd comes with apache2-utils or httpd-tools)
# sudo htpasswd -c /etc/nginx/.htpasswd alice # -c creates the file: leave it out when adding users
location /admin/ {
auth_basic "Admin area";
auth_basic_user_file /etc/nginx/.htpasswd;
}
# Inside a protected server block, open one path to everyone
location /public/ {
auth_basic off;
}
# Test, then reload
# curl -I -u alice:PASSWORD https://example.com/admin/
# sudo nginx -t && sudo systemctl reload nginxStill 401 with the right password? Check that the user is in the file (htpasswd -c overwrites the file, removing earlier users), and that the app behind nginx doesn't need the Authorization header too: nginx's Basic login and an app's Bearer tokens both use it, so the app receives nginx's credentials and rejects them.
401 vs 403: What's the Difference?
The 401 and 403 codes are often confused. The short version: 401 means "I don't know who you are", while 403 means "I won't let you in", whether or not your identity is the problem.
| Aspect | 401 Unauthorized | 403 Forbidden |
|---|---|---|
| Core meaning | Authentication failed or missing | Authorization denied |
| The server's question | "Who are you?" | "You do not have permission" |
| Credentials | Not provided or invalid | Valid but insufficient, or not the issue (IP block, firewall, file permissions) |
| Can retrying help? | Yes, with the right credentials | Not with the same credentials |
| WWW-Authenticate header | Required by the spec (many APIs skip it) | Optional (e.g. Bearer error="insufficient_scope") |
| Example scenario | Accessing admin panel without logging in | Logged in as viewer, trying to delete posts |
A practical rule: if providing the right username and password (or API key) would fix it, the server should return 401. If the user is already authenticated but simply does not have access to that resource, the server should return 403 Forbidden.
Common Causes of 401 Errors
The causes, from the visitor's side to the server's:
- Wrong username or password — the most basic cause, especially after a password reset
- Expired authentication token — JWT tokens, OAuth access tokens, and session cookies all have expiry times
- Missing Authorization header — the request did not include any credentials at all
- Invalid API key — the key was revoked, rotated, or copied incorrectly
- Incorrect auth scheme — server expects Bearer token but received Basic auth, or vice versa
- Clock skew — the server that checks a JWT and the one that issued it (or your machine, if it signs the JWT) disagree on the time; many libraries allow no leeway at all
- A CORS preflight — the browser's OPTIONS check never carries credentials, so a server that demands them answers 401 and the real request is never sent
- A stale session — the browser sends a session cookie the server has already ended
- Something in between drops the header — Apache hides Authorization from PHP-FPM and CGI scripts unless told otherwise, CloudFront removes it from GET and HEAD requests by default, and nginx Basic auth in front of an app takes it over
- Locked or revoked credentials — too many failed attempts can lock an account (some APIs answer that with 429 Too Many Requests instead)
How to Fix 401 as a Visitor
If you encounter a 401 error on a website you are trying to access, the issue is almost always related to your login credentials. Follow these steps in order.
1. Check Your Login Credentials
The most common cause of a 401 error is simply wrong credentials. If the site shows a login popup or form, double-check your username and password.
Common mistakes: Caps Lock is on, you are using an old password (especially after a recent reset), or you are logging into the wrong account. If you have a password manager, let it auto-fill the credentials to avoid typos.
2. Clear Browser Cache and Cookies
Your browser may be sending an expired session cookie. Deleting the site's cookies makes it ask for a fresh login.
Chrome, Edge, Firefox: Ctrl+Shift+Delete (Cmd+Shift+Delete on a Mac)
→ Time range: All time → Cookies and site data + Cached files → Delete / Clear
(this signs you out of every site; the per-site option below doesn't)
Safari: Settings → Privacy → Manage Website Data → the site → Remove
One site in Chrome: the icon left of the address → Site settings → Delete dataAfter clearing, close the browser completely (not just the tab), reopen it, and navigate to the page again. You should see a fresh login prompt.
3. Try Incognito or Private Mode
Open the URL in an incognito (Chrome) or private (Firefox/Safari) window. This bypasses all cached cookies, extensions, and stored credentials.
If the page works in incognito but not in your regular browser, the problem is a cached cookie or a browser extension interfering with authentication. Disable extensions one by one to find the culprit.
4. Verify the URL
Make sure you are visiting the correct URL. Some servers return 401 for paths that require authentication, even if the path itself is wrong. You might be trying to access a restricted area you were not meant to visit.
Check if there is a public version of the page at a different URL. For example, example.com/admin/ might return 401 while example.com/ is publicly accessible.
Not sure the site works at all? The Website Down Checker opens it from 11 places, so you can tell a login problem from an outage.
How to Fix 401 as a Developer
For developers working with APIs, 401 errors are usually about the Authorization header, token format, or credential lifecycle. These are the most common fixes.
5. Verify the Authorization Header
The most common developer mistake is a malformed Authorization header. When the server sends a WWW-Authenticate header, it names the scheme it expects; many JSON APIs (GitHub's and OpenRouter's, for example) leave it out and explain the problem in the response body instead.
Check that your header matches the required format. The most common schemes are Bearer (for tokens) and Basic (for username:password encoded in Base64).
# Bearer token authentication (most APIs)
curl -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." https://api.example.com/data
# Basic authentication (username:password in Base64)
curl -u "username:password" https://api.example.com/data
# Equivalent to:
curl -H "Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=" https://api.example.com/data
# Common mistakes that cause 401:
# Missing "Bearer " prefix: Authorization: eyJhbGci... ← WRONG
# Extra space: Authorization: Bearer eyJ... ← many servers reject it
# Wrong scheme: Authorization: Basic eyJhbGci... ← WRONGThen read the WWW-Authenticate header in the 401 response: it names the scheme the server expects. DNS Robot's HTTP Header Checker shows the full response.
6. Check API Key Validity
API keys stop working when the key is rotated or revoked, the account is suspended or downgraded, or a test key is used against production. (A rate limit answers 429, and a key without access to an endpoint usually gets 403.)
Check that the key is still active in the provider's dashboard, then test it directly:
# Test a key: print only the status code (a real GET; some APIs reject HEAD)
curl -s -o /dev/null -w "%{http_code}\n" -H "Authorization: Bearer YOUR_API_KEY" https://api.example.com/me
# 200 = the key works
# 401 = the key is missing, wrong, revoked or expired
# 403 = the key works but isn't allowed to use this endpoint
# Common slips:
# 1. A space or newline after the key in .env: API_KEY="abc123 "
# 2. The test key in production, or the reverse
# 3. An empty variable, so the header is just "Authorization: Bearer"7. Handle Token Expiry and Refresh
JWT tokens and OAuth access tokens have a limited lifetime — typically 15 minutes to 24 hours. When they expire, every API call returns 401 until you get a fresh token.
If you have a refresh token (OAuth 2.0 and most JWT setups), exchange it for a new access token; without one, sign in again.
# Read a JWT's payload (tokens use base64url, so plain base64 -d often fails)
python3 -c 'import sys,base64,json; p=sys.argv[1].split(".")[1]; print(json.dumps(json.loads(base64.urlsafe_b64decode(p+"==")),indent=2))' "$TOKEN"
# "exp" is a Unix timestamp; compare it with: date +%s
# OAuth 2.0: get a new access token with the refresh token
curl -X POST https://auth.example.com/token \
-d "grant_type=refresh_token" \
-d "refresh_token=YOUR_REFRESH_TOKEN" \
-d "client_id=YOUR_CLIENT_ID"8. Fix CORS Preflight Issues
When a web page calls an API on another domain with an Authorization header, the browser first sends a preflight OPTIONS request, and the preflight never carries credentials. If the server demands authentication on OPTIONS, it answers 401, the preflight fails, and the browser reports a CORS error: the real request is never sent.
The fix: let OPTIONS requests through without authentication on CORS-enabled endpoints.
# Nginx — allow OPTIONS requests without auth
location /api/ {
if ($request_method = OPTIONS) {
add_header Access-Control-Allow-Origin https://app.example.com;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
add_header Access-Control-Allow-Headers "Authorization, Content-Type";
add_header Access-Control-Max-Age 86400;
return 204;
}
# CORS header on every other answer, the 401 included, or the browser reports a CORS error
add_header Access-Control-Allow-Origin https://app.example.com always;
# Normal auth for other methods
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;
}How to Fix 401 as a Site Owner
If your visitors or users are reporting 401 errors, the problem is in your server's authentication configuration. Work through these checks.
9. Review Server Authentication Config
Check that authentication is only enabled on the routes that need it. A common mistake is protecting an entire directory or site when only specific paths should require login.
On nginx, check your auth_basic directives; on Apache, AuthType and Require. On Node.js/Express, check your middleware order: an app.use(auth) registered before your public routes protects them too, so register public routes first or attach auth only to the protected router.
# Nginx — WRONG: protects everything, including public pages
server {
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;
# All pages now require login — including your homepage!
}
# Nginx — CORRECT: only protect admin routes
server {
location / {
# Public — no auth required
}
location /admin/ {
auth_basic "Admin Area";
auth_basic_user_file /etc/nginx/.htpasswd;
}
}10. Check .htaccess Authentication Rules
On Apache, .htaccess files can turn on Basic or Digest authentication for a directory. If a public directory has a .htaccess with AuthType and Require directives, every visitor gets a 401 login prompt.
Check for .htaccess files in the affected directory and all parent directories — Apache applies rules from every .htaccess in the path.
# Find all .htaccess files with auth rules
find /var/www/html -name '.htaccess' -exec grep -l 'AuthType\|AuthUserFile\|Require valid-user' {} \;
# Example .htaccess that causes 401 for everyone:
# AuthType Basic
# AuthName "Restricted Area"
# AuthUserFile /etc/apache2/.htpasswd
# Require valid-user
# Fix: remove auth lines from public directories,
# or move them to the specific /admin/.htaccess only11. Make Sure the Authorization Header Reaches Your App
The client sends correct credentials, but the app never sees them. Where the header gets lost:
nginx forwards Authorization to the backend by default, so you don't need extra lines; but if the same location uses auth_basic, nginx's login takes over the header (see the nginx section above). Apache hides Authorization from PHP-FPM and CGI scripts unless you turn on CGIPassAuth (Apache 2.4.13+), the classic cause of 401s in WordPress and Laravel APIs behind Apache.
# Apache 2.4.13+ (inside a <Directory> block, or .htaccess): pass Authorization to PHP-FPM and CGI
CGIPassAuth On
# Older Apache: copy it into an environment variable instead
SetEnvIf Authorization "(.+)" HTTP_AUTHORIZATION=$1Debugging 401 Errors with HTTP Headers
The fastest way to diagnose a 401 is to read the response: the WWW-Authenticate header, when the server sends it, says which login it wants, and JSON APIs usually explain the error in the body.
Use DNS Robot's HTTP Header Checker (if the 401 only appears after a redirect, the Redirect Checker shows which hop answers it), or curl from a terminal:
# Print the response headers of a real GET
curl -sS -D - -o /dev/null https://api.example.com/protected-endpoint
# A 401 often carries one of:
# WWW-Authenticate: Bearer realm="api", error="invalid_token"
# WWW-Authenticate: Basic realm="Admin Area"
# It tells you:
# - the scheme (Bearer, Basic, Digest, Negotiate)
# - the realm (which area is protected)
# - for Bearer tokens, the error: invalid_request, invalid_token or insufficient_scopeIf WWW-Authenticate says Bearer, you need a token; if it says Basic, a username and password. error="invalid_token" means the token is expired, revoked, malformed or otherwise invalid. No header at all? Read the response body: many APIs put the reason there.
Does a 401 Error Affect SEO?
A 401 on a public page takes it out of Google. Google treats every 4xx code except 429 the same way: the crawler reports that the content doesn't exist, and an indexed URL is removed (Google's crawler documentation).
401s on pages that should need a login (admin panels, dashboards, APIs) are normal: Google doesn't penalize a site for them. Just don't use 401 or 403 to slow Googlebot down; Google says they have no effect on crawl rate.
The problem is a 401 on pages that should be public, usually from authentication applied to a whole site, or a CDN or proxy rule asking for credentials on public paths.
How to Prevent 401 Errors
Prevention saves you from debugging later. Follow these practices to minimize 401 errors in your applications and websites.
- Implement token auto-refresh — use refresh tokens to silently get new access tokens before they expire
- Set proper auth scopes — only protect routes that genuinely need authentication, keep public pages open
- Use clear error messages — return helpful JSON error bodies alongside 401, not just the status code
- Monitor auth failures — set up alerts for spikes in 401 responses, which may indicate credential issues or attacks
- Sync server clocks — use NTP to keep all servers within a few seconds of UTC, preventing JWT clock-skew rejections
- Test with the HTTP Header Checker — regularly verify that public pages return 200 and protected pages return 401 as expected
- Document your auth scheme — make the expected Authorization header format clear in your API documentation
- Handle CORS preflight — always allow OPTIONS requests without authentication on API endpoints
See the 401 and its WWW-Authenticate header
DNS Robot's free HTTP Header Checker shows any URL's status code and response headers, including WWW-Authenticate, which names the login scheme the server expects.
Sources
Frequently Asked Questions
What does a 401 error mean?
What does "401 Authorization Required" mean?
What is the difference between 401 and 403?
How do I fix a 401 Unauthorized error?
Why am I getting 401 on my API call?
What does "proxy error 401: Missing Authentication header" mean?
What is the WWW-Authenticate header?
Can a 401 error be caused by CORS?
How do I check if my token is expired?
Why does my browser show a login popup for 401?
Related Articles
Related Tools
HTTP Header Checker
Response headers exactly as sent, with a Mozilla Observatory security grade
Redirect Checker
Follow every redirect hop by hop: 301/302 chains, timing and bulk checks
SSL Certificate Check
Verify SSL certificate validity and security details
Website Down Checker
Is it down for everyone or just you? Check any site from 11 places and your own connection, with a live screenshot



