The 1xx–5xx class guide
HTTP status codes are grouped into five classes by their first digit, so a developer who knows the class rules can triage a response without reading the specific code. The class tells you immediately whether the problem originates on the client, on the server, or somewhere in between, and that single distinction drives whether you retry, re-authenticate, follow a redirect, or file a server-side bug.1
Decoding each response class
1xx Informational —
the server received the request and is continuing to process it. A 100 Continue
response lets a client with a large body start transmitting only after the server
signals readiness, and 101 Switching Protocols confirms an upgrade such as a move
to WebSockets. You rarely handle these explicitly in application code because they
are mostly an implementation detail of the HTTP connection itself.
2xx Success — the
request was received, understood, and accepted without error. 200 OK is the
baseline response for a successful GET or PUT; 201 Created follows a write that
adds a new resource and should include a Location header pointing at it; 204 No
Content is the cleanest choice for a DELETE that returns no body, since it tells
the client the action succeeded without wasting bandwidth on an empty payload.
3xx Redirection —
the client must take an additional action, usually a request to a different URI,
to complete the original operation. 301 and 308 signal permanent moves that search
engines and bookmark managers can cache indefinitely; 302 and 307 signal temporary
detours that keep the original address authoritative. The key distinction between
the 301/302 pair and the 308/307 pair is method preservation: 308 and 307 require the
client to repeat the same HTTP method (POST stays POST) when it follows the redirect,
while 301 and 302 allow clients to downgrade the request to a GET.2
4xx Client Error —
the request contains bad syntax, missing authorization, or a logical state that
the server refuses to act on. The fault lies with the client, so retrying the
unchanged request usually produces the same outcome. 400 covers structurally
malformed requests that the parser cannot interpret; 401 and 403 both cover access
problems but distinguish between an unknown identity and a known-but-unauthorized
one; 404 covers resources that cannot be found at the requested address; 429 covers
rate limiting, signalling that the client is sending too many requests a given
window and should back off before trying again.1
5xx Server Error —
the server failed to fulfil a request that the client formed correctly. The fault
is server-side, so the client can often retry the same request later and succeed
once the underlying problem is resolved. 500 is the generic catch-all for an
unexpected condition the server does not want to expose in detail; 502 and 504 both
point to upstream dependency problems such as a crashed backend or a timed-out
gateway; 503 signals that the server is deliberately refusing traffic because it is
overloaded or undergoing planned maintenance, and well-behaved clients respect the
Retry-After header when one is present.3
Using codes in API design
Choosing the right status code is as much a part of your API contract as the shape of the response body, because client code branches on status codes to decide whether to retry, prompt for credentials, follow a redirect, or surface an error to the end user. When a team is unsure which of two close codes applies, the decision usually comes down to what behaviour they want the client to exhibit next, not just to the literal condition on the server.
Three code pairs that cause the most confusion
400 vs 422: Return 400 when
the request is structurally broken, meaning the server cannot even parse it into
a meaningful operation. A missing JSON brace, a wrong Content-Type, or an absent
required top-level field all fall into this category. Return 422 when the request is
structurally valid but fails semantic or business rules: a date range whose end
precedes its start, a quantity below the minimum order, a string that violates a
documented pattern. The rule of thumb is that 400 covers syntax, while 422 covers
validation rejected by domain logic.4
401 vs 403: Return 401 when
the client is not authenticated and you want to prompt them to log in, since a
well-behaved client follows a 401 by requesting credentials. Return 403 when the
caller is authenticated but lacks permission for this specific resource or action,
meaning re-authenticating will not help because the identity itself is unauthorized.
Returning 404 instead of 403 is a defensible security choice when you want to avoid
revealing that a resource exists to an unprivileged caller.4
404 vs 410: Return 404 when
you are not certain the resource ever existed, or when you want to leave the door
open to recreating it at the same URI later. Return 410 Gone when the resource was
definitively deleted and will never return, because that tells both people and
automated systems the absence is permanent. Google treats 404 and 410 similarly for
indexing purposes, but 410 makes the permanent-removal intent much easier to see
in your own logs, monitoring alerts, and client telemetry.3
A concrete request makes the choice obvious. A POST to
/api/bookings with a checkOutDate earlier than
checkInDate parses as valid JSON with every
required field present, so the server cannot reject it as malformed. The
date relationship itself violates a business rule, which is exactly what
422 Unprocessable Content is for, not 400.
Unofficial codes
Several widely-used codes have never been registered with the IANA HTTP Status
Code Registry, yet they show up regularly in production traffic because large
infrastructure vendors defined them to capture conditions the standard range cannot
express in enough detail. Understanding them is not academic: these codes appear
in load-balancer access logs, monitoring dashboards, and error-tracking tools the
same way any official code does, and an engineer who cannot identify them will
misattribute a vendor-specific outage to the wrong layer of the stack.
Vendor-specific codes in the wild
Cloudflare reserves the 520–526 range for edge-to-origin failure modes that the
existing 5xx family describes too loosely. A 522 Connection Timed Out and a 524 A
Timeout Occurred distinguish between an origin that never replied and an origin
that replied too late, distinctions that a generic 504 Gateway Timeout collapses
into a single value.5 nginx, on the
other hand, defined a family of 4xx codes for client-and-connection events rather
than application errors: 444 silently drops the connection, 495 and 496 flag bad
TLS certificates, and 499 captures a client that closed the socket before the
server could respond. That last code is especially valuable for diagnosing timeout
mismatches between a load balancer, a CDN, and an application server, because a
sudden spike in 499 responses usually points at a keep-alive or body-size
misconfiguration rather than at application logic.67
The Unofficial badge in this reference marks these vendor-defined codes clearly,
so you can recognize them at a glance without assuming they are tracked by the
RFC series. Including them in your monitoring and runbooks keeps the same
diagnostic detail available across the whole fleet, whether the traffic flows
through Cloudflare, nginx, or some other intermediary that has invented its own
vocabulary for describing transport and edge failures.
Caching behavior and redirect permanence
HTTP caching interacts with status codes in ways that have lasting operational
consequences, because the code on the wire determines whether a stored response is
reusable at all. Getting the code wrong for a cacheable endpoint either serves
stale data to users after a change or defeats the cache by forcing needless
revalidation, and both outcomes are expensive to debug in production once live. A
200 OK response is cacheable whenever Cache-Control or Expires headers say so, and a
304 Not Modified response tells the client its local copy is still valid, letting
the browser skip the download and reuse the cached headers
instead.8 These two codes together are
the foundation of web performance caching: full content on first load, incremental
validation on subsequent requests.
Picking the right redirect for your caching plan
A 200 OK response is cacheable whenever Cache-Control or Expires headers say so,
and a 304 Not Modified response tells the client its local copy is still valid,
letting the browser skip downloading and reuse the cached headers
instead. Together they carry most of the performance benefit of web caching:
transfer the full resource once, then validate cheaply on each repeat visit.
Redirect responses affect caches differently, and the choice between 301 and 302
has long-term consequences that are easy to underestimate. A 301 Permanent
Redirect is heuristically cacheable, meaning browsers and CDNs will keep serving
it even after you change or remove the target URL, unless your cache headers say
otherwise.28 A
302 Temporary Redirect is not heuristically cacheable by default, but a cache can
still store it when explicit freshness information permits. Using 301 for a
redirect you plan to reverse later can therefore leave visitors pinned to the old
destination until every cache finally expires, which is why 301 should be reserved
for genuinely permanent moves and 302 or 307 used for temporary redirects where you
want the freedom to point the URL somewhere else again next week.
Picked the Right Status Code Checklist
- 400 vs 422 400 means the request is structurally broken and the server cannot parse it. 422 means it parsed fine but failed a business rule, like an end date before a start date.
- 401 vs 403 401 means the caller has no valid credentials yet, so the client should prompt for login. 403 means the caller is known but not allowed to do this, so re-authenticating won't help.
- 404 vs 410 404 leaves the door open to the resource existing later. 410 says it's gone permanently and tells crawlers and monitoring not to expect it back.
Pick a status code for your own endpoint and check it against these three pairs before you ship it.
- 1.
R. Fielding, M. Nottingham, and J. Reschke, "HTTP Semantics," RFC 9110, IETF, June 2022. https://www.rfc-editor.org/rfc/rfc9110.txt
- 2.
MDN Web Docs, "Redirections in HTTP," developer.mozilla.org, accessed June 2026. https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Redirections
- 3.
Google, "How HTTP Status Codes Affect Google's Crawlers," developers.google.com, February 2026. https://developers.google.com/crawling/docs/troubleshooting/http-status-codes
- 4.
MDN Web Docs, "HTTP response status codes," developer.mozilla.org, accessed June 2026. https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status
- 5.
Cloudflare, "Error responses," developers.cloudflare.com, accessed June 2026. https://developers.cloudflare.com/fundamentals/reference/error-responses/
- 6.
nginx, "Module ngx_http_core_module," nginx.org, accessed June 2026. https://nginx.org/en/docs/http/ngx_http_core_module.html
- 7.
nginx, "ngx_http_special_response.c," github.com, accessed June 2026. https://github.com/nginx/nginx/blob/release-1.15.8/src/http/ngx_http_special_response.c
- 8.
R. Fielding, M. Nottingham, and J. Reschke, "HTTP Caching," RFC 9111, IETF, June 2022. https://www.rfc-editor.org/rfc/rfc9111.txt