Skip to main content

HTTP Status Codes by Class: What 200, 301, 404, 429, and 502 Actually Tell You

A practical guide to HTTP status codes by class. What 2xx, 3xx, 4xx, and 5xx mean, the codes you hit most, and how to read them while debugging an API.

Published By Li Lei
#http #api #debugging #web-development #status-codes

HTTP Status Codes by Class: What 200, 301, 404, 429, and 502 Actually Tell You

Every HTTP response carries a three-digit number, and most of us learned them by accident: 200 means it worked, 404 means it didn't, and the rest is a blur until something breaks at 2 a.m. The good news is that the numbers are not random. The first digit sets the class, so before you read anything else, that one digit already tells you who is to blame. Learn the five bands and you can triage almost any response without opening a spec.

Here is the whole map in one line: 2xx means it worked, 3xx means go somewhere else, 4xx means your request is wrong, and 5xx means the server failed. (1xx is informational and you rarely see it in application code.) Everything below is just detail hanging off those four ideas.

The first digit is the whole story

When a response lands, read the leading digit first.

  • 1xx Informational — the server received the request and is still working. You almost never handle these directly; 100 Continue and 101 Switching Protocols (for WebSocket upgrades) are the only two most developers ever meet.
  • 2xx Success — the request was received, understood, and accepted.
  • 3xx Redirection — there is more to do, usually following a redirect to a new location.
  • 4xx Client Error — the request itself is wrong. Bad syntax, missing auth, a resource that isn't there. Retrying the exact same request will get you the exact same error.
  • 5xx Server Error — the request was fine, but the server failed to fulfil it. This one is not your fault, and a retry might actually succeed.

That last distinction is the one that saves the most time. A 4xx tells you to fix the request; a 5xx tells you to look at the server or backend. If you internalise nothing else, internalise that boundary.

The 2xx codes: more than just 200

200 OK is the workhorse, but it is not always the right answer. When a POST creates a new resource, the correct response is 201 Created, and you should put the new resource's address in the Location header so the client knows where it lives. A long-running job that you accepted but haven't finished yet is 202 Accepted. A DELETE that succeeded with nothing to return is 204 No Content.

Reaching for a generic 200 everywhere isn't wrong enough to break clients, but it throws away information. A REST client that sees 201 knows a record was created and where to find it. One that sees a bare 200 has to guess.

The 3xx codes: where redirects live (and SEO breaks)

The redirect family is small but full of traps. The argument that comes up in every review is 301 vs 302:

  • 301 Moved Permanently — the URL changed forever. Search engines pass ranking signals to the new address. Use it for an http-to-https switch or a renamed page.
  • 302 Found — a temporary detour. The original URL stays canonical. Use it for a maintenance page or a post-login bounce.

Shipping a 302 for a permanent move is one of the most expensive small bugs in web work: the old URL keeps the rankings while the new one starves. If the request method must be preserved across the redirect, use 308 (permanent) or 307 (temporary) instead. And 304 Not Modified is the quiet hero of caching — it tells the browser to use its cached copy, saving a full download.

The 4xx codes: your request is wrong

This is the busiest band in day-to-day work, and two pairs cause most of the confusion.

401 vs 403. The names are backwards from intuition. **401 Unauthorized actually means you are not authenticated — no valid credential was provided, and the response should carry a WWW-Authenticate header telling the client how to log in. 403 Forbidden means you are authenticated but not allowed** — like a normal user hitting an admin route. Re-logging in fixes a 401. It does nothing for a 403. Swap these two and you send users into a useless login loop.

404 vs 410. Both say "not here," but 404 Not Found is non-committal while 410 Gone is a deliberate, permanent removal. Crawlers keep retrying a 404 for weeks; a 410 gets dropped from the index fast.

Then there's 422 Unprocessable Content — the request parsed fine but a field failed business validation. And 429 Too Many Requests, which means you tripped a rate limit. A well-behaved server sends a Retry-After header; a polite client backs off for that many seconds instead of hammering the endpoint. If you see 429 in production, slow your request rate, batch calls, or ask for more quota.

The 5xx codes: the server failed

When the leading digit is 5, stop debugging your request and look at the server.

  • 500 Internal Server Error — an unhandled exception or bug in the application. Check the server logs, not your payload.
  • 502 Bad Gateway — a proxy or load balancer got a broken reply from the app behind it. Often the app crashed or isn't listening.
  • 503 Service Unavailable — the server is down, overloaded, or in maintenance. This one is frequently transient, and a retry after the Retry-After delay often works.
  • 504 Gateway Timeout — the backend is alive but too slow to answer in time.

Retrying a 4xx without changing the request is pointless. Retrying a 503 after the suggested delay is exactly the right move.

A worked example: reading a status code while debugging an API

Here is a real shape of the problem. I was wiring a frontend form to a backend endpoint, and my fetch call kept coming back red. I had spent ten minutes rereading my JSON payload, convinced I'd fumbled a comma, before I actually looked at the status line: 422.

That single number reframed the whole hunt. A 4xx meant my request was the problem — fine — but 422 specifically means the body parsed correctly and a field failed validation. So there was no syntax error to find; I'd been searching for a bug that didn't exist. I checked the response body, saw "email": "must be unique", and realised I was re-submitting an address already in the database. The fix took thirty seconds once I read the code instead of guessing.

The lesson stuck: read the status line first. If it had been 500, I'd have gone straight to the server logs. If it had been 401, I'd have checked my auth token. If it had been 502, I'd have checked whether the backend was even up. The number tells you which direction to look before you read a single line of the body. When the body is JSON and you do need to dig in, paste it into a JSON formatter so the validation errors are actually readable.

Keeping the map handy

Nobody memorises all sixty-odd codes, and you don't need to. You need the four classes in your head and a fast way to look up the specifics — the exact meaning of 423, whether 308 preserves the method, what 426 is asking for. That's why I keep the HTTP Status Code Reference one tab away while building: type a number to jump straight to it, or search a phrase like "rate limit" or "redirect" to find the right code by intent.

Read the first digit, trust what it tells you about whose fault it is, and let a quick lookup fill in the rest. Most "mysterious" API failures stop being mysterious the moment you actually read the number.


Made by Toolora · Updated 2026-06-13