Every HTTP response opens with a three-digit number. Most of the time nobody looks at it, because the browser turns a good one into a page and a bad one into an error screen. The moment something breaks, that number is the shortest honest account of what happened, and it turns a vague "the site is down" into a specific question with a specific owner.
The full registry is larger than anyone needs to memorise. The useful move is to learn the structure first, then the dozen or so codes that carry real information.
The first digit carries the meaning#
Codes are grouped into five classes by their first digit, and the last two digits do no categorising work at all. 1xx is informational, 2xx is success, 3xx is redirection, 4xx is a client error, and 5xx is a server error.
That grouping degrades gracefully, which is the part worth internalising. A client that has never heard of 451 can still tell it is a client-side refusal and behave sensibly, which is what lets new codes be added without breaking what is already deployed.
Most codes in daily use are defined in RFC 9110, the current HTTP semantics specification, and the authoritative list of who owns which number is the IANA HTTP Status Code Registry. The registry also shows how much room is left: large stretches, including 452 through 499 and 512 through 599, are unassigned. Two entries are recorded as (Unused), 306 and 418, the latter being the joke teapot code that got popular enough to need permanently reserving.
Success is not only 200#
200 OK is the one everyone knows, and it means the request succeeded and a representation is attached. Two of its neighbours are worth recognising because they change what a client should do next.
204 No Content. Succeeded, and deliberately has no body. A save that returns nothing to display, or a beacon that just needs acknowledging. Treating an empty body here as a failure is a common bug in hand-written clients.206 Partial Content. Succeeded, and this is only the slice that was asked for. Video seeking, resumable downloads, and range requests generally live here.
An API that returns 200 with an error message in the body is a real problem, not a stylistic one. Every cache, monitor, and retry policy in the path reads the status line, not your JSON.
Four redirects, and why the method matters#
Four codes all mean "look somewhere else," and picking between them is the most consequential status-code decision most sites make.
The permanent pair first. 301 Moved Permanently says the resource has a new address for good, which is what you want after a domain change or an HTTPS migration: it tells anything holding the old address to update its records rather than keep asking. 308 Permanent Redirect means the same thing with one addition that matters: MDN puts it plainly, the user agent "must not change the HTTP method used: if a POST was used in the first request, a POST must be used in the second request."
The temporary pair works the same way. 302 Found says the resource is elsewhere for now, and 307 Temporary Redirect says the same while forbidding a method change. Both pairs exist because clients historically turned a redirected POST into a GET, silently dropping the submitted body.
Then there is 303 See Other, the opposite intent made explicit: it tells the client to fetch the other address with a GET. That is the post-then-redirect pattern, where a form submission ends on a plain results page so a refresh does not resubmit the order.
Redirects also cost real time, since each hop is another round trip before anything renders. A chain of three or four is worth flattening, and our HTTP header inspector is built to show it: it follows up to five hops and lists each one with its status code and the Location it pointed at.
304 is a hit, not a failure#
304 Not Modified sits in the 3xx block but redirects nothing. It answers a conditional request: the client already has a copy and asks whether it is still current, and the server confirms it is without resending the bytes. As MDN describes it, the client "can continue to use the same cached version of the response."
This is why 304 is the odd one out in its class, and why any code that follows redirects has to special-case it. Our own inspector does exactly that: it treats a status from 300 to 399 as a redirect to follow, except 304, which it reports as the final answer.
Plenty of 304s in a log is usually good news. Caching is working, and repeat visitors are paying for a header exchange instead of a full download.
401 and 403 are different refusals#
These two get used interchangeably, and they answer different questions.
401 Unauthorized is misnamed. As MDN notes, "semantically this response means 'unauthenticated'. That is, the client must authenticate itself to get the requested response." The server does not know who is asking. A correct 401 comes with a WWW-Authenticate header describing how to prove it.
403 Forbidden is the other case. The client's identity is known and access is refused anyway. Logging in again will not help; the account genuinely lacks the right.
There is a third option that looks like a mistake and often is not. A server may answer 404 in place of 403, which MDN describes as a way "to hide the existence of a resource from an unauthorized client." Confirming that /admin/reports/2026-q3 exists but is off limits leaks the structure of a private system to anyone probing it.
404 says missing, 410 says finished#
404 Not Found is genuinely non-committal. The server cannot find anything at that address, and says nothing about whether it ever existed. A typo, a page not published yet, and a page deleted years ago all produce the same answer.
410 Gone commits. The content was there, it has been deliberately removed, and no forwarding address exists. MDN spells out the consequence for anyone on the other end: "Clients are expected to remove their caches and links to the resource." That is the whole difference. A 410 asks everyone holding a reference to drop it, where a 404 leaves the question open.
We rely on this on our own site. The per-entry pages under ASN Explorer, Port Lookup, and the MAC vendor directory only publish once an entry has actually been researched. Everything else returns a real 410 with noindex, follow, and a page pointing at the directories that are live. It is a deliberate choice not to auto-generate a thin page for every possible number just to have something return 200.
429 and 451: limits that are not technical#
Two later additions describe refusals where nothing is broken at all.
RFC 6585 defines 429 Too Many Requests, which "indicates that the user has sent too many requests in a given amount of time ('rate limiting')." Responses "SHOULD include details explaining the condition, and MAY include a Retry-After header indicating how long to wait before making a new request." That header is the difference between a client that backs off correctly and one that hammers you at random intervals.
The same RFC is honest about the code's limits. Answering a flood with 429 still costs the server work, so "servers are not required to use the 429 status code; when limiting resource usage, it may be more appropriate to just drop connections, or take other steps." That is the same reasoning behind how DDoS attacks work: under real load, answering costs more than ignoring. RFC 6585 also brought 428 Precondition Required, 431 Request Header Fields Too Large, and 511 Network Authentication Required, the last being what a captive portal should return.
RFC 7725 added 451 Unavailable For Legal Reasons for when "the server is denying access to the resource as a consequence of a legal demand." The spec asks for the details in the body: "the party making it, the applicable legislation or regulation, and what classes of person and resource it applies to." It also notes the blocking party need not be the origin, since such demands most directly affect ISPs and search engines. The number is a nod to Fahrenheit 451.
5xx: naming which machine broke#
Server errors do the most diagnostic work, because two of the four common ones tell you the failure happened behind the machine you are talking to.
500 Internal Server Error. The generic case. The application itself failed and has nothing more specific to say. Your logs, not your network.502 Bad Gateway. The server was acting as a gateway and "got an invalid response" from upstream. The proxy is healthy; whatever sits behind it is not.504 Gateway Timeout. Same relationship, different failure. The gateway "cannot get a response in time." Upstream is not answering rather than answering badly.503 Service Unavailable. Not ready, usually maintenance or overload, and explicitly temporary. It should carryRetry-Afterwith an estimate when one exists.
The 502 versus 504 distinction saves real time. Both look identical to a visitor and send you to different places: one to the upstream service's error output, the other to whatever is making it slow. If a CDN sits in front of your origin, that layer is the gateway doing the reporting, which explains an error page carrying a provider's branding. Our post on what a CDN is covers where that layer sits.
Read the chain, not the last number#
A status code summarises one exchange, and a browser only shows you the last one. The interesting information is usually in the hops before it: an http to https upgrade, a bare domain to www, then a trailing-slash fix, each adding a round trip nobody intended.
Our HTTP header inspector reports the full chain with the status of every hop, the final status code and its reason phrase, the response time, and a grade from A+ to F for the security headers that came back. If you want the headers themselves explained, HTTP security headers goes through what each one does.
For availability rather than configuration, our response time checker sends repeated HTTP HEAD probes from a Cloudflare edge location and records the status and timing of each. Some origins reject HEAD with 405 Method Not Allowed or 501 Not Implemented, so it falls back to a small GET rather than reporting a failure that is really a method restriction. A status code describes one specific request, and changing the request can change the answer.
None of this requires memorising the registry. Recognise the five classes, know which member of each pair you meant to send, and treat the number as the first fact of an investigation rather than the end of one.
See the full status chain for any URL
Follow every redirect hop with its status code and destination, see the final response and how long it took, and get the security headers graded in the same view.
Inspect HTTP headers →