WWW-Authenticate auth response
Tells the client what authentication scheme is required to access the resource — sent on 401 responses.
What it does
WWW-Authenticate tells the client what authentication scheme is required to access a resource, and what parameters to use. It's sent on 401 Unauthorized responses. Without it, the client knows authentication failed but doesn't know how to authenticate.
It's the server's half of the HTTP authentication challenge-response handshake — WWW-Authenticate is the challenge; Authorization is the response.
Syntax
WWW-Authenticate: <scheme> <parameters>
WWW-Authenticate: <scheme> realm="<realm>"[, <param>="<value>"]
Multiple challenges can be listed (comma-separated, or multiple header instances):
WWW-Authenticate: Basic realm="My App", Bearer realm="My App"
Examples:
WWW-Authenticate: Basic realm="Admin Area"
WWW-Authenticate: Bearer realm="api"
WWW-Authenticate: Bearer realm="api", error="invalid_token", error_description="Token expired"
WWW-Authenticate: Digest realm="example.com", nonce="abc123", algorithm=MD5
The realm parameter
realm is the only universally required parameter. It identifies the "protection space" — a label for the resource area requiring authentication. Its practical effects:
- Browser Basic auth dialogs show the realm as the prompt text: "Sign in to [realm]"
- Credential scoping: browsers may reuse stored credentials for other requests with the same realm on the same server
- For Bearer/JWT APIs, realm is often just your app name or
"api"— it's informational
Scheme-specific parameters
Basic
WWW-Authenticate: Basic realm="My Application"
Triggers the browser's native username/password dialog. The simplest scheme — just realm is needed.
Bearer (OAuth 2.0 / JWT)
WWW-Authenticate: Bearer realm="api"
WWW-Authenticate: Bearer realm="api", error="invalid_token", error_description="The token has expired"
WWW-Authenticate: Bearer realm="api", error="insufficient_scope", scope="read:admin"
Standard error codes for Bearer (RFC 6750):
invalid_request— malformed requestinvalid_token— token expired, revoked, or malformedinsufficient_scope— valid token but lacks required permissions
Digest
WWW-Authenticate: Digest realm="example.com", nonce="abc123xyz", algorithm=MD5, qop="auth"
Complex challenge-response scheme. Rarely used in new systems.
The authentication flow
Client Server
| |
| GET /api/resource |
|------------------------------>|
| |
| 401 Unauthorized |
| WWW-Authenticate: Bearer |
| realm="api" |
|<------------------------------|
| |
| GET /api/resource |
| Authorization: Bearer <tok> |
|------------------------------>|
| |
| 200 OK |
|<------------------------------|
Browser behaviour with Basic auth
When a browser receives WWW-Authenticate: Basic realm="...", it:
- Shows a native login dialog with the realm text
- On submit, sends
Authorization: Basic <base64(user:password)> - Caches the credentials for that realm for the session
- Re-sends them automatically on subsequent requests to URLs with the same realm
This built-in browser behaviour is convenient for simple password-protected areas but gives you no control over styling and is generally avoided in modern web apps in favour of form-based auth.
How it interacts with other headers
WWW-Authenticate always accompanies a 401 Unauthorized status code. A 401 without WWW-Authenticate is technically non-compliant (though widely seen in practice for APIs where the client already knows the scheme).
Proxy-Authenticate is the proxy equivalent — same mechanism, but for proxy authentication, accompanied by 407 Proxy Authentication Required.
Authentication-Info can appear on successful responses (200) after Digest auth to provide mutual authentication confirmation.
Common mistakes and gotchas
Returning 401 without WWW-Authenticate. Compliant HTTP clients expect WWW-Authenticate on a 401. API clients that check for it to determine how to authenticate will fall back to guessing or fail. Always include it.
Generic realm values. realm="Restricted" or realm="Protected" tells the user nothing. Use something meaningful like realm="MyApp API" or realm="Admin Dashboard".
Not including error details on Bearer. When a token fails, returning WWW-Authenticate: Bearer realm="api", error="invalid_token", error_description="Token expired" is far more useful for API consumers than a bare 401. It tells them exactly why the token was rejected.
Multiple schemes in the wrong order. If you list multiple schemes, put the most preferred/secure one first. Some clients pick the first recognised scheme.
Real-world examples
Basic auth challenge (static site protection):
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="Staging Environment"
Bearer challenge with error detail:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="api", error="invalid_token", error_description="JWT expired at 2026-06-22T00:00:00Z"
Content-Type: application/json
{"error": "Unauthorized", "message": "Token has expired"}
Multiple schemes (prefer Bearer, fall back to Basic):
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="api", Basic realm="api"
Insufficient scope (valid token, wrong permissions):
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="api", error="insufficient_scope", scope="admin:write"
FAQ
Is WWW-Authenticate required on every 401?
Per RFC 9110, yes — a 401 response SHOULD include WWW-Authenticate. In practice, many APIs omit it when the client is expected to already know the auth scheme (API clients, not browsers). Omitting it is technically non-compliant but widely tolerated. For browser-facing endpoints, always include it.
Can I send WWW-Authenticate on responses other than 401?
The spec allows it on other responses as additional information, but in practice it's almost exclusively sent on 401. Some implementations also send it on 403 to indicate the resource requires different credentials — but this conflates authentication and authorization in a confusing way.
What's the difference between WWW-Authenticate and Proxy-Authenticate?
Same mechanism, different target. WWW-Authenticate + 401 is for the origin server — the resource itself requires authentication. Proxy-Authenticate + 407 is for an intermediate proxy — the proxy requires authentication before forwarding the request. The client responds to WWW-Authenticate with Authorization, and to Proxy-Authenticate with Proxy-Authorization.
Does WWW-Authenticate work for Single Page Applications?
Not directly — SPAs handle authentication in JavaScript and don't rely on browser-native auth dialogs. But WWW-Authenticate is still useful for SPAs: an API returning WWW-Authenticate: Bearer realm="api", error="invalid_token" gives the SPA's HTTP client clear machine-readable signal to redirect to login or refresh the token.
Fun fact
The triple-W prefix in WWW-Authenticate is a relic of HTTP's origins as the World Wide Web protocol. Early HTTP headers were often prefixed with WWW- to namespace them. As HTTP became universal infrastructure far beyond "the web," the naming looks increasingly anachronistic — but like many HTTP naming decisions, it's too embedded to change. Proxy-Authenticate (its sibling) got a cleaner name because it was designed slightly later with the awkwardness of WWW- already apparent.