HTTP Status Codes Explained: The Complete Cheat Sheet
A status code is the API telling you, in three digits, how the request went. Most of the time you only care about two of them: 200 (fine) and 500 (broken). But the day an integration breaks, the difference between a 401 and a 403, or a 400 and a 422, is the difference between fixing it in a minute and guessing for an hour.
This is the reference I keep open. Skim the table, then read the section on the codes you actually run into, because those are the ones with real gotchas.
The five classes
Every code starts with a digit that tells you the category before you even read the rest:
- 1xx - informational. You almost never see these.
- 2xx - success. The request worked.
- 3xx - redirection. Go look somewhere else.
- 4xx - client error. You sent something wrong.
- 5xx - server error. They broke, not you.
That first digit is the fastest triage you have. A 4xx means stop and check your request. A 5xx means the problem is on the server and retrying (or waiting) may be the move.
The cheat sheet
The codes you will actually meet, what they mean, and the usual fix:
| Code | Meaning | When you hit it / fix |
|---|---|---|
| 200 | OK | The request succeeded. Nothing to do. |
| 201 | Created | A POST created a resource. Check the Location header for its URL. |
| 204 | No Content | Success, but there is no body (common on DELETE). Do not try to parse JSON. |
| 301 / 308 | Moved Permanently | The URL changed for good. Update your saved endpoint. |
| 302 / 307 | Found / Temporary Redirect | Temporary move. Follow the Location header. |
| 304 | Not Modified | Your cached copy is still good. Not an error. |
| 400 | Bad Request | The server could not parse your request. Malformed JSON, wrong types, missing fields. |
| 401 | Unauthorized | You are not authenticated. Missing or bad token. (Yes, the name is wrong.) |
| 403 | Forbidden | Authenticated, but not allowed. Wrong permissions or scope. |
| 404 | Not Found | The resource or route does not exist. Check the path and the ID. |
| 405 | Method Not Allowed | Right URL, wrong verb. You sent GET where it wants POST, etc. |
| 409 | Conflict | A duplicate or a version clash. Common on create-if-not-exists. |
| 415 | Unsupported Media Type | Set the right Content-Type header (usually application/json). |
| 422 | Unprocessable Content | Valid syntax, but the data failed validation. Read the error body. |
| 429 | Too Many Requests | Rate limited. Back off and check the Retry-After header. |
| 500 | Internal Server Error | The server crashed on your request. Not your fault to fix; report or retry. |
| 502 | Bad Gateway | A proxy got a bad response from an upstream server. Usually transient. |
| 503 | Service Unavailable | Server is down or overloaded (or in maintenance). Retry later. |
| 504 | Gateway Timeout | An upstream server took too long. Check its health or your timeout. |
401 vs 403 (the one everyone mixes up)
These two get confused constantly, and the fix for each is completely different.
- 401 Unauthorized means "I do not know who you are." You are missing credentials, or your token is expired or malformed. The fix is on the auth side: send a valid token.
- 403 Forbidden means "I know who you are, and you are not allowed." Your credentials are fine, but this account or key lacks permission for this resource. Sending a fresh token will not help. You need the right role or scope.
Quick rule: 401 is about authentication, 403 is about authorization. If re-logging-in fixes it, it was a 401 problem.
400 vs 422 (malformed vs invalid)
Both are "your request is wrong," but at different layers, and good APIs use them precisely.
- 400 Bad Request means the server could not even parse what you sent. Broken JSON (a trailing comma, a missing quote), a wrong data type, or a missing required field. The request never made it to the business logic.
- 422 Unprocessable Content means the JSON parsed fine, but the values failed the rules. An email that is not an email, a date in the past, a quantity of -1. The syntax was valid; the meaning was not.
If you get a 400, check your JSON is even valid first (paste it into the JSON viewer to catch a stray comma). If you get a 422, stop fixing syntax and read the error body, because the server is telling you which field it rejected and why.
429 and the Retry-After header
A 429 means you hit a rate limit. The important part most people miss: well-behaved APIs send a Retry-After header telling you how many seconds to wait before trying again. Read it and back off, rather than hammering the endpoint and getting rate limited for longer. If you are looping requests in code, add exponential backoff.
See the real status code for any request
The fastest way to debug any of this is to send the request and read the actual code and response the server returns, without writing a script. Open the API tester, paste your URL, set the method, add your auth header, and send. It shows the status code, the response headers (including Retry-After and Location), and the formatted body. That is usually enough to tell a 401 from a 403, or spot the field a 422 is complaining about, in seconds.
If you are calling the API from your own frontend and seeing failures with no status code at all, that is often a CORS issue rather than an HTTP error. I covered that trap in how to test an API in your browser.
FAQ
What is the difference between 401 and 403?
401 means you are not authenticated (missing or bad credentials). 403 means you are authenticated but not permitted. Re-authenticating fixes a 401, not a 403.
Is 400 or 422 correct for a validation error?
Use 400 when the request cannot be parsed (malformed JSON, wrong types). Use 422 when it parses but fails validation rules. Many APIs use 400 for both, but 422 is more precise.
Should I retry on a 5xx?
Often yes, since 5xx errors are server-side and frequently transient. Retry 502, 503 and 504 with backoff. A persistent 500 usually needs the API owner to fix it.
What does 429 mean?
Too Many Requests. You are rate limited. Check the Retry-After header and slow down; add exponential backoff if you are sending requests in a loop.
Next time an API returns something unexpected, send it through the API tester to read the exact status code, headers, and body, then use the table above to find your fix.