HTTP 401 Unauthorized Error: What It Means & How to Fix It

What Is a 401 Unauthorized Error?
A 401 Unauthorized error is an HTTP status code that means the server requires authentication for the requested resource, but the request either did not include credentials or the credentials provided were invalid.
The HTTP specification (RFC 9110, Section 15.5.2) defines it as: the request lacks valid authentication credentials for the target resource. The server generating the 401 response must include a WWW-Authenticate header indicating which authentication scheme to use.
In simple terms: the server is asking "who are you?" before allowing access. Either you did not provide any identification, or the identification you provided was wrong.
What a 401 Error Looks Like
The 401 error appears differently depending on the server, browser, and application. Here are the most common messages you will encounter.
401 Unauthorized — the standard HTTP response message
HTTP Error 401 – Unauthorized — common in IIS and ASP.NET applications
401 Authorization Required — Nginx default error page
Error 401 — short form in browser address bars
Access Denied: Invalid credentials — custom application error pages
Authentication Required — browser popup prompt for Basic/Digest auth
Invalid API Key — common in REST API responses
Token Expired — JWT or OAuth token needs refreshing
When a server sends a 401, most browsers will display a login popup asking for a username and password. If the server uses token-based authentication (like APIs), you will see the error in the JSON response body instead.
401 vs 403: What's the Difference?
The 401 and 403 status codes are frequently confused, even by experienced developers. The distinction is simple: 401 means "I do not know who you are" while 403 means "I know who you are, but you are not allowed."
| 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 |
| Can retrying help? | Yes — provide correct credentials | No — you lack permission |
| WWW-Authenticate header | Required in response | Not included |
| 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
Understanding why a 401 error occurs depends on whether you are a regular user, a developer calling an API, or a server administrator. Here are the most frequent causes.
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 — JWT validation fails when the server and client clocks are out of sync by more than a few minutes
CORS preflight stripping headers — browser removes the Authorization header from preflight OPTIONS requests
Stale browser cache — browser sends a cached, expired session cookie instead of requesting a new one
Reverse proxy misconfiguration — Nginx or Apache strips the Authorization header before forwarding to the backend
Rate-limited or revoked credentials — too many failed attempts triggered account lockout
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 or cached authentication token. Clearing these forces the browser to request fresh credentials from the server.
Chrome: Settings → Privacy → Clear browsing data → Cookies + Cached images
Firefox: Settings → Privacy → Clear Data → Cookies + Cache
Safari: Settings → Privacy → Manage Website Data → Remove All
Edge: Settings → Privacy → Clear browsing data → Cookies + CacheAfter 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.
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. The server's WWW-Authenticate response header tells you exactly which scheme it expects.
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... ← WRONG
# Wrong scheme: Authorization: Basic eyJhbGci... ← WRONGAlways check the WWW-Authenticate header in the 401 response. It tells you exactly what the server expects. Use DNS Robot's HTTP Headers tool to inspect the full response.
6. Check API Key Validity
API keys can silently stop working for several reasons: the key was rotated, the associated account was downgraded, the key hit its rate limit, or it was scoped to different endpoints than you are calling.
Verify your key is still active in the provider's dashboard. Many APIs (Google, AWS, Stripe) let you test the key directly from their console.
# Test if your API key is valid
curl -I -H "Authorization: Bearer YOUR_API_KEY" https://api.example.com/me
# 200 = key is valid
# 401 = key is invalid or expired
# 403 = key is valid but lacks permission for this endpoint
# Check common API key issues:
# 1. Trailing whitespace in .env file: API_KEY="abc123 " ← trailing space
# 2. Wrong environment: using test key on production
# 3. Missing prefix: some APIs need "sk_live_" prefix7. 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.
The fix depends on your authentication flow. OAuth 2.0 uses a refresh token to get a new access token without re-authenticating. JWT-based systems typically require a new login.
# Decode a JWT token to check its expiry (works on macOS and Linux)
echo "eyJhbGciOiJIUzI1NiIs..." | cut -d'.' -f2 | base64 -d 2>/dev/null | python3 -m json.tool
# Look for "exp" field — it's a Unix timestamp
# Compare with current time: date +%s
# OAuth 2.0 refresh token flow
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 browser sends a cross-origin request with an Authorization header, it first sends a preflight OPTIONS request. The browser automatically strips the Authorization header from this preflight. If your server requires auth on the OPTIONS request, it returns 401 before the real request ever fires.
The fix: configure your server to allow OPTIONS requests without authentication on CORS-enabled endpoints.
# Nginx — allow OPTIONS requests without auth
location /api/ {
if ($request_method = OPTIONS) {
add_header Access-Control-Allow-Origin *;
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;
}
# 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, check AuthType and Require directives. On Node.js/Express, check your middleware order — authentication middleware placed before route handlers will block everything.
# 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 servers, .htaccess files can enable Basic or Digest authentication for specific directories. If a .htaccess file exists in a public directory with AuthType directives, every visitor will get 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. Fix Reverse Proxy Header Stripping
If your app sits behind Nginx, Apache, or a load balancer, the proxy may strip the Authorization header before forwarding the request to your backend. This is one of the most frustrating 401 causes because the client sends correct credentials but the server never receives them.
Check your proxy configuration to ensure it passes the Authorization header through.
# Nginx reverse proxy — pass Authorization header to backend
location /api/ {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Authorization $http_authorization; # ← Critical!
proxy_pass_header Authorization; # ← Also add this
}
# Apache reverse proxy
<Location /api/>
ProxyPass http://localhost:3000/api/
ProxyPassReverse http://localhost:3000/api/
RequestHeader set Authorization "expr=%{HTTP:Authorization}" # Pass auth header
</Location>Debugging 401 Errors with HTTP Headers
The fastest way to diagnose a 401 error is to inspect the response headers. The WWW-Authenticate header in the server's response tells you exactly what authentication method is required.
Use DNS Robot's HTTP Headers tool or curl from the terminal to see the full response.
# Check the WWW-Authenticate header in the 401 response
curl -I https://api.example.com/protected-endpoint
# Typical 401 response headers:
# HTTP/1.1 401 Unauthorized
# WWW-Authenticate: Bearer realm="api", error="invalid_token"
# WWW-Authenticate: Basic realm="Admin Area"
# Content-Type: application/json
# The WWW-Authenticate header tells you:
# - The auth scheme (Bearer, Basic, Digest)
# - The realm (which area is protected)
# - The error reason (invalid_token, expired, etc.)Pay close attention to the WWW-Authenticate header. If it says Bearer, you need a token. If it says Basic, you need a username and password. If it includes error=invalid_token, your token exists but is malformed or expired. This single header usually tells you exactly what is wrong.
Does a 401 Error Affect SEO?
A 401 error on public-facing pages will hurt your SEO. When Googlebot encounters a 401, it cannot crawl the page and will eventually drop it from the index.
However, 401 errors on pages that should require authentication (admin panels, user dashboards, API endpoints) are completely normal. Google expects these pages to be protected and will not penalize your site for them.
The problem arises when 401 errors appear on pages that should be publicly accessible. This typically happens when authentication middleware is misconfigured or when a CDN/reverse proxy incorrectly requires credentials on public routes.
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 [HTTP Headers tool](/http-headers) — 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
Check your HTTP response headers
Use DNS Robot's free HTTP Headers tool to inspect any URL's response status, headers, and WWW-Authenticate information instantly.
Try HTTP HeadersFrequently Asked Questions
A 401 Unauthorized error means the server requires authentication but your request did not include valid credentials. You either did not provide a username/password or API key, or the ones you provided were incorrect or expired.