Every HTTP Status Code You Will Actually Encounter — Explained

HTTP status codes — Chunky Munster

HTTP status codes are the server’s quick way of telling you what happened to a request. If you can read them without guessing, you can debug APIs, browser issues, and deploy problems faster; if you want a live reference, give the HTTP status codes tool a spin.

You do not need the entire RFC memorized. In real work, a small set of codes covers most of what you’ll see, and the first digit already tells you the shape of the problem.

The five status code families

HTTP groups responses by the first digit. That’s the part worth learning first, because it gives you the right mental model before you care about the exact code.

That grouping is not just trivia. In logs, monitoring, and incident chats, it tells you where to start looking. A 404 points you at routes or URLs. A 500 points you at application code, upstream services, or infrastructure.

The codes you will actually see most often

Some status codes show up constantly. Others exist, but in the wild they’re rare enough that you can safely treat them like edge-case archaeology.

If you remember only a handful, start with 200, 201, 204, 301, 302, 304, 400, 401, 403, 404, 409, 422, 429, 500, 502, 503, and 504. That is enough to make most HTTP traces legible.

How to read a status code in context

A status code never lives alone. You need the request method, URL, headers, and response body to understand what the server is saying.

For example, a 404 on GET /users/123 usually means the user does not exist or the route is wrong. A 404 on POST /users/123 might mean the endpoint is not implemented at all. The same code can mean different things depending on the method and the API design.

Body content matters too. Many APIs return JSON errors like this:

{
  "error": "validation_failed",
  "fields": {
    "email": "must be a valid email address"
  }
}

Here, the status might be 422 or 400, but the JSON tells you exactly what broke. In browser devtools, curl output, CI logs, and reverse proxy traces, that extra payload is usually the real clue.

If you need a broader refresher on request/response anatomy, our guide on what happens when a browser turns a URL into a request fits neatly beside this one.

Common debugging patterns

Status codes are most useful when you connect them to repeatable failure patterns. That keeps you from chasing the wrong layer of the stack.

A few patterns come up all the time:

When you see a server-side code, check where the failure originated. A load balancer, API gateway, CDN, app server, and database can all emit their own version of “something went wrong,” and the status code often tells you which layer complained first.

For command-line checks, curl -i https://example.com/api/users is still a reliable move. The -i flag shows headers, which makes redirects, cache behavior, and auth responses easier to spot.

What APIs should return, and why it matters

Good APIs use status codes consistently. That makes them predictable for clients, tests, retries, and alerting.

For create operations, 201 Created is usually better than a flat 200 OK, because it signals that something new exists now. For deletions, 204 No Content keeps the response clean when there is nothing useful to return. For invalid input, 400 or 422 is far more helpful than hiding the failure behind a generic 500.

Retries should also depend on the code. A client can often retry 502, 503, or 504 safely if the operation is idempotent. Retrying 401 without fixing the token is pointless, and retrying a 409 without changing the request will just hammer the same conflict.

Rule of thumb: if the client can fix it, it is usually a 4xx. If the server or an upstream dependency failed, it is usually a 5xx.

Before and After

Here is a practical example of how status codes change the debugging story. The first version leaves you guessing; the second version tells you what to fix.

Before

POST /api/login
Response: 500 Internal Server Error
Body: {"error":"something went wrong"}

After

POST /api/login
Response: 401 Unauthorized
Body: {"error":"invalid_credentials"}

POST /api/profile
Response: 422 Unprocessable Entity
Body: {
  "error": "validation_failed",
  "fields": {
    "displayName": "must be at least 3 characters"
  }
}

In the first case, the backend hides a user error behind a server error. In the second and third cases, the client gets a precise signal: bad credentials in one path, validation problems in another. That is easier to debug, easier to test, and easier to automate against.

Here is another quick example with redirects:

GET /docs
Response: 301 Moved Permanently
Location: /docs/

GET /docs/
Response: 200 OK
Body: documentation page

That trailing slash matters more than people like to admit. Misconfigured redirects can create broken links, duplicate content, or weird cache behavior that only shows up under load.

Frequently Asked Questions

What is the difference between 401 and 403?

401 Unauthorized means the request lacks valid authentication, or the login token failed. 403 Forbidden means the server knows who you are, but you still do not have permission. In practice, 401 often means “log in again,” while 403 means “your account cannot do this.”

Is 404 a client error or a server error?

404 Not Found is a client-side error, so it sits in the 4xx family. It usually means the URL is wrong, the resource was deleted, or the server is intentionally hiding whether it exists. If you see a 404 in production, check routing, deployment assets, and base paths before blaming the backend.

What does 500 Internal Server Error actually mean?

500 is a generic server failure. It means the server hit an unexpected problem and could not complete the request, but it does not tell you which subsystem failed. You usually need logs, stack traces, or upstream service errors to find the real cause.

Why do APIs use 422 instead of 400?

Some APIs use 422 Unprocessable Entity to mean the JSON was well-formed, but the data failed business rules or validation. 400 Bad Request is broader and often covers malformed syntax or missing required fields. The exact split is a design choice, but consistency matters more than the specific number.

Wrapping Up

HTTP status codes are not just decoration on the response line. They are the shortest possible summary of what happened, and once you know the common ones, you can spot routing bugs, auth issues, rate limits, proxy failures, and backend crashes much faster.

Start by learning the families, then memorize the codes you keep seeing in your own logs. If you work with APIs often, it helps to keep a reference open while you debug so you do not have to decode everything from memory.

When you need a fast lookup, use the HTTP status codes tool and keep moving. Less guessing, fewer dead ends, cleaner logs.

// try the tool
give the HTTP status codes tool a spin →
// related reading
← all posts