The Complete HTTP Status Code Cheatsheet (2026)

#1HTTP status codes: the ones that actually matter
What we tested: We sent requests from our browser-based HTTP tools to test endpoints on localhost and remote servers. Header inspection, status code handling, and CORS preflight behavior were verified against Express.js, Fastify, and nginx backends.
Most teams only need a small subset of HTTP status codes, but the mistakes around them are expensive: confusing auth with permission, using the wrong redirect code, or returning 429 without Retry-After.
This reference focuses on the codes that affect real clients, caches, retries, and debugging.
#2The five classes
| Class | Meaning | Rule of thumb |
|---|---|---|
1xx | Informational | Request received, still processing. Rare in application code (100 Continue, 101 Switching Protocols). |
2xx | Success | The request succeeded. The specific code tells the client how. |
3xx | Redirection | Further action needed, usually a different URL. Method-preservation matters. |
4xx | Client error | The request is wrong: bad syntax, missing auth, not found. Retrying unchanged won't help. |
5xx | Server error | The server failed on a valid request. Retrying may help. |
The class alone tells the client whether the fault is theirs (4xx) or yours (5xx) and whether a retry is worth attempting. Getting the class right matters more than getting the exact code right.
#2The Fast-Lookup Table
The codes you'll actually reach for, with the one-line rule that governs each.
| Code | Name | Use it when |
|---|---|---|
200 | OK | Standard success with a body (GET, or POST/PUT that returns the resource). |
201 | Created | A POST/PUT created a new resource. Include a Location header pointing at it. |
202 | Accepted | Request accepted for async processing; work isn't done yet. |
204 | No Content | Success with no body (DELETE, or PUT that returns nothing). |
301 | Moved Permanently | Resource has a new canonical URL, forever. Caches and search engines update. |
302 | Found | Temporary redirect. Historically method-mangling, see below. |
304 | Not Modified | Conditional GET: the client's cached copy is still valid. |
307 | Temporary Redirect | Temporary, method-preserving, a POST stays a POST. |
308 | Permanent Redirect | Permanent, method-preserving. The safe permanent redirect. |
400 | Bad Request | Malformed syntax the server can't parse at all. |
401 | Unauthorized | Not authenticated, no or invalid credentials. Must send WWW-Authenticate. |
403 | Forbidden | Authenticated but not permitted. Re-authenticating won't help. |
404 | Not Found | Resource doesn't exist (or you're hiding its existence). |
405 | Method Not Allowed | URL exists, method doesn't. Must send an Allow header. |
409 | Conflict | Request conflicts with current server state (edit conflict, duplicate). |
410 | Gone | Like 404, but you're asserting it existed and is permanently removed. |
422 | Unprocessable Content | Syntax is valid, but the content fails validation (semantic error). |
429 | Too Many Requests | Rate limit hit. Send Retry-After. |
500 | Internal Server Error | Unhandled server-side failure. The catch-all you should minimize. |
502 | Bad Gateway | An upstream server returned an invalid response. |
503 | Service Unavailable | Temporarily down/overloaded. Send Retry-After if you can. |
504 | Gateway Timeout | An upstream server didn't respond in time. |
#2The Confusable Pairs (Where the Bugs Live)
#3401 vs 403, authentication vs authorization
401 Unauthorized means the server doesn't know who you are, no credentials, expired token, invalid signature. The name is a historical misnomer; it's really "Unauthenticated." A 401 must include a WWW-Authenticate header, and the correct client response is to (re)authenticate.
403 Forbidden means the server knows who you are and you still can't do this. Re-authenticating changes nothing; the identity simply lacks permission. If you don't want to reveal that a resource exists to unauthorized users, returning 404 instead of 403 is a legitimate information-hiding choice.
#3301 vs 302 vs 307 vs 308, the redirect matrix
The two axes are permanence and method preservation. Older 301/302 were specified loosely, and many clients "helpfully" rewrite a POST to a GET on redirect, which silently drops your request body. The 307/308 codes were introduced precisely to forbid that rewrite.
| Temporary | Permanent | |
|---|---|---|
| May change method (legacy) | 302 Found | 301 Moved Permanently |
| Must preserve method | 307 Temporary Redirect | 308 Permanent Redirect |
Rule: for a plain GET page move, 301 is fine and SEO-friendly. For anything that might be a POST, API endpoints, form handlers, use 307/308 so the method and body survive.
#3409 vs 422, conflict vs invalid
422 Unprocessable Content means the request was well-formed and parseable but semantically wrong: a required field is missing, an email is malformed, a value is out of range. This is your validation-failure code. (400 is for syntax the server can't even parse, use 422 for "I understood you, but this is invalid.")
409 Conflict means the request collides with the current state of the resource: an optimistic-locking version mismatch, a duplicate unique key, editing a record someone else just changed. The distinction: 422 is about the request in isolation; 409 is about the request relative to server state.
#3429 + Retry-After, rate limiting done right
429 Too Many Requests without a Retry-After header forces clients to guess when to retry, and they guess badly (tight retry loops that make the overload worse). Always send Retry-After, either seconds (Retry-After: 30) or an HTTP date. Pair it with RateLimit headers so well-behaved clients can self-throttle before they ever hit the wall.
#2Idempotency and Retry Semantics
Status class interacts with HTTP method idempotency to tell a client whether a retry is safe.
5xx, the server failed; a retry may succeed. Safe to retry automatically only for idempotent methods (GET,PUT,DELETE,HEAD). Retrying a non-idempotentPOSTon5xxrisks double-submission unless you use an idempotency key.4xx, the request is wrong; retrying it unchanged will fail again. Fix the request first. The exceptions are401(re-authenticate, then retry) and429(wait forRetry-After, then retry).3xx, follow theLocation, preserving the method only for307/308.
You can confirm exactly which method, headers, and body your client sends on retry with the HTTP request builder, and inspect the raw response, status line, headers, timing, with the REST API tester.
#3A minimal retry pattern in curl
Here's a shell snippet that implements the retry logic above, backing off on 429 and 5xx, re-authenticating on 401, and giving up on other 4xx:
#!/usr/bin/env bash
MAX_RETRIES=3
for i in $(seq 1 $MAX_RETRIES); do
STATUS=$(curl -s -o /dev/null -w '%{http_code}' \
-H "Authorization: Bearer $TOKEN" \
https://api.example.com/v1/orders)
case "$STATUS" in
2*) echo "OK ($STATUS)"; exit 0 ;;
429|5*) echo "Retry $i/$MAX_RETRIES (got $STATUS)"; sleep $((i * 2)) ;;
401) echo "Auth expired, refresh token"; exit 1 ;;
4*) echo "Client error $STATUS, fix the request"; exit 1 ;;
esac
done
echo "Exhausted retries"The key insight: 429 and 5xx are the only codes where retrying the same request is correct. Everything else needs a different request or no retry at all.
#2Related References
- HTTP status code reference, every code with its canonical description.
- HTTP methods reference, GET/POST/PUT/PATCH/DELETE semantics and idempotency.
- Headers builder, construct
Cache-Control,Retry-After,Location, andWWW-Authenticatecorrectly. - REST API tester, send requests and read the exact status and headers back.
#2Frequently Asked Questions
#3What is the difference between 401 and 403?
401 Unauthorized means you are not authenticated, the server has no valid credentials for you, so you should log in or send a valid token, and the response must include a WWW-Authenticate header. 403 Forbidden means you are authenticated but not authorized, your identity is known and simply lacks permission for this action, so re-authenticating will not help. A useful test: if presenting valid credentials could fix it, use 401; if the request would still be denied with perfect credentials, use 403. Some APIs deliberately return 404 instead of 403 to avoid confirming that a protected resource exists.
#3When should I use 301 vs 308 for redirects?
Use 301 Moved Permanently for permanent moves of resources fetched with GET, plain page URLs, canonical-URL consolidation, and SEO redirects, where it is well understood by search engines. Use 308 Permanent Redirect when the request might use a method other than GET, such as a POST to an API endpoint, because 308 guarantees the client preserves the original method and body. The risk with 301/302 is that many clients silently downgrade a POST to a GET on redirect, dropping the request body. For API endpoints, prefer 307/308; for GET-only web pages, 301 is the conventional and safe choice.
#3What is the correct status code for a validation error?
422 Unprocessable Content (formerly "Unprocessable Entity") is the right code when the request is syntactically valid, the server could parse it, but fails semantic validation, such as a missing required field, a malformed email, or an out-of-range value. Reserve 400 Bad Request for requests the server cannot parse at all, like malformed JSON. Use 409 Conflict when the problem is not the request in isolation but its collision with current server state, such as a duplicate key or an optimistic-locking version mismatch. Many APIs over-use 400 for everything; distinguishing 400, 422, and 409 gives clients far more actionable errors.
#3Is it safe to automatically retry on a 500 error?
Only for idempotent methods. GET, PUT, DELETE, and HEAD can be safely retried after a 5xx because repeating them produces the same effect as a single call. Retrying a POST after a 500 is risky: the server may have processed the request before failing to respond, so a retry can create a duplicate. To make POST safely retryable, use an idempotency key that the server records and de-duplicates against. For 4xx errors, do not retry unchanged, the request itself is wrong, except 401 (re-authenticate first) and 429 (honor Retry-After first).
#3What headers should accompany a 429 Too Many Requests?
Always include Retry-After, expressed either as a number of seconds (Retry-After: 30) or an HTTP date, so the client knows exactly when to try again instead of hammering the server in a tight loop. Ideally also send the RateLimit family of headers (RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset) so well-behaved clients can throttle themselves before they ever hit the limit. Rate limiting without Retry-After is a common cause of retry storms that amplify the very overload the limit was meant to prevent. Build and inspect these headers with the headers builder.
You do not need to memorize all sixty-odd HTTP status codes, you need the fifteen that appear in real traffic and a clear rule for the five pairs that cause bugs. Get the class right first (whose fault, is a retry worth it), then pick the specific code, then attach the header the code requires.
Send real requests and read the exact status line, headers, and timing back with the REST API tester. Look up any code in the HTTP status reference, check method semantics in the HTTP methods reference, and assemble correct response headers with the headers builder.
Written by Rahul Jalavadiya, founder of AllDevToolsHub. All tools run locally in your browser.
#2Sources / Further reading
- IETF - RFC 9110: HTTP Semantics
- IETF - RFC 9111: HTTP Caching
- IETF - RFC 7538: Status Code 308
- MDN Web Docs - HTTP response status codes
Quick Summary
>- Every HTTP status code you actually need, grouped by class, with the real-world rules that trip developers up: 401 vs 403, 301 vs 308, 302 vs 307, 409 vs 422, when to use 429 and Retry-After, and the idempotency and caching semantics behind each code. Includes a fast-lookup table and copy-ready guidance for API design.
Key Takeaways
- HTTP status codes are grouped by class: 1xx (info), 2xx (success), 3xx (redirect), 4xx (client error), 5xx (server error).
- The most common production issues come from misconfigured 3xx redirects, improper 401 vs 403 usage, and unhandled 502/503 cascading failures.
- RFC 9110 (2022) consolidated and updated the HTTP semantics, deprecating some older status codes.
When to use it
- Debugging a 502 Bad Gateway error from a reverse proxy — typically indicates the upstream server crashed or timed out.
- Choosing between 401 Unauthorized and 403 Forbidden — 401 means 'authenticate first,' 403 means 'authenticated but not allowed.'
- Implementing proper redirect chains — 301 for permanent moves (SEO), 302 for temporary, 308 for preserving request method.
Common Mistakes
- Returning 200 OK with an error message in the body — clients check status codes, not response bodies, for success/failure.
- Using 301 redirects for temporary maintenance pages — search engines cache 301 permanently, hurting SEO when you revert.
- Returning 404 for authentication failures instead of 401 — this prevents clients from knowing they need to re-authenticate.
The Complete HTTP Status Code Cheatsheet (2026), Frequently Asked
What is the difference between 401 and 403?
401 Unauthorized means 'you need to authenticate.' 403 Forbidden means 'you are authenticated but not authorized.' If a user is not logged in, return 401. If they are logged in but lack permission, return 403.
When should I use 308 vs 301 redirects?
Use 301 for permanent redirects where the method can change (GET after POST). Use 308 when you need to preserve the original HTTP method — essential for API redirects where POST must stay POST.
Tools Mentioned in This Article
HTTP Methods Reference
Interactive reference for all HTTP methods with safe, idempotent, and cacheable properties.
HTTP Request Builder
Build and send HTTP requests to test APIs right from your browser.
REST API Tester
Debug and test HTTP endpoints with a clean, browser-based interface.
cURL Command Generator
Build a cURL command from method, URL, headers and body.
Tools, tactics, and toughened-up tips, once a week
New tools, deep-dives on developer workflows, and the occasional gem we found this week. No spam, no tracking. Unsubscribe anytime.
Found an error or have feedback?
We correct errors quickly and document changes in our changelog. Report issues at support@alldevtoolshub.com.