401 Status Code

A practical reference for API developers, testers, and solutions architects.
Why 401 matters
Authentication bugs are noisy. They break CI pipelines, confuse frontend teams, and trigger retries that hide real failures. When you return a 401, you are starting an authentication conversation between a client and a server, and that conversation is easy to get wrong.
Today, APIs are no longer called only by browsers and backend services. They are called by LLM agents, code generation tools, AI-powered test runners, and automated integrations that do not behave like humans or browsers. These systems rely heavily on status codes to decide what to do next. A wrong 401 can trigger infinite retries, token refresh storms, or silent failures that are hard to trace.
The difference between returning []401 and 403 is important to understand](/concepts/401-vs-403). It directly affects retry logic, agent behavior, SDK error handling, browser flows, and how observability tools classify failures. In AI-driven systems, where requests are chained and decisions are automated, a misused 401 can amplify quickly and break entire workflows.
This guide explains HTTP 401 from a protocol and API design point of view, with a practical lens for modern systems. You will learn how 401 actually works, where teams misuse it, and how to test and mock authentication failures in a way that holds up in token-based APIs, gateways, and AI-driven clients.
What 401 actually means in HTTP
Despite its name, 401 Unauthorized does not mean permission denied In HTTP terms, 401 means:
The request was not applied because it lacks valid authentication credentials.
This has two important implications.
- First, the client is either not authenticated or authenticated incorrectly. Missing token, expired token, malformed credentials, wrong signature all fall under this.
- Second, the server expects the client to retry with credentials. That expectation is baked into the protocol.
This is why the HTTP spec requires a 401 response to include a WWW-Authenticate header. Without it, the client does not know how to authenticate.
Example:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer
Content-Type: application/json
{
"error": "invalid_token"
}
If you return 401 without WWW-Authenticate, you are violating the spec. Many APIs still do this, but clients, proxies, and auth libraries rely on that header.
Where 401 came from?
The number 401 dates back to HTTP/1.0 in the mid 1990s. At the time, HTTP authentication mostly meant Basic auth, username and password over headers.
The original intent was simple:
- Server challenges the client
- Client retries with credentials
- Server accepts or rejects
The term “Unauthorized” was chosen early and never renamed, even though it describes authorization, not authentication. Later specs clarified the meaning, but the status text stayed for compatibility.
From HTTP/1.0 to HTTP/1.1 to HTTP/2 and HTTP/3, the semantics never changed. Only the wire format did.
- HTTP/1.x uses a textual status line: HTTP/1.1 401 Unauthorized
- HTTP/2 and HTTP/3 use :status: 401 without a reason phrase
The meaning remains identical across all versions.
The 401 response structure
A correct 401 response has three required parts.
-
Status code
401: This tells the client the request failed due to authentication. -
WWW-Authenticate header: This is mandatory. Examples:
WWW-Authenticate: Basic
WWW-Authenticate: Bearer
WWW-Authenticate: Bearer error="invalid_token"You can send multiple challenges if you support more than one scheme.
-
Optional response body: This can include error details, but should be generic enough to avoid leaking sensitive information.
The body is not standardized. OAuth defines some common fields like error and error_description.
Usagse
401 in REST and JSON APIs
For today's JSON Rest APIs 401 almost always means token problems.
Common scenarios:
- Missing Authorization header
- Authorization: Bearer present but token expired
- JWT signature verification fails
- OAuth access token revoked
- API key not found or disabled
Example response for expired token:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer error="invalid_token", error_description="Token expired"
Many OAuth clients rely on this exact signal to trigger token refresh logic. If you return 403 or 400 instead, that logic breaks.
Browser behavior
Browsers treat 401 differently based on auth scheme. For example,.
- Basic or Digest auth triggers a browser login prompt
- Bearer token auth does not trigger prompts, but frontend apps often intercept 401 to redirect users to a login page
This makes consistency important. If one endpoint returns 401 and another returns 403 for the same auth failure, frontend behavior becomes unpredictable.
Testing and mocking
Authentication failures are sometime hardest to debug on the wire. This is the place where an Echo or a mock server is helpful.
Beeceptor is lets to simuate a 401 error. You can mock 401 responses with correct headers, simulate token expiry and invalid credentials, inspect incoming Authorization headers, and see why a client is failing authentication. More importantly, you can repeat these failures on demand.
So, instead of waiting for auth to break in production, you model the breakage early.