HTTP Status Codes: A Developer's Cheat Sheet (With Fixes for the Common Errors)
Engineering

HTTP Status Codes: A Developer's Cheat Sheet (With Fixes for the Common Errors)

A practical HTTP status code cheat sheet: what every code class means, the ~25 codes you'll actually hit, and how to fix the common 4xx and 5xx errors — with curl examples and a quick client-vs-server guide.
HTTP Status Codes: A Developer's Cheat Sheet (With Fixes for the Common Errors)
NI
Nikolas Dimitroulakis
Last updated on July 01, 2026

HTTP Status Codes: A Developer's Cheat Sheet (With Fixes for the Common Errors)

Introduction

An HTTP status code is a three-digit number a server returns with every response to tell the client what happened to the request — whether it succeeded, was redirected, failed because of something the client did, or failed on the server. The first digit sets the class: 1xx informational, 2xx success, 3xx redirection, 4xx client error, 5xx server error.
That first digit is the fastest triage tool you have. A 4xx means fix your request; a 5xx means the problem is on the server side. You can read any response's status directly:
1
curl -i https://api.example.com/users
1
HTTP/1.1 200 OK
2
Content-Type: application/json
The status line (HTTP/1.1 200 OK) is the code and its reason phrase. Everything below is about knowing what each one means and, for the ones that break things, what to do about it.

The five classes at a glance

ClassRangeMeaningWhose move is it?
1xx100–103Informational — request received, still processing.Neither; interim.
2xx200–206Success — the request worked.Done.
3xx300–308Redirection — more steps needed to complete.Usually the client (follow the redirect).
4xx400–429Client error — the request was wrong.You. Fix the request.
5xx500–504Server error — the server failed to fulfill a valid request.The server. Retry may help for some.

The cheat sheet: the codes you'll actually meet

These are the ~25 codes that come up in day-to-day API and web work. The rarer ones exist, but if you know these you can read almost any response.
CodeNameWhat it meansTypical cause / fix
200OKStandard success, response has a body.Nothing to do.
201CreatedA resource was created.Read the Location header for the new resource URL.
202AcceptedRequest accepted, processing async.Poll a status endpoint or wait for a webhook.
204No ContentSuccess, no body returned.Common for DELETE/PUT. Don't parse a body.
206Partial ContentA range of the resource was returned.Response to a Range request (resumable downloads).
301Moved PermanentlyResource has a new permanent URL.Update your stored URL to the Location value.
302FoundTemporary redirect.Follow Location; don't cache the redirect.
304Not ModifiedCached copy is still valid.Response to a conditional request (ETag/If-None-Match); serve from cache.
307Temporary RedirectTemporary, method preserved.Re-send the same method to Location.
308Permanent RedirectPermanent, method preserved.Update the URL; keep the original method.
400Bad RequestRequest is malformed.Fix syntax, JSON, or missing required fields.
401UnauthorizedNot authenticated.Send valid credentials; check the WWW-Authenticate header.
403ForbiddenAuthenticated but not permitted.Check roles/permissions on the resource.
404Not FoundResource or route doesn't exist.Verify the path and the resource ID.
405Method Not AllowedWrong HTTP method for the resource.Switch to a method in the Allow header.
406Not AcceptableServer can't match your Accept header.Relax or correct the requested content type.
408Request TimeoutClient took too long to send the request.Retry; check network and payload size.
409ConflictRequest conflicts with current state.Re-fetch, resolve the conflict, retry (e.g. version mismatch).
410GoneResource permanently removed.Stop calling it; there's no new location.
415Unsupported Media TypeServer rejects the payload's format.Set the correct Content-Type (e.g. application/json).
422Unprocessable ContentSyntax is fine but validation failed.Fix the field values, not the request format.
429Too Many RequestsYou've hit a rate limit.Back off; honor the Retry-After header.
500Internal Server ErrorGeneric server-side failure.Server-side bug; retry, then report if it persists.
501Not ImplementedServer doesn't support the method at all.Different from 405 — the server never handles this method.
502Bad GatewayAn upstream server returned an invalid response.Usually transient; retry with backoff.
503Service UnavailableServer overloaded or down for maintenance.Honor Retry-After; retry with backoff.
504Gateway TimeoutAn upstream server didn't respond in time.Retry; check upstream health and timeouts.

2xx: success isn't just 200

Most developers reach for 200 for everything, but the distinctions carry information. 201 Created tells a client a new resource exists and where to find it (in the Location header). 202 Accepted signals asynchronous work — the request was taken but isn't finished, so the client should poll or wait for a callback rather than treat the response as final. 204 No Content is a success with deliberately no body, standard for a DELETE or an update that returns nothing — parsing it as JSON will throw.

3xx: redirects and the method trap

Redirects look simple until a POST turns into a GET. Historically, clients following a 301 or 302 often switched the method to GET, which silently breaks a form submission or an API write. If you need the method preserved across a redirect, the correct codes are 307 (temporary) and 308 (permanent), which mandate keeping the original method. 304 Not Modified is a different animal — it's the payoff of conditional requests: send an If-None-Match with a stored ETag, and a 304 means your cache is still good and no body is sent.

4xx: the client errors you'll debug most

This is where most day-to-day debugging lives. The trap is that several of these codes look interchangeable and aren't:
  • 400 vs 422400 Bad Request means the request is malformed (broken JSON, wrong syntax). 422 Unprocessable Content means the request parsed fine but failed validation (an email field with no @, a negative quantity). If you're getting a 422, stop checking your syntax and start checking your values.
  • 401 vs 403401 Unauthorized is about authentication: you're not logged in, or your token is missing or expired. 403 Forbidden is about authorization: you're authenticated, but you're not allowed to do this. A 401 says who are you; a 403 says you can't.
  • 404 vs 405404 Not Found means the route doesn't exist. 405 Method Not Allowed means the route exists but rejects your verb. These get confused constantly, and the fix is entirely different — see the dedicated guide on 405 Method Not Allowed for how to read the Allow header and resolve it.
  • 409 Conflict — the request clashes with the resource's current state, most often a version mismatch on a concurrent update. Re-fetch the latest state, reapply your change, and retry.
  • 429 Too Many Requests — you've exceeded a rate limit. The response frequently includes a Retry-After header telling you how long to wait:
1
HTTP/1.1 429 Too Many Requests
2
Retry-After: 30
3
Content-Type: application/json
4
5
{"error": "rate limit exceeded", "retry_after": 30}
Honoring Retry-After (here, 30 seconds) with exponential backoff is the correct handling — hammering a 429 just extends the block.

5xx: when it's the server, not you

A 5xx means the server received a valid request and failed to handle it. The practical difference between them tells you whether retrying is worth it:
  • 500 Internal Server Error — a generic, unhandled server-side failure. There's nothing to fix in your request; retry once, and if it persists it's a bug to report.
  • 502 Bad Gateway — a gateway or proxy got an invalid response from an upstream server. Usually transient — retry with backoff.
  • 503 Service Unavailable — the server is overloaded or in maintenance. Like a 429, it may include a Retry-After header; honor it.
  • 504 Gateway Timeout — a gateway didn't get a response from an upstream server in time. Retry, and if you control the upstream, check its health and timeout settings.
The rule of thumb: 500 and 501 are rarely worth an immediate retry; 502, 503, and 504 are transient often enough that a retry with backoff is the right default.

How to inspect a status code

You don't need to guess. Fire the request and read the status line and headers directly.
With curl, the -i flag includes the response headers so you see the status and the diagnostic headers (Allow, Retry-After, Location, WWW-Authenticate) that tell you what to do next:
1
curl -i -X POST https://api.example.com/orders \
2
-H "Content-Type: application/json" \
3
-d '{"item": "sku_123"}'
For interactive work, an API client makes this repeatable. Voiden is an offline-first, Git-native client that stores each request as a Markdown-based .void file committed alongside your code — so the exact call that produced a 409 or a 422 is versioned and reproducible by anyone on the team, not stuck in one person's local tool. It's open source (Apache 2.0) and you can download it here.

Where ApyHub Fits

Reading status codes is one problem; getting consistent, well-documented ones across every API you call is another. When you're wiring up ten different services, each with its own conventions for what a 422 body looks like or whether it returns 200 or 201 on create, the inconsistency is its own source of bugs.
ApyHub is a certified API marketplace — a catalog of 200+ APIs and 1,000+ endpoints for common utility work (file conversion, validation, PDF processing, data enrichment, and more). Every endpoint in the catalog ships with a documented, machine-readable specification, including its methods and response shapes, so status-code behavior is predictable before you write the integration — and readable by AI agents consuming the catalog over MCP, not just by humans. It won't stop upstream services from returning a 503, but it removes the guesswork about what a given endpoint returns and when.

Conclusion

HTTP status codes are a diagnostic language, not noise. The class digit tells you whose problem it is, the specific code tells you what went wrong, and the response headers — Allow, Retry-After, Location, WWW-Authenticate — usually tell you how to fix it. Bookmark the table above, learn the pairs that get confused (401/403, 404/405, 400/422, 502/503/504), and most "mystery" errors stop being mysteries.

FAQ

What are the five classes of HTTP status codes?

1xx is informational, 2xx is success, 3xx is redirection, 4xx is a client error (the request was wrong), and 5xx is a server error (the server failed on a valid request). The first digit tells you which class a code belongs to.

How do I know if an error is my fault or the server's?

Read the first digit. A 4xx code means the problem is in your request — wrong URL, method, credentials, or data — so fixing the request resolves it. A 5xx means the server failed, and the fix is server-side, though retrying with backoff helps for 502, 503, and 504.

What's the difference between 401 and 403?

401 Unauthorized means you're not authenticated — your credentials are missing, invalid, or expired. 403 Forbidden means you're authenticated but not permitted to perform the action. In short: 401 is about identity, 403 is about permission.

What's the difference between 400 and 422?

400 Bad Request means the request is malformed — broken JSON or invalid syntax the server can't parse. 422 Unprocessable Content means the request was parsed successfully but failed validation, such as a field with an invalid value. A 422 points you at your data, not your formatting.

What's the difference between 404 and 405?

404 Not Found means the route or resource doesn't exist. 405 Method Not Allowed means the route exists but doesn't accept the HTTP method you used, and the response includes an Allow header listing the methods it does accept. See the 405 Method Not Allowed guide for the full fix.

How should I handle a 429 Too Many Requests error?

Stop sending requests and wait. If the response includes a Retry-After header, wait that many seconds before retrying; otherwise use exponential backoff. Repeatedly retrying immediately typically extends the rate-limit block rather than resolving it.

Which HTTP errors are safe to retry?

Transient server errors — 502 Bad Gateway, 503 Service Unavailable, and 504 Gateway Timeout — are worth retrying with backoff, and 429 after honoring any Retry-After. A 500 is worth one retry at most, and 4xx errors like 400, 401, and 404 won't fix themselves on retry — you have to change the request.

What does a 304 Not Modified mean?

It's the successful result of a conditional request: you sent a stored validator (an ETag via If-None-Match, or a date via If-Modified-Since), and the server confirmed your cached copy is still current, so it returned no body. Serve the resource from your cache rather than re-downloading it.