HTTP Status Codes

Searchable HTTP status code reference including the proxy-specific codes - 499, 502, 504, 52x - that actually show up in production incidents.

Reference Protocol Reference Runs in your browser
Try:

Result

Status classes

ClassMeaningDescription
1xxInformationalRequest received, processing continues.
2xxSuccessThe request was received, understood and accepted.
3xxRedirectionFurther action needed to complete the request.
4xxClient errorThe request is faulty - fixing it is the client's job.
5xxServer errorThe request was valid; the server failed to fulfil it.

Codes (40)

CodeNameWhat it means in practice
100ContinueClient may send the request body. Used with Expect: 100-continue.
101Switching ProtocolsUpgrade accepted - WebSocket handshake.
103Early HintsPreload hints before the final response.
200OKStandard success.
201CreatedResource created; Location header should point at it.
204No ContentSuccess with an empty body. Common for DELETE and captive-portal probes.
206Partial ContentRange request satisfied - resumable downloads and video seeking.
301Moved PermanentlyPermanent redirect. Cached aggressively - hard to undo.
302FoundTemporary redirect; method may change to GET. Prefer 307.
304Not ModifiedCache validation succeeded; no body sent.
307Temporary RedirectTemporary, method and body preserved.
308Permanent RedirectPermanent, method and body preserved.
400Bad RequestMalformed syntax. Often an oversized header or bad JSON.
401UnauthorizedAuthentication required or failed - it means unauthenticated.
403ForbiddenAuthenticated but not permitted, or blocked by a WAF.
404Not FoundNo resource at this path.
405Method Not AllowedWrong verb - frequently a POST to a GET-only route.
408Request TimeoutClient took too long to send the request.
409ConflictState conflict, such as a concurrent update.
410GoneDeliberately removed and will not return.
413Payload Too LargeBody exceeds server limit - nginx client_max_body_size.
414URI Too LongUsually a runaway query string.
418I'm a teapotRFC 2324 joke code, occasionally used to fingerprint bots.
421Misdirected RequestConnection reused for a host this server does not serve - TLS/SNI coalescing.
422Unprocessable ContentSyntactically valid, semantically wrong - validation failures.
425Too EarlyTLS early data rejected to avoid replay.
429Too Many RequestsRate limited. Honour the Retry-After header.
431Request Header Fields Too LargeHeader block too big - often oversized cookies.
451Unavailable For Legal ReasonsBlocked by legal demand.
499Client Closed Requestnginx-specific: client gave up before the response.
500Internal Server ErrorUnhandled application error. Check application logs, not the proxy.
501Not ImplementedMethod not supported at all.
502Bad GatewayUpstream returned something invalid, or is not listening.
503Service UnavailableTemporarily overloaded or in maintenance.
504Gateway TimeoutUpstream did not answer in time - the proxy timeout fired.
507Insufficient StorageServer out of space.
508Loop DetectedInfinite redirect or recursion.
521Web Server Is DownCloudflare-specific: origin refused the connection.
522Connection Timed OutCloudflare-specific: origin did not complete the TCP handshake.
525SSL Handshake FailedCloudflare-specific: TLS negotiation with the origin failed.
502 versus 504
502 means the upstream answered with garbage or refused the connection; 504 means it never answered in time. That distinction points at completely different causes - a crashed backend versus a slow one - and is the first thing to establish during an incident.

About HTTP Status Codes

The status code is the first piece of evidence in almost every web incident. This reference includes the non-standard codes that real infrastructure emits - nginx 499, Cloudflare 52x - because those are the ones missing from most tables when you need them.

Choosing codes for an API

Use 400 for malformed syntax and 422 for a well-formed request that fails validation; the distinction tells a client whether retrying with the same body could ever work. Use 409 for a state conflict, 429 with Retry-After for rate limiting, and 503 only for genuine unavailability. Return 201 with a Location header on creation, and 204 with no body on deletion. Above all, never return 200 with an error in the body — it defeats every monitor, cache and retry policy between you and the client.

401 versus 403

401 means unauthenticated: no valid credentials were presented, and the response should include a WWW-Authenticate challenge. 403 means authenticated but not permitted - or blocked by policy such as a WAF or geo rule. The names are historically backwards, which is why the distinction is worth stating explicitly in code review.

Common use cases

  • Triaging an outage from a load balancer log.
  • Choosing the correct code for an API you are designing.
  • Explaining to a client why a 301 cannot simply be reverted.

Edge cases and gotchas

  • 301 and 308 are cached by browsers, sometimes indefinitely. Test redirects with 302 or 307 first.
  • A 200 response with an error message in the body defeats every monitoring system you own.

Frequently asked questions

What does 499 mean?
It is nginx-specific: the client closed the connection before the server responded. It usually indicates a slow backend and an impatient client or a timeout at the far end, not a server fault.
Should a rate limiter return 429 or 503?
429 with a Retry-After header, so clients can back off correctly. 503 is for genuine unavailability.