HTTP Status Codes
Look up every HTTP status code with its plain-English meaning and when to use it.
68 codes
The server got the request headers; the client should send the body.
Used with “Expect: 100-continue” before uploading a large body.
The server agrees to switch protocol, e.g. to WebSocket.
You see this when a WebSocket connection is established.
WebDAV: the request is received and still being processed.
Rarely used today.
Preliminary headers (usually Link preload hints) before the final response.
Lets browsers start loading CSS/fonts while the server is still working.
The request succeeded.
The default success response for GET, and for POST/PUT when you return a body.
A new resource was created.
Return it after a successful POST, with a Location header pointing to the new resource.
The request was accepted but processing hasn’t finished.
Good for queued/background jobs. Return a URL where the client can check status.
The response was modified by a proxy.
Uncommon.
Success, with no response body.
Typical for DELETE, or a PUT that returns nothing. Must not include a body.
Success; the client should reset the form/view.
Rare in APIs.
Only part of the resource is returned, as asked by a Range header.
Used for video streaming and resumable downloads.
WebDAV: several status codes for several operations.
The body contains a status per sub-request.
WebDAV: members already listed earlier in the response.
Rare.
Delta encoding result.
Very rare.
Several representations are available.
Rarely used; most servers pick one.
The resource has a new permanent URL.
Use for permanent URL changes; search engines transfer ranking. Browsers may change POST to GET — use 308 to keep the method.
Temporary redirect.
Common after login. Browsers usually switch to GET; use 307 to keep the method.
Go to another URL with GET.
The classic “redirect after POST” to avoid resubmitting forms.
The cached copy is still valid.
Sent in reply to If-None-Match / If-Modified-Since. No body — saves bandwidth.
Temporary redirect that keeps the method and body.
Use instead of 302 when a POST must stay a POST.
Permanent redirect that keeps the method and body.
Use instead of 301 for APIs where the method matters.
The server can’t process the request because it is malformed.
Invalid JSON, missing fields or wrong types. Return details about what was wrong.
Authentication is missing or invalid.
Means “not logged in”. Include a WWW-Authenticate header. For “logged in but not allowed” use 403.
Reserved for payment flows.
Some APIs use it when a plan limit or subscription is required.
The server understood but refuses to authorise it.
The user is known but lacks permission. Also used by WAFs and hotlink protection.
No resource at this URL.
Also used to hide the existence of resources the user can’t access.
The method isn’t supported for this URL.
e.g. POST to a read-only endpoint. Include an Allow header listing valid methods.
No representation matches the Accept headers.
Check the Accept header the client sends.
Authenticate with the proxy first.
Seen on corporate networks.
The server timed out waiting for the request.
Slow clients or networks; the client may retry.
The request conflicts with the current state.
Duplicate records, edit conflicts or version mismatches.
The resource is permanently gone.
Stronger than 404 — tells search engines to drop the URL.
A Content-Length header is required.
Send the body length or use chunked encoding where supported.
A condition like If-Match was false.
Used for optimistic locking with ETags.
The request body is too large.
Raise limits (e.g. nginx client_max_body_size) or upload in chunks.
The URL is longer than the server accepts.
Move large data from the query string into a POST body.
The body format isn’t supported.
Usually a missing or wrong Content-Type (e.g. sending JSON without application/json).
The requested Range can’t be served.
The range is outside the file size.
The Expect header can’t be met.
Rare.
An April Fools’ joke from RFC 2324.
Sometimes used for joke or bot-blocking responses.
The request went to a server that can’t answer for this host.
Seen with HTTP/2 connection reuse and TLS certificates.
Well-formed but semantically invalid.
Popular for validation errors (Laravel, Rails, FastAPI).
WebDAV: the resource is locked.
Rare outside WebDAV.
WebDAV: a previous request failed.
Rare.
The server won’t risk processing a replayable early-data request.
Related to TLS 1.3 0-RTT.
Switch to a different protocol.
e.g. the server requires HTTPS or a newer HTTP version.
The request must be conditional.
Forces clients to send If-Match to avoid lost updates.
Rate limit exceeded.
Respect the Retry-After header and back off exponentially.
Headers are too large.
Often caused by huge cookies — clear them.
Unofficial: nginx closed the connection without replying.
Used to drop malicious requests.
Blocked for legal reasons.
e.g. censorship or a court order.
Unofficial: the client disconnected before the server replied.
Users navigated away or a client timeout fired.
Generic server-side failure.
An unhandled exception. Check the server logs.
The server doesn’t support this functionality.
An unknown method or a not-yet-built feature.
A proxy got an invalid response from the upstream server.
The app behind nginx/a load balancer crashed or is restarting.
The server is overloaded or down for maintenance.
Temporary. Send Retry-After. Search engines treat it as temporary.
A proxy timed out waiting for the upstream server.
Slow queries or external calls. Increase timeouts or make the work asynchronous.
The HTTP version isn’t supported.
Rare.
Content negotiation misconfiguration.
Rare.
WebDAV: the server is out of storage.
Disk full.
WebDAV: an infinite loop was detected.
Rare.
Further extensions are required.
Obsolete.
Log in to the network first.
Captive portals in hotels and airports.
Unofficial: the origin returned something unexpected.
Check origin server logs.
Unofficial: the origin refused the connection.
The origin is down or blocks Cloudflare IPs.
Unofficial: Cloudflare couldn’t reach the origin in time.
Firewall or overloaded origin.
Unofficial: no route to the origin.
DNS or network issues.
Unofficial: the origin took too long to respond.
Requests over ~100 s on most plans.