HTTP Cheatsheet

Status Codes

Use this HTTP reference while you build software engineering projects, review code, or refresh the syntax you reach for most.

The five classes

ClassRangeMeaningClient should
1xx100-103informational, interimkeep waiting
2xx200-226successproceed
3xx300-308redirectionfollow, or use the cache
4xx400-451client errorfix the request, do not blindly retry
5xx500-511server errorretry with backoff

The rule that matters in production: 4xx is your fault, 5xx is theirs. Returning 500 for bad input hides real bugs behind noise, and returning 200 with {"error": ...} inside defeats every retry, cache, and monitoring layer above you.

1xx informational

CodeNameWhen it is correct
100Continueserver accepts headers, client may send the body after Expect: 100-continue
101Switching ProtocolsWebSocket upgrade, Upgrade: websocket
103Early Hintspreload hints sent before the real response

2xx success

CodeNameWhen it is correct
200OKthe generic success, body present
201Createda new resource exists, include Location
202Acceptedqueued for async processing, not done yet
203Non-Authoritative Informationa proxy modified the payload
204No Contentsuccess with no body, common for DELETE and PUT
205Reset Contentclear the form, rare
206Partial Contentanswering a Range request, needs Content-Range
207Multi-StatusWebDAV, per-item results
208Already ReportedWebDAV
226IM Useddelta encoding

204 must send no body at all. Sending one is a protocol violation and some clients will hang waiting to frame it.

3xx redirection

CodeNameMethod preservedCacheableUse for
300Multiple Choices—yesrare, agent-driven negotiation
301Moved Permanentlyno, POST → GETyes, aggressivelypermanent URL change, SEO
302Foundno, POST → GETonly with explicit headerstemporary, ambiguous, avoid
303See Otherno, always GETnopost-then-redirect-to-result
304Not Modifiedn/an/aconditional GET, no body
307Temporary Redirectyesnotemporary, method safe
308Permanent Redirectyesyespermanent, method safe

Choosing between them:

- Renaming a URL forever: 301 (or 308 if a POST must stay a POST). - Sending a browser somewhere after a form POST: 303, which converts to GET and stops the refresh-resubmits-the-form problem. - Temporary maintenance page or A/B route: 307. - Never use 302 in new work. Its historical method rewriting is exactly the ambiguity 303 and 307 were added to remove.

301 and 308 are cached hard, sometimes permanently by browsers. A wrong permanent redirect is very hard to take back, so test with 307 first.

4xx client errors

CodeNameWhen it is correct
400Bad Requestmalformed syntax, unparseable JSON, bad framing
401Unauthorizedno or invalid credentials, must send WWW-Authenticate
402Payment Requiredreserved, rarely used
403Forbiddenauthenticated but not permitted, or refused outright
404Not Foundno such resource, also used to hide existence from 403
405Method Not Allowedwrong method, must send Allow
406Not Acceptablecannot satisfy Accept
407Proxy Authentication Requiredproxy credentials needed
408Request Timeoutclient was too slow sending
409Conflictstate conflict, duplicate, edit collision
410Gonedeleted on purpose and it will not come back
411Length RequiredContent-Length missing where required
412Precondition FailedIf-Match or If-Unmodified-Since did not hold
413Content Too Largebody over the limit
414URI Too Longusually a GET that should have been a POST
415Unsupported Media Typewrong or missing Content-Type
416Range Not Satisfiablethe requested range is outside the resource
417Expectation Failedcannot meet the Expect header
418I'm a teapota joke code from RFC 2324, reserved forever
421Misdirected Requestwrong connection for this authority
422Unprocessable Contentsyntax valid, semantics invalid, validation errors
425Too Earlyreplay risk on TLS 1.3 early data
426Upgrade Requiredmust switch protocol, for example to TLS
428Precondition Requiredserver demands a conditional request
429Too Many Requestsrate limited, send Retry-After
431Request Header Fields Too Largeoversized headers or cookies
451Unavailable For Legal Reasonscensorship, takedown

401 vs 403 is the pair everyone gets wrong. 401 means "I do not know who you are, authenticate", so it always carries WWW-Authenticate. 403 means "I know who you are and the answer is no", and re-authenticating will not help.

400 vs 422 is the second. 400 for a body the parser cannot read, 422 for a body that parses fine but fails your rules.

5xx server errors

CodeNameWhen it is correct
500Internal Server Erroran unhandled exception, the catch-all
501Not Implementedthe server does not support this method at all
502Bad Gatewayupstream returned garbage or refused the connection
503Service Unavailabledown or overloaded, send Retry-After
504Gateway Timeoutupstream did not answer in time
505HTTP Version Not Supportedversion refused
507Insufficient StorageWebDAV, out of space
508Loop Detectedinfinite loop in processing
511Network Authentication Requiredcaptive portal

The proxy trio, read literally, points straight at the layer to check:

CodeMeaning behind a reverse proxyWhere to look
502the app crashed, refused the socket, or spoke nonsenseapp process, port, protocol
503nothing healthy to route to, or shed loadhealth checks, replica count, upstream pool
504the app is alive but too slowslow queries, deadlocks, upstream timeouts

Retrying and error bodies

CodeRetry?With what
408, 425yesimmediately, once
429yeshonor Retry-After, then exponential backoff plus jitter
500cautiouslyonly if the request is idempotent
502, 503, 504yesexponential backoff plus jitter, respect Retry-After
4xx (others)nofix the request first

Report errors with RFC 9457 problem details rather than an ad hoc shape, so clients can parse failures generically.

{
  "type": "https://example.com/probs/insufficient-stock",
  "title": "Not enough stock",
  "status": 409,
  "detail": "SKU HU-100 has 1 unit left, 2 requested",
  "instance": "/orders/8814"
}

Serve it as Content-Type: application/problem+json, and keep the status field identical to the real HTTP status.