HTTP Status Codes Explained: The Ones You Actually Need to Know
404 and 500 you already know. But 401 vs 403, 301 vs 302, and 429 trip up developers constantly — and getting them wrong quietly breaks debugging, SEO, and API integrations. Here's what each family actually means and when to use which.
EDTechToolsCenter EditorialEvery HTTP response carries a three-digit status code, and most developers know maybe ten of them by instinct — 200, 404, 500 — and guess at the rest. That's usually fine until it isn't: an API returns 403 when it means 401, a redirect uses 302 when it should use 301 and quietly costs a page its search ranking, or a bug in an error handler swallows a real failure and returns 200 anyway, hiding the problem from every tool downstream that trusts status codes to mean what they say. Status codes are a small, fully specified vocabulary — there's no ambiguity in what each one is supposed to mean, only in how consistently they're actually used. This is a working reference for the codes you'll actually run into, grouped the way the HTTP spec groups them, plus the mix-ups that cause real bugs.
The five families, at a glance
Every status code's first digit tells you its category before you even need to know the specific number: 1xx is informational (rare in normal application work), 2xx means success, 3xx means redirection, 4xx means the client did something the server won't accept, and 5xx means the server itself failed. That first digit alone is often enough to route your handling logic — retry logic, for instance, generally makes sense for some 5xx codes and never for 4xx codes, since a 4xx means the request itself was the problem and retrying the identical request will fail identically.
Sponsored
2xx — success, but not all successes look the same
200 OK is the default success response and covers the overwhelming majority of successful requests, but a few more specific 2xx codes exist for good reason and using them correctly makes an API meaningfully easier for a client to reason about.
- 200 OK — the request succeeded and the response body contains the result. The universal default.
- 201 Created — specifically for a request (typically POST) that created a new resource. A well-behaved API also returns a Location header pointing at the new resource, so the client doesn't have to guess its URL.
- 202 Accepted — the request was accepted for processing but isn't complete yet, common for async or queued work (a job submitted for background processing, for instance). This tells the client 'this succeeded, but check back for the actual result' rather than implying the work is done.
- 204 No Content — the request succeeded and there's deliberately no response body, common for DELETE requests or updates where returning the full resource back isn't necessary.
- 206 Partial Content — returned when a client requests part of a resource via a Range header, common in video streaming and resumable downloads.
3xx — redirection, and where 301 vs 302 actually matters
This is the family that causes the most real, measurable damage when used carelessly, because search engines treat different 3xx codes differently, and the difference compounds silently over time rather than failing loudly.
- 301 Moved Permanently — this URL has permanently moved; search engines transfer the old URL's ranking signals to the new one, and browsers/clients are expected to update any cached reference to point at the new URL going forward. Use this for a genuine permanent move — a page renamed, a site restructured, a domain migrated.
- 302 Found — a temporary redirect. Ranking signals stay with the original URL, since search engines are explicitly told 'this is temporary, don't transfer authority yet.' Using 302 for what's actually a permanent move is one of the more common, quietly damaging SEO mistakes — the new URL never properly accumulates the old page's authority because every signal keeps saying 'temporary.'
- 304 Not Modified — sent in response to a conditional GET (using If-Modified-Since or If-None-Match headers) when the cached version the client already has is still valid. No body is sent, saving bandwidth — this is a core mechanism behind effective browser and CDN caching.
- 307 Temporary Redirect / 308 Permanent Redirect — functionally like 302/301 but with one important guarantee 301/302 don't strictly make: the request method and body are preserved on the redirect. A POST redirected with 302 is, by older spec behaviour, often re-sent as a GET by browsers; a POST redirected with 307 stays a POST. This matters for form submissions and API calls specifically.
4xx — the client did something the server won't accept
This family gets misused constantly, mostly around two specific pairs that genuinely are confusing on first encounter.
- 400 Bad Request — the request itself is malformed: invalid syntax, a missing required field, a value that fails basic validation. This is about the request's shape, not who's making it.
- 401 Unauthorized — despite the name, this means 'you are not authenticated' — the server doesn't know who you are, or your credentials weren't provided or weren't valid. A 401 should come with a WWW-Authenticate header indicating how to actually authenticate.
- 403 Forbidden — the server knows exactly who you are (you're authenticated) but you don't have permission to do this specific thing. The distinction that trips people up: 401 means 'log in'; 403 means 'you're logged in, but no.' Returning 403 for someone who isn't authenticated at all is a common mislabeling that makes API error handling harder to write correctly, since a client can't tell from the code alone whether retrying with credentials would help.
- 404 Not Found — no resource exists at this URL. Straightforward in theory, but a common real bug is a soft 404: a page that displays 'not found' content while the server actually returns 200, which search engines and monitoring tools take at face value as a working page rather than a missing one, quietly polluting both search indexing and uptime metrics.
- 405 Method Not Allowed — the resource exists, but doesn't support this HTTP method (a POST to an endpoint that only accepts GET, for instance). Should include an Allow header listing the methods that are actually supported.
- 409 Conflict — the request conflicts with the current state of the resource, most commonly during concurrent updates — two clients trying to update the same record based on stale data.
- 422 Unprocessable Entity — the request is syntactically valid (unlike 400) but semantically wrong — the JSON parses fine, but a field fails business-logic validation, like an email address in the wrong format or a date that's logically impossible. Many APIs use 400 for this instead of 422, which isn't strictly wrong but loses a useful distinction for clients trying to differentiate a malformed request from a semantically invalid one.
- 429 Too Many Requests — you've hit a rate limit. A well-behaved API includes a Retry-After header telling the client how long to wait before trying again, which a well-behaved client should actually respect rather than retrying immediately.
5xx — the server's fault, and what each one actually implies for debugging
- 500 Internal Server Error — a generic catch-all for 'something went wrong on the server and we don't have a more specific code for it.' In practice this is often an unhandled exception — the first place to look when debugging is application logs, not the client.
- 502 Bad Gateway — a server acting as a gateway or proxy got an invalid response from an upstream server it was relying on. This points debugging toward the upstream service or load balancer, not the client-facing application code itself.
- 503 Service Unavailable — the server is temporarily unable to handle the request, commonly due to overload or planned maintenance. Should ideally include a Retry-After header, same as 429, so well-behaved clients know when to try again rather than hammering a struggling server.
- 504 Gateway Timeout — similar to 502, but specifically means the upstream server didn't respond in time, rather than responding with something invalid. Points toward a slow or hung upstream dependency as the actual root cause.
How status codes affect SEO — and why soft 404s are worse than real ones
Search engines use status codes as a primary signal for how to treat a URL going forward, which means getting them wrong doesn't just confuse a human reading the response — it actively misdirects a crawler's model of your site. A real 404 is honest and, while not ideal to have many of, is at least correctly understood: the crawler learns the page doesn't exist and eventually stops indexing it. A soft 404 — a page that shows 'not found' content but returns HTTP 200 — is worse specifically because it's dishonest to the crawler: the page gets treated as a real, valid, indexable page with thin or missing content, which can quietly drag down how the rest of the site is evaluated. The same logic applies to redirects: a 302 used for what's actually a permanent move leaves the old URL competing with the new one indefinitely instead of consolidating ranking signal onto the new URL the way a 301 would.
How to actually check the status code of a request
Your browser's DevTools Network tab shows the status code for every request a page makes — open it, reload the page, and click any request to see its status alongside full response headers, which is the fastest way to debug a single page's behaviour interactively. From a terminal, `curl -I https://example.com` sends a HEAD request and prints just the response headers including status, without downloading the full body — useful for quickly checking redirects or confirming a fix without opening a browser. For inspecting the JSON body an API actually returned alongside its status code, our JSON Formatter is a fast way to pretty-print and validate the response once you've copied it out of DevTools or curl's output.
Common mistakes worth specifically avoiding
- Returning 200 for an error response with an error message in the body — this breaks every piece of tooling (monitoring, retries, client error handling) that reasonably assumes status codes reflect actual outcome.
- Using 403 when the real issue is that the user isn't authenticated at all — that's 401's job, and conflating the two makes client-side error handling genuinely harder to write correctly.
- Using a 302 redirect for a permanent URL change, quietly preventing search engines from transferring ranking signal to the new URL.
- Serving 'not found' page content with a 200 status (a soft 404), which search engines and uptime monitors both take at face value.
- Omitting the Retry-After header on 429 and 503 responses, leaving well-behaved clients to guess how long to back off.
- Treating every 4xx as retry-worthy — a 4xx generally means the request itself needs to change, and retrying it unmodified will just fail the same way again.
- Building custom, non-standard status codes for application-specific states instead of using an existing code plus a descriptive body — this breaks generic HTTP tooling that only understands the standard set.
A quick mental model for debugging by status code
When you see a status code you didn't expect, the first digit tells you where to start looking before you even read documentation for the specific code. A 4xx means look at what you sent — the request itself, its headers, its body, your credentials. A 5xx means look at what came back from the server side — logs, upstream dependencies, infrastructure — since the request was accepted as valid but something failed processing it. A 3xx means look at where you're actually ending up — follow the redirect chain (DevTools shows this clearly) and confirm it lands where you expect, since redirect loops and unexpected chains are a common, hard-to-spot source of slow or broken requests. This alone won't replace reading the specific code's meaning, but it's a fast first triage step before diving into logs or documentation.
Tools used in this article
Sponsored
Frequently asked questions
401 Unauthorized means the server doesn't know who you are — you're not authenticated. 403 Forbidden means the server knows who you are but you don't have permission for this specific action. 401 says 'log in'; 403 says 'you're logged in, but no.'
TechToolsCenter Editorial
How-to Guides
Our editorial desk publishes step-by-step tutorials, comparisons and productivity tips for everyday digital tasks.
Related articles
What Is Rate Limiting, and How Does It Actually Work?
A 429 error isn't your code failing — it's an API telling you, quite specifically, to slow down. Here's what's actually enforcing that, and how to work with it instead of against it.
CORS Explained: Why Your API Requests Get Blocked (and How to Fix It)
"Blocked by CORS policy" is one of the most common errors in web development — and one of the most commonly misunderstood, since the fix almost never lives where the error appears.
How to Validate and Beautify JSON Online (and Actually Fix It)
Why JSON.parse errors are so unhelpful, how a proper JSON formatter pinpoints the exact broken character, and a practical workflow for cleaning up messy API responses.