HTTP 401 Unauthorized Error: Complete Diagnosis and Fix Guide
The HTTP 401 Unauthorized status code means the server received your request but refuses to process it because valid authentication credentials were either absent, incorrect, or expired. Unlike a 403 Forbidden error — where the server recognizes you but denies access based on permissions — a 401 specifically signals an authentication failure: the server does not know who you are, or cannot verify it.
This distinction matters. A 401 response always includes a WWW-Authenticate header in the server's reply, instructing the client which authentication scheme to use. If that header is missing, you may be dealing with a misconfigured server rather than a credential problem. Knowing the exact failure mode before you start troubleshooting saves significant time.
What a 401 Response Actually Looks Like
The error surfaces under several message variants depending on the server software, framework, or CDN in front of the application:
401 UnauthorizedHTTP Error 401 – Unauthorized401 Unauthorized: Access is denied due to invalid credentialsAuthorization Required401 Authorization Required(common in NGINX)HTTP 401(API clients, Postman, curl)
All of these map to the same RFC 9110-defined status code. The variation in wording is purely cosmetic — driven by the web server, reverse proxy, or application framework generating the response.
The Technical Anatomy of a 401 Error
Understanding what happens at the protocol level prevents guesswork. When a client sends a request to a protected resource without credentials, the server responds with:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="example", error="invalid_token"
Content-Type: application/jsonThe WWW-Authenticate header is the server's challenge. It tells the client exactly which scheme — Basic, Bearer, Digest, NTLM, or a custom scheme — is required. A client that ignores this header and retries without adjusting its request will loop indefinitely.
401 vs. 403 vs. 407: Knowing the Difference
| Status Code | Name | Root Cause | `WWW-Authenticate` Header |
|---|---|---|---|
| — | — | — | — |
| 401 | Unauthorized | Missing or invalid authentication credentials | Required by spec |
| 403 | Forbidden | Authenticated but lacks permission | Not present |
| 407 | Proxy Auth Required | Proxy server requires credentials | `Proxy-Authenticate` header |
| 511 | Network Auth Required | Captive portal (hotel Wi-Fi, etc.) | Not applicable |
Misidentifying a 403 as a 401 is a common developer error. If your server returns 401 but omits WWW-Authenticate, it is technically non-compliant with RFC 9110 — and some strict HTTP clients will treat the response as malformed.
Root Causes of a 401 Unauthorized Error
Credential and Token Problems
- Incorrect username or password — the most frequent cause for browser-based access
- Expired access tokens — OAuth 2.0 Bearer tokens have a finite
expires_invalue; once elapsed, every request returns 401 until the token is refreshed - Revoked API keys — keys can be invalidated server-side without the client being notified
- JWT signature mismatch — if the signing secret rotates and the client holds a token signed with the old secret, verification fails silently
- Clock skew — JWTs include
iat(issued at) andexp(expiry) claims validated against server time; a client clock drifted more than a few minutes can cause valid tokens to be rejected
Missing or Malformed Authorization Headers
Every authentication scheme has a precise header format. Deviating from it — even by a single space or incorrect Base64 padding — produces a 401:
# Correct Basic Auth header
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
# Correct Bearer token header
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...A common mistake is sending Authorization: bearer <token> (lowercase b). While RFC 6750 states the scheme name is case-insensitive, many server-side libraries perform strict string matching and reject the lowercase variant.
Server-Side Misconfiguration
- Wrong authentication method enforced — a server configured for OAuth 2.0 receiving Basic Auth headers will reject them
.htaccessdirectives — on Apache, a misconfiguredAuthType,AuthName, orRequiredirective in.htaccesswill gate every request behind a password prompt- NGINX
auth_basicblocks — anauth_basicdirective applied to the wronglocationblock can lock out legitimate users - Reverse proxy stripping headers — load balancers and reverse proxies (NGINX, HAProxy, Cloudflare) can strip or rewrite
Authorizationheaders before they reach the origin server
Browser and Client-Side Interference
- Corrupted cookies — session cookies carrying authentication state can become corrupted or mismatched after a server-side session invalidation
- Aggressive browser extensions — ad blockers, privacy extensions, and VPN extensions can modify or strip request headers
- CORS preflight failures — in cross-origin API calls, the browser sends an
OPTIONSpreflight request; if the server does not respond correctly to it, the actual authenticated request never fires
Infrastructure and Network Factors
- Firewall rules blocking authentication endpoints — WAFs (Web Application Firewalls) with overly aggressive rules can flag and drop requests containing
Authorizationheaders as potential injection attacks - CDN caching authenticated responses — if a CDN caches a 401 response and serves it to subsequent users, even valid credentials will appear to fail
- IP-based rate limiting — repeated failed authentication attempts can trigger a temporary block that returns 401 for all requests from that IP
How to Fix a 401 Error: Step-by-Step
For End Users and Browser Access
Step 1: Verify credentials precisely
Check that Caps Lock is off. Confirm you are using the current password — not one saved before a recent reset. If your account uses multi-factor authentication (MFA), ensure the one-time code has not expired (TOTP codes are valid for 30 seconds by default).
Step 2: Clear browser cookies and cache
Stale session cookies are a persistent source of 401 loops. In Chrome, navigate to chrome://settings/clearBrowserData, set the time range to All time, check Cookies and other site data and Cached images and files, then clear. In Firefox, use about:preferences#privacy and click Clear Data.
After clearing, close all browser tabs for the affected domain before retrying — some browsers maintain in-memory session state that survives a cache clear if the tab remains open.
Step 3: Test in a private/incognito window
A private window starts with no cookies, no cached data, and most extensions disabled. If the 401 disappears in incognito mode, the problem is definitively client-side: either a corrupt cookie, a cached bad response, or a browser extension.
Step 4: Disable extensions selectively
Navigate to chrome://extensions/ and disable all extensions. Reload the page. If authentication succeeds, re-enable extensions one at a time to isolate the culprit. Privacy Badger, uMatrix, and certain VPN extensions are frequent offenders.
Step 5: Check the URL for errors
Ensure you are not navigating to a path that requires elevated permissions. A URL like /admin/dashboard will return 401 if your session lacks admin privileges — even if your basic login is valid. Verify the exact path with the site owner or documentation.
Step 6: Reset your password
If credential expiry is suspected, use the Forgot Password flow. After resetting, clear cookies again before attempting login — the old session cookie may conflict with the new credential state.
For Developers and API Integrations
Step 7: Inspect the raw HTTP response
Before changing anything, capture the exact server response using curl with verbose output:
curl -v -H "Authorization: Bearer YOUR_TOKEN" https://api.example.com/endpointThe -v flag shows both request headers sent and response headers received, including the WWW-Authenticate challenge. This tells you precisely which scheme the server expects.
Step 8: Validate token state
For JWT tokens, decode the payload without verifying the signature to inspect claims:
echo "YOUR_JWT_PAYLOAD_BASE64" | base64 --decode | python3 -m json.toolCheck the exp field (Unix timestamp). Compare it against current time:
date +%sIf exp is less than the current timestamp, the token is expired. Implement a refresh flow using your OAuth provider's token endpoint before the token reaches expiry.
Step 9: Audit server-side authentication configuration
On Apache, inspect the relevant .htaccess or virtual host configuration:
AuthType Basic
AuthName "Restricted Area"
AuthUserFile /etc/apache2/.htpasswd
Require valid-userConfirm the AuthUserFile path exists and is readable by the web server process. On NGINX, check the relevant server or location block:
location /secure/ {
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;
}Verify the .htpasswd file contains the correct hashed credentials. Use htpasswd -v /etc/nginx/.htpasswd username to test a password against the stored hash.
Step 10: Check server logs
Server logs provide the ground truth. On Apache:
tail -f /var/log/apache2/error.log | grep 401On NGINX:
tail -f /var/log/nginx/error.log | grep 401For application-level authentication (Node.js, Django, Laravel), check the application's own log output. The log entry will often specify whether the failure was a missing header, an invalid token, or a database lookup failure.
Step 11: Verify reverse proxy header forwarding
If your application sits behind NGINX acting as a reverse proxy, ensure the Authorization header is forwarded to the upstream application:
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Authorization $http_authorization;
proxy_pass_header Authorization;
}Without proxy_pass_header Authorization, NGINX strips the header before it reaches your application server — causing a 401 that looks like a client error but is entirely infrastructure-caused.
Step 12: Inspect WAF and firewall rules
If you are running a WAF (ModSecurity, Cloudflare WAF, AWS WAF), check whether any rule is matching and blocking requests containing Authorization headers. Temporarily set the WAF to detection-only mode and retry. If the 401 disappears, refine the offending rule rather than disabling the WAF entirely.
Step 13: Audit CDN caching behavior
Ensure your CDN is not caching 401 responses. In Cloudflare, set a Cache Rule to bypass cache for authenticated endpoints. In AWS CloudFront, configure the behavior to forward the Authorization header to the origin — by default, CloudFront strips it, which means your origin never receives credentials and always returns 401.
Implementing Robust Authentication: Best Practices for Server Owners
If you manage a web application or API — whether on a VPS Hosting environment or a Dedicated Server — these practices prevent 401 errors from reaching your users in the first place.
Token Lifecycle Management
Never issue tokens without a defined expiry. For OAuth 2.0, use short-lived access tokens (15–60 minutes) paired with long-lived refresh tokens. Implement proactive token refresh: trigger a refresh when the access token has less than 20% of its lifetime remaining, not after it has already expired.
Access Token TTL: 15 minutes
Refresh Token TTL: 30 days (rotated on each use)
Refresh trigger: < 3 minutes remaining on access tokenFor JWT-based systems, implement key rotation with a grace period. When rotating the signing secret, keep the old secret valid for one additional token lifetime so in-flight tokens are not immediately invalidated.
Meaningful Error Responses
A 401 response should always include a body that helps the client understand what to do next:
{
"error": "invalid_token",
"error_description": "The access token expired at 2024-01-15T10:30:00Z",
"error_uri": "https://api.example.com/docs/authentication"
}Vague 401 responses that return only a status code force developers to guess the failure reason, dramatically increasing support burden.
Authentication Logging and Alerting
Log every authentication failure with sufficient context: timestamp, IP address, user agent, requested resource, and failure reason. Set up alerts for anomalous patterns — a spike in 401s from a single IP indicates either a misconfiguration or a credential stuffing attack. Platforms running on Dedicated Servers have full access to system-level logs and can implement custom alerting pipelines without restriction.
Secure Credential Transmission
Authentication credentials must only travel over encrypted connections. If your application handles user logins, an SSL Certificate is non-negotiable — transmitting Basic Auth credentials over plain HTTP exposes Base64-encoded usernames and passwords in cleartext on the wire.
API Key Scoping and Rotation
Issue API keys with the minimum required scope. Implement a key rotation policy and provide clients with a rotation mechanism that allows them to swap keys without downtime. Revoke compromised keys immediately and notify affected clients through a documented channel.
Testing Authentication Flows in CI/CD
Integrate authentication flow tests into your deployment pipeline. A test suite that exercises valid credentials, expired tokens, missing headers, and revoked keys will catch regressions before they reach production. This is especially critical after dependency updates that touch authentication middleware.
401 Errors in Specific Environments
WordPress
WordPress returns 401 on its REST API (/wp-json/) when Application Passwords are misconfigured or when a security plugin (Wordfence, iThemes Security) blocks REST API access. Check Settings > Permalinks and resave — this flushes rewrite rules that can break authentication endpoints. If you manage WordPress on a VPS with cPanel, verify that mod_rewrite is enabled and that .htaccess is writable.
cPanel and Web Hosting Control Panels
Password-protected directories configured through cPanel use Apache's mod_authn_file. If the .htpasswd file path in the generated .htaccess is absolute and the document root changes (common after account migrations), the path breaks and every request returns 401. Always use relative paths or verify absolute paths after any migration. Environments using VPS Control Panels provide direct file system access to correct these paths without opening a support ticket.
Email Clients and SMTP Authentication
SMTP servers return a protocol-level equivalent of 401 (535 Authentication credentials invalid) when email client credentials are wrong or when the server requires STARTTLS and the client attempts plain authentication. If you are configuring Email Hosting, ensure your mail client is configured with the correct authentication method (PLAIN, LOGIN, or CRAM-MD5) and that TLS is enforced before credentials are transmitted.
Mobile Applications
Mobile apps frequently encounter 401 errors after a user changes their password on the web — the app's stored refresh token is invalidated server-side but the app has no mechanism to detect this until the next API call fails. Implement a global HTTP interceptor that catches 401 responses, attempts a token refresh exactly once, and if the refresh also returns 401, redirects the user to the login screen with a clear message.
Decision Matrix: Diagnosing Your 401 Error
| Symptom | Most Likely Cause | First Action |
|---|---|---|
| — | — | — |
| 401 on all requests, including previously working ones | Token expired or revoked | Inspect token `exp` claim; trigger refresh |
| 401 only in browser, not in curl | Corrupt cookie or extension interference | Clear cookies; test in incognito |
| 401 only from specific IP | Firewall rate limit or IP block | Check WAF logs; whitelist if legitimate |
| 401 after server migration | `.htpasswd` path broken | Verify `AuthUserFile` path in `.htaccess` |
| 401 on OPTIONS preflight | CORS misconfiguration | Add `Authorization` to `Access-Control-Allow-Headers` |
| 401 despite correct credentials | Reverse proxy stripping headers | Add `proxy_pass_header Authorization` to NGINX config |
| 401 on CDN-cached resources | CDN serving cached 401 response | Bypass cache for authenticated routes |
| 401 after dependency update | Auth middleware breaking change | Review changelog; check header parsing logic |
Practical Checklist Before Escalating a 401 Error
Use this checklist before filing a support ticket or escalating to your infrastructure team:
- Captured the raw HTTP response with
curl -vand confirmed theWWW-Authenticateheader value - Decoded the JWT or token and verified the
expclaim against current server time - Confirmed the
Authorizationheader format matches the scheme the server advertises - Tested in an incognito window with all extensions disabled
- Cleared all cookies and cache for the affected domain
- Checked server error logs for the specific rejection reason
- Verified the reverse proxy configuration is forwarding the
Authorizationheader - Confirmed the CDN is not caching the 401 response
- Checked WAF rules for false-positive matches on the
Authorizationheader - Verified SSL/TLS is active on the endpoint — credentials should never travel unencrypted
FAQ
What is the difference between HTTP 401 and HTTP 403?
A 401 means the server cannot identify who you are — authentication is missing or invalid. A 403 means the server knows who you are but has decided you do not have permission to access the resource. Fix a 401 by providing or correcting credentials; fix a 403 by adjusting access control rules or permissions.
Why does my API return 401 even when I send the correct token?
The most common causes are token expiry (check the exp claim), clock skew between client and server (synchronize NTP), a rotated signing secret invalidating existing tokens, or the Authorization header being stripped by a reverse proxy or CDN before reaching the origin server.
Can a 401 error be caused by server misconfiguration rather than client error?
Yes. A misconfigured .htaccess file, an NGINX auth_basic block applied to the wrong location, a reverse proxy stripping the Authorization header, or a WAF rule blocking authenticated requests can all produce 401 responses even when the client sends perfectly valid credentials.
How do I prevent 401 errors caused by token expiry in a production application?
Implement proactive token refresh — monitor the token's remaining lifetime and refresh it before expiry, not after. For OAuth 2.0, use the refresh token endpoint to obtain a new access token when the current one has less than 20% of its TTL remaining. Add a global HTTP response interceptor that automatically handles 401 responses by attempting a single token refresh before retrying the original request.
Does clearing cookies always fix a 401 error in a browser?
Only if the root cause is a corrupt or stale session cookie. If the 401 is caused by server-side misconfiguration, an expired API key, or a firewall block, clearing cookies will have no effect. Use an incognito window as a diagnostic step — if the 401 persists in incognito, the problem is server-side or network-side, not browser-side.
