HTTP Status Codes Explained (With Real Examples)
Every HTTP response carries a three-digit status code, and if you've done any web development or even just browsed the internet, you've seen a handful of them repeatedly: 200, 404, 500. Here's what the whole system actually means, organized the way it's actually useful to understand it — not as a memorized list, but as a set of categories with a clear logic behind them.
The five categories, and what the first digit tells you
Status codes are grouped by their first digit, and that digit alone tells you the general nature of the response before you even look at the specific number:
- 1xx – Informational. The request was received and processing is continuing. You'll rarely see these directly; they're mostly used internally by the protocol.
- 2xx – Success. The request worked.
- 3xx – Redirection. The resource has moved, or the client needs to take an additional step to complete the request.
- 4xx – Client error. Something about the request itself was wrong — bad syntax, missing authentication, requesting something that doesn't exist.
- 5xx – Server error. The request was valid, but the server failed to fulfill it.
That last distinction — 4xx versus 5xx — is the most practically useful thing to internalize: a 4xx means "you (the client) did something the server didn't like"; a 5xx means "the server broke while handling a request that was probably fine." This single distinction usually tells you where to start debugging.
The codes you'll actually encounter most often
200 OK — the request succeeded, plain and simple. This is what you want to see for a normal successful GET request.
201 Created — the request succeeded and, as a result, a new resource was created. You'll see this specifically after a successful POST that creates something, like a new user account or a new record.
204 No Content — the request succeeded, but there's nothing to send back. Common after a successful DELETE, where there's no resource left to describe.
301 Moved Permanently / 302 Found — the resource has moved to a different URL. 301 signals a permanent move (search engines will update their index to the new URL); 302 signals a temporary one (the old URL should still be treated as canonical). Mixing these up is a common SEO mistake — using 302 for a permanent redirect means search engines may keep indexing the old URL instead of transferring authority to the new one.
304 Not Modified — a caching response: the client already has the current version of the resource cached, so the server doesn't resend the body, saving bandwidth.
400 Bad Request — the server couldn't understand the request due to malformed syntax — often a broken JSON body, a missing required field, or an invalid parameter value.
401 Unauthorized — despite the name, this specifically means authentication is missing or failed, not that you're forbidden. If you're logged out, or your token expired, this is the response you'll get.
403 Forbidden — you're authenticated, but you don't have permission to do this specific thing. The distinction from 401 matters: 401 means "we don't know who you are (or your credentials are invalid)"; 403 means "we know who you are, and you're not allowed to do this."
404 Not Found — the server can't find the requested resource. The most universally recognized status code, and the one most often shown directly to end users.
429 Too Many Requests — you've hit a rate limit. Common with APIs that cap how many requests a client can make in a given time window.
500 Internal Server Error — a generic catch-all for "something broke on the server while handling this," without specifying what. This is the code you see when the server itself has a bug or unhandled exception.
502 Bad Gateway — a server acting as a proxy or gateway got an invalid response from an upstream server it was relying on. Common in setups with a load balancer or reverse proxy in front of the actual application server.
503 Service Unavailable — the server isn't ready to handle the request right now, often because it's overloaded or down for maintenance. Unlike a 500, this often implies the problem is temporary.
Why the exact code matters, not just "it worked" or "it broke"
It's tempting to treat status codes as basically binary — success or failure — but the specific code carries real information that changes how your code (or you, debugging) should respond:
- A 401 should typically trigger a re-authentication flow (refresh the token, redirect to login).
- A 403 shouldn't trigger a re-login attempt — the user is already correctly authenticated; retrying login won't fix a permissions problem.
- A 429 should trigger a backoff-and-retry, ideally respecting a
Retry-Afterheader if the server provides one, rather than immediately hammering the endpoint again. - A 5xx generally means retrying might work (the server had a transient problem), whereas retrying a 4xx with the exact same request will almost always fail again, since the problem is with the request itself.
Treating all errors identically — showing a generic "something went wrong" for every non-200 response — throws away information that would let both your code and your users respond more usefully.
A practical way to explore status codes as you encounter them
Rather than memorizing the full list, it's more useful to look codes up as you actually run into them, with the context of what caused it. An HTTP Status Code Explorer that lets you search by code or by name is faster than searching generically online mid-debugging session, and keeps the explanation in the same place you're already working.
Frequently asked questions
What's the difference between a 401 and a 403 error?
401 Unauthorized means authentication is missing or invalid — the server doesn't know who you are, or your credentials failed. 403 Forbidden means you're authenticated successfully, but you don't have permission to access this specific resource. If you see a 403, logging in again won't help; the account itself lacks permission.
What's the difference between a 404 and a 500 error?
A 404 means the requested resource simply doesn't exist — a client-side issue, like a mistyped URL or a deleted page. A 500 means the server encountered an error while trying to process a request that was otherwise valid — a server-side problem, often an unhandled bug or exception in the application code.
Should I use a 301 or 302 redirect?
Use 301 for a permanent move — when the old URL should stop being used going forward, and you want search engines to transfer ranking authority to the new URL. Use 302 for a temporary redirect, where the original URL is still the canonical one and should remain indexed as such.
What does a 429 status code mean and how should I handle it?
429 Too Many Requests means you've exceeded a rate limit. The correct response is to back off and retry after a delay, ideally respecting a Retry-After header if the API provides one, rather than immediately retrying the request, which will likely just trigger the rate limit again.