HTTP Status Codes Reference

Complete list of HTTP status codes

1xx 1xx Informational

100
Continue
Server received request headers, client should proceed
101
Switching Protocols
Server is switching protocols as requested
102
Processing
Server is processing the request (WebDAV)
103
Early Hints
Used to return response headers before final response

2xx 2xx Success

200
OK
Request succeeded
201
Created
Request succeeded, new resource created
202
Accepted
Request accepted for processing
203
Non-Authoritative Information
Metadata from third-party copy
204
No Content
No content to send, headers may be useful
205
Reset Content
Reset the document that sent this request
206
Partial Content
Partial resource due to Range header
207
Multi-Status
Multiple status codes (WebDAV)
208
Already Reported
DAV binding already reported (WebDAV)

3xx 3xx Redirection

300
Multiple Choices
Multiple options for the resource
301
Moved Permanently
Resource moved permanently to new URL
302
Found
Resource temporarily moved to different URL
303
See Other
Response found at another URI using GET
304
Not Modified
Resource not modified since last request
307
Temporary Redirect
Temporary redirect, keep HTTP method
308
Permanent Redirect
Permanent redirect, keep HTTP method

4xx 4xx Client Error

400
Bad Request
Server cannot process due to client error
401
Unauthorized
Authentication required
402
Payment Required
Reserved for future use
403
Forbidden
Server refuses to authorize
404
Not Found
Resource not found
405
Method Not Allowed
HTTP method not allowed
406
Not Acceptable
No content conforming to Accept headers
407
Proxy Authentication Required
Proxy authentication needed
408
Request Timeout
Server timed out waiting for request
409
Conflict
Request conflicts with server state
410
Gone
Resource permanently deleted
411
Length Required
Content-Length header required
412
Precondition Failed
Precondition in headers not met
413
Payload Too Large
Request entity too large
414
URI Too Long
URI too long for server
415
Unsupported Media Type
Media format not supported
416
Range Not Satisfiable
Range specified can't be fulfilled
417
Expectation Failed
Expect header cannot be met
418
I'm a teapot
Server refuses to brew coffee with teapot
422
Unprocessable Entity
Request well-formed but has semantic errors
423
Locked
Resource is locked (WebDAV)
424
Failed Dependency
Request failed due to previous request
425
Too Early
Server unwilling to risk early request
426
Upgrade Required
Client should switch protocols
428
Precondition Required
Request must be conditional
429
Too Many Requests
Rate limited, too many requests
431
Request Header Fields Too Large
Headers too large
451
Unavailable For Legal Reasons
Blocked for legal reasons

5xx 5xx Server Error

500
Internal Server Error
Generic server error
501
Not Implemented
Server does not support functionality
502
Bad Gateway
Invalid response from upstream server
503
Service Unavailable
Server not ready, often overloaded
504
Gateway Timeout
Gateway did not get response in time
505
HTTP Version Not Supported
HTTP version not supported
506
Variant Also Negotiates
Content negotiation error
507
Insufficient Storage
Server unable to store (WebDAV)
508
Loop Detected
Infinite loop detected (WebDAV)
510
Not Extended
Further extensions required
511
Network Authentication Required
Network authentication needed

Status Codes Are a Protocol Contract, Not Decoration

An HTTP status code is machine-readable control flow, and half the internet branches on it: browsers decide whether to follow a redirect or show an error page, caches and CDNs decide whether to store the response, search crawlers decide whether to keep or drop a URL from the index, HTTP client libraries decide whether to retry, and monitoring systems decide whether to page someone. Returning 200 with an error message in the JSON body — the most common status-code antipattern — defeats every one of those systems at once: the error gets cached, the crawler indexes it, the client library reports success, and your error-rate dashboard stays green through an outage. The authoritative definitions live in RFC 9110 "HTTP Semantics" (2022), which consolidated and replaced the older RFC 7231 family. The first digit carries the contract: 1xx informational, 2xx success, 3xx redirection, 4xx the client erred, 5xx the server erred. That classification is load-bearing because of an explicit rule in the spec: a client that receives a code it does not recognize must treat it as the x00 of its class. A client that has never heard of 429 must handle it as a generic 400; an unknown 599 is treated as 500. This is what lets new codes enter the ecosystem without breaking deployed software — and it is why inventing private codes in the wrong class (a "success" reported as 470, say) breaks intermediaries you do not control. The 4xx/5xx boundary is also a blame assignment — it decides who gets paged.

Redirects Done Right: 301, 302, 303, 307, 308

Five redirect codes exist because of a twenty-year-old disagreement between the spec and the browsers. HTTP/1.0 defined 301 and 302 as method-preserving: a POST redirected with 302 should be re-POSTed to the new location. Browsers ignored this and rewrote the method to GET, and the behavior was too widespread to fix. HTTP/1.1 codified reality instead of fighting it: 303 See Other was created to mean "go GET this other resource" (the backbone of the POST-redirect-GET pattern that prevents form resubmission on refresh), 307 Temporary Redirect restored the original strict meaning — same method, same body, guaranteed — and RFC 7538 completed the grid in 2015 with 308 Permanent Redirect, the method-preserving twin of 301. So the mental model is a 2x2 matrix: permanent vs temporary crossed with may-change-method vs must-preserve-method. 301 and 302 are the legacy corner (method may mutate to GET); 308 and 307 are the strict corner. For API endpoints that accept POST, PUT, or DELETE, that distinction is not cosmetic — redirecting an upload with 301 silently converts it into a bodyless GET on many clients, and the request data evaporates. Permanence has teeth. Browsers cache 301 and 308 aggressively, often with no expiry, so a mistaken permanent redirect keeps firing from local caches long after the server stops sending it — users need a cache purge you cannot trigger remotely. The standard advice: deploy risky redirects as 302/307 first, watch, then promote to 301/308. Search engines treat 301/308 as "transfer ranking signals to the new URL", making them the correct choice for domain migrations and HTTPS upgrades, ideally kept alive for months.
                 method may → GET   method preserved
permanent        301 Moved           308 Permanent Redirect
temporary        302 Found           307 Temporary Redirect
after POST       303 See Other  →  always GET (PRG pattern)

# Verify what a redirect really does:
curl -si -X POST https://example.com/old | head -3
HTTP/1.1 301 Moved Permanently
Location: https://example.com/new
# many clients will now GET /new — the POST body is gone

401 vs 403 vs 404: Authentication, Authorization, and Hiding

The names sabotage the semantics: 401 is labeled "Unauthorized" but means unauthenticated — the server does not know who you are. RFC 9110 makes the intent structural: a 401 response is required to carry a WWW-Authenticate header telling the client which authentication scheme to use, because 401 is not a dead end but an invitation to try again with credentials. That is why browsers respond to a 401 with a Basic challenge by popping a login dialog, and why well-built API clients treat 401 as the trigger to refresh an expired access token and replay the request once. 403 Forbidden is the opposite situation: authentication succeeded, identity is known, and the answer is still no. The token is valid but lacks a scope; the user is real but not an admin; the resource exists but belongs to someone else. The critical operational difference is that retrying a 403 with the same credentials is pointless — token refresh loops that fire on 403 are a bug that hammers auth servers for nothing. There is a third option the spec explicitly endorses: lying. A 403 for a resource confirms that the resource exists, and existence is sometimes the secret — private repository names, user account presence, internal admin paths. RFC 9110 allows a server that wishes to hide a resource to return 404 instead of 403, and GitHub famously does exactly this for private repos you cannot see. The cost is debuggability (legitimate users with missing permissions see a confusing "not found"), so the choice is a real security-versus-supportability tradeoff, best made deliberately.

Retries and Rate Limits: 429, 503, and Retry-After

429 Too Many Requests (defined in RFC 6585, not the core spec) is the protocol's back-pressure valve: the request was understood, the client is simply sending too fast. A well-formed 429 carries a Retry-After header, which accepts two formats — delta seconds (Retry-After: 30) or an absolute HTTP-date — and clients should honor it instead of retrying on their own schedule. Most real APIs supplement it with quota telemetry headers (the X-RateLimit-Limit / Remaining / Reset family, being standardized as RateLimit fields), which let clients pace themselves before hitting the wall rather than after. Whether to retry at all depends on three questions. Is the failure retryable? 5xx generally yes, 4xx generally no — the request itself is defective — with 408, 429, and (with care) 425 as the exceptions. Is the method safe to repeat? GET, PUT, and DELETE are defined as idempotent; a POST that timed out mid-flight may have succeeded invisibly, so blind POST retries risk double charges — the reason payment APIs add idempotency keys. And how should retries be spaced? Exponential backoff with jitter, because a fleet of clients retrying on the same fixed schedule re-synchronizes into waves that re-crush a recovering server. During incidents, the 5xx trio is a triage map. 502 Bad Gateway: the proxy reached upstream and got garbage — look at the app process (crashed, OOM). 503 Service Unavailable: deliberate refusal — overload, maintenance, health checks failing; may include Retry-After. 504 Gateway Timeout: upstream never answered in time — look at slow queries, deadlocks, exhausted connection pools.
HTTP/1.1 429 Too Many Requests
Retry-After: 30
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1751414460

Retry decision cheat sheet:
408, 429, 5xx  → retry with exponential backoff + jitter
other 4xx      → do not retry; fix the request
POST           → only retry with an idempotency key

backoff: 1s → 2s → 4s → 8s (+ random jitter each step)

Status Codes and Caching: 304, ETags, and the Cacheable-by-Default List

304 Not Modified is the only status code whose entire job is saving bandwidth. The flow is conditional revalidation: the server tags a response with a validator — an ETag (opaque version identifier) or Last-Modified date — and when the cached copy expires, the client asks again with If-None-Match or If-Modified-Since. If the resource is unchanged, the server answers 304 with no body, the cache marks its copy fresh again, and the payload never crosses the wire. ETags come in two strengths — weak validators (W/ prefix) promise semantic equivalence, strong ones promise byte identity, required for ranged requests — and one classic pitfall: default ETags derived from file inode metadata differ across servers behind a load balancer, silently breaking revalidation. Less known and more dangerous: some status codes are cacheable by default. RFC 9110 designates 200, 203, 204, 206, 300, 301, 308, 404, 405, 410, 414, and 501 as heuristically cacheable — a cache may store them even with no Cache-Control header at all, guessing freshness from heuristics like one-tenth of the time since Last-Modified. Yes, 404 is on the list. The production failure mode: a request arrives before your deploy finishes, the CDN caches the 404, and the file keeps 404ing after it exists — until someone purges. Meanwhile 302 and 307 are not heuristically cacheable, which is exactly why temporary redirects are the safe experiment and permanent ones are the commitment. The takeaway is to never rely on defaults: send explicit Cache-Control on every response, including errors — something like a 60-second TTL on 404s and no-store on 5xx keeps mistakes short-lived.
# First request — server tags the response
HTTP/1.1 200 OK
ETag: "v42-a1b2c3"
Cache-Control: max-age=3600

# One hour later — conditional revalidation
GET /app.js HTTP/1.1
If-None-Match: "v42-a1b2c3"

HTTP/1.1 304 Not Modified        ← no body: bytes saved
ETag: "v42-a1b2c3"

# Cacheable WITHOUT any Cache-Control header (RFC 9110):
# 200 203 204 206 300 301 308 404 405 410 414 501
Last updated:

About this tool

A searchable HTTP status code reference covers every standard response code grouped by class: 1xx informational, 2xx success, 3xx redirection, 4xx client error, and 5xx server error. Each entry shows the canonical name and a short explanation so you can answer "what does 422 actually mean" or "should I return 401 or 403" without leaving your editor.

How to use

  1. Type a code (404), partial name (gateway), or keyword (auth) into the search box.
  2. Browse the filtered list grouped by status class.
  3. Read the canonical name and one-line description for the matching codes.
  4. Use the colour coding to quickly spot 4xx (client error) vs 5xx (server error).
  5. Reference the result in your API design, log analysis, or error handling code.

Common use cases

  • Choosing the right status code for a new REST API endpoint.
  • Investigating a strange status code (e.g., 418, 451) you saw in a server log.
  • Deciding between 401 Unauthorized and 403 Forbidden for an auth flow.
  • Documenting expected error responses in an OpenAPI / Swagger spec.
  • Understanding why a CDN returned 503 vs 504 during an outage.
  • Mapping HTTP errors to user-facing error messages with consistent semantics.

Frequently asked questions

Q. When should I return 401 vs 403?

A. 401 means "not authenticated, present credentials"; 403 means "authenticated but not allowed". If the client has no valid session, send 401. If they are logged in but lack permission, send 403.

Q. Is 422 the same as 400?

A. Both are 4xx, but 400 means the request itself is malformed (bad JSON, missing header) while 422 means the request is well-formed but semantically invalid (validation failed).

Q. Should I always use 200 for successful POSTs?

A. 201 Created is more precise when you create a new resource and 204 No Content when you succeed but return no body. 200 is correct when you do return a representation.

Q. What does 429 mean for rate limiting?

A. 429 Too Many Requests signals the client should slow down. Pair it with a Retry-After header so clients know when to try again.