HTTP Status Code Reference

Searchable HTTP status code reference (1xx → 5xx) with short descriptions and typical use cases. Filter by class, copy a code, link to the IETF spec.

Loading…

All processing runs in your browser — no files or inputs are uploaded to a server.

The five status classes (1xx → 5xx)

HTTP groups status codes into five classes by the first digit. The classes are coarse — a single category covers everything from "keep going" to "all your fonts are missing" — but the digit alone tells a client whether the request worked, what went wrong, and whose fault it is.

ClassRangeNameWhat it actually means
1xx100–199InformationalInterim response. The request was received and processing continues — the final response is still on its way.
2xx200–299SuccessThe request succeeded. The exact semantics depend on the method — 200 for GET, 201 for created resources, 204 for "done, nothing to return".
3xx300–399RedirectionFurther action is needed by the client — usually a different URL to follow, sometimes a cached copy is still valid.
4xx400–499Client errorThe client did something wrong — bad syntax, missing auth, asking for something that does not exist, or sending data the server cannot accept.
5xx500–599Server errorThe server failed to fulfill an apparently valid request. The fault is server-side; the client did nothing wrong.

Pairs that get mixed up most often

A handful of code pairs cause the majority of real-world API bugs because the names sound interchangeable. The split is intentional — picking the right one tells the client what to do next.

401 vs 403

  • 401Unauthorizedthe client is not authenticated. The server needs credentials and got none, or got bad ones. The "Unauthorized" wording is misleading — it really means "unauthenticated".
  • 403Forbiddenthe client is authenticated but does not have permission. Re-authenticating will not help.

301 vs 302 vs 307 vs 308

  • 301Moved Permanentlythe resource has a new permanent URL. Browsers may rewrite the method to GET on redirect (legacy behavior).
  • 302Foundtemporary redirect, same legacy method-rewriting behavior. Often what people accidentally use when they meant 303 or 307.
  • 307Temporary Redirectlike 302 but the method must be preserved. A POST stays a POST after redirect.
  • 308Permanent Redirectlike 301 but the method must be preserved. Modern equivalent of 301.

200 vs 201 vs 202 vs 204

  • 200OKa generic success with a body. Default for GET.
  • 201Createda new resource was created. Include a Location header pointing at it.
  • 202Acceptedthe request was queued — work has not started, will finish asynchronously.
  • 204No Contentsuccess, but the response body is intentionally empty. Default for successful DELETE.

400 vs 422

  • 400Bad Requestthe request itself was malformed — invalid JSON, missing required header, etc. The server could not parse it.
  • 422Unprocessable Contentthe request was understood but the data is semantically wrong — e.g. an email field had no @, or a quantity was negative.

502 vs 503 vs 504

  • 502Bad Gatewaya proxy got an invalid response from an upstream server. The upstream replied with something the proxy could not use.
  • 503Service Unavailablethe server itself is temporarily down — overload, maintenance window, etc. Often paired with a Retry-After header.
  • 504Gateway Timeouta proxy waited too long for an upstream and gave up. Different from 502: 504 is "no answer", 502 is "bad answer".

Which code should an API return?

For a REST API, the conventional mapping is short. Successful GET: 200 (with body) or 304 (cached, unchanged). Successful POST that creates a resource: 201 with a Location header. Successful PUT or PATCH: 200 (with the updated body) or 204 (no body). Successful DELETE: 204. Validation failure: 422. Missing auth: 401. Authorized but no permission: 403. Resource not found: 404. Server bug: 500.

Two anti-patterns are common enough to call out. First, returning 200 with an error message in the body ("status: 200, error: 'not found'") breaks every monitoring tool — they all key off the status code. Second, returning 500 for every kind of failure leaves the client with no way to distinguish "retry this" (503) from "your input is wrong" (400) from "contact support" (500).

Which RFC defines what — a brief map

The current authoritative reference is RFC 9110 (HTTP Semantics, June 2022), which consolidates twelve earlier RFCs into one document and explicitly obsoletes RFC 7231 and RFC 7232. Most of the codes you use day-to-day were already in RFC 1945 (HTTP/1.0, 1996); 308 Permanent Redirect was added by RFC 7538, 421 Misdirected Request by RFC 7540, and 451 Unavailable For Legal Reasons by RFC 7725.

For practical lookup, the IANA HTTP Status Code Registry is the live source — it lists every assigned code with its defining RFC. If you need the formal wording for an audit or compliance report, cite RFC 9110 plus the registry; if you just need to remember what 422 means, the search box above is faster.

How to use

Type a code, a name, or a use-case keyword into the search box (`404`, `not found`, `redirect`, `unauthorized`, `idempotent`) and the table filters live. Click a class chip (1xx / 2xx / 3xx / 4xx / 5xx) to narrow further. Each row carries the canonical name, a one-line description, a "when to use" hint, and a link to the IETF section that defines it — `RFC 9110` for the core 2022 revision that replaced the long-lived RFC 7231 / 7232 / 7233 / 7234 / 7235 series.

Reach for this when designing an API, reading server logs, or debugging a request that surfaces an unfamiliar code. The 4xx / 5xx classes get most of the attention, but the 3xx redirect codes and the 2xx success codes have real semantic weight — `301` vs `308`, `200` vs `204` vs `201`, `409` vs `422` all communicate different things to caches and clients. Picking the right code makes integration with libraries (axios, RestSharp, Spring) and infrastructure (CloudFront, nginx, AWS API Gateway) behave predictably without custom hooks.

Examples

Looking up `422`

Input
search: 422
Output
422 Unprocessable Content (RFC 9110 §15.5.21)
Use: request is syntactically valid but the server cannot process it for semantic reasons — failed validation, business rule violation. Often confused with 400.

`400 Bad Request` means the request itself is malformed (broken JSON, missing required header). `422` means the request was understood but its meaning is wrong (email already in use, age must be ≥ 18). Most modern APIs (Stripe, GitHub, Twilio) prefer `422` for validation errors so backend logs separate "client sent garbage" from "client tried something we cannot do".

`301` vs `308` redirect

Input
search: redirect permanent
Output
301 Moved Permanently — historic permanent redirect; browsers may rewrite the method to GET on POST / PUT.
308 Permanent Redirect (RFC 7538) — same semantics but preserves the original method and body.

Use `308` for new API endpoints when you want clients to keep using POST / PUT after the redirect. Use `301` for SEO and old-URL → new-URL moves where rewriting to GET is fine (and historically expected). The same split applies to temporary: `302` (legacy, may rewrite to GET) vs `307` (preserves method).

`401` vs `403`

Input
search: unauthorized forbidden
Output
401 Unauthorized — request lacks valid authentication. Server must return a WWW-Authenticate header. Despite the name, this is really "Unauthenticated".
403 Forbidden — request is authenticated but the principal is not allowed to perform this action. No WWW-Authenticate; retrying with different credentials won't help unless permissions change.

The naming is unfortunate — `401` is about authentication (who are you?) and `403` is about authorization (what can you do?). A common pattern: return `401` when the auth token is missing or expired (client should re-login), `403` when the token is valid but lacks scope (client should request elevated permissions). Some APIs use `404` instead of `403` to avoid leaking the existence of resources to unauthorized callers.

FAQ

Is the list authoritative?

Codes are sourced from the IANA HTTP Status Code Registry, which is the official authority. The current core definitions live in RFC 9110 (HTTP Semantics, June 2022), with extensions in RFC 9111 (Caching) and topic-specific RFCs like 7538 (308 redirect), 6585 (precondition required, too many requests), and 8297 (early hints). Each row links to the section that defines it so you can verify against the spec.

Why are some codes here that I have never seen in the wild?

The registry is permissive — anyone can request a code allocation through the IETF process. Some codes are common (`200`, `404`, `500`); others are niche (`418 I'm a teapot` from an April Fools RFC, `451 Unavailable For Legal Reasons` named after Fahrenheit 451). Some address narrow protocols (WebDAV adds 207 / 422 / 423 / 424 / 507 in RFC 4918). The reference shows all of them so you can recognize them when they appear in a CDN log or a third-party API.

My API returns `200` with an `errors: [...]` body. Is that legal?

Legal but misleading. HTTP status codes communicate to *infrastructure* — load balancers, retry libraries, cache layers, monitoring dashboards. Sending `200` for what is logically a failure tells the CDN to cache the error response, the retry library to consider the call successful, and the on-call dashboard to plot it as a green dot. Reserve `2xx` for actual success; use `4xx` for client errors and `5xx` for server errors so the surrounding ecosystem treats them correctly. GraphQL is the main exception — its spec returns `200` with errors in the body because the protocol layer is HTTP-agnostic.

Are 1xx codes ever useful in practice?

Two of them are. `100 Continue` is used by HTTP/1.1 clients with `Expect: 100-continue` to ask the server if a large request body is welcome before sending it; most servers handle this transparently. `103 Early Hints` (RFC 8297, 2017) lets the server send preload hints for CSS / JS before the actual `200` response is ready — Cloudflare and Fastly support it. The rest (`101 Switching Protocols` for WebSocket upgrade, `102 Processing` for WebDAV) are protocol-specific. Day-to-day API development rarely sees 1xx.

What is the difference between `502`, `503`, and `504`?

All three are upstream / gateway failures, but from different angles. **`502 Bad Gateway`** — the proxy got a *broken* response from the upstream (connection reset, malformed HTTP). **`503 Service Unavailable`** — the server itself is unable to handle the request (overload, maintenance, graceful shutdown); should include `Retry-After` header. **`504 Gateway Timeout`** — the proxy waited for the upstream and timed out. In an nginx → app stack: `502` is "app crashed", `503` is "app said `I am full`", `504` is "app took too long to answer". The right code helps on-call know whether to restart, scale, or investigate latency.

Can I make up my own status codes?

Technically no — the IANA registry is the source of truth and proxies, browsers, and middleware may treat unregistered codes as their class default (any 4xx behaves like 400, any 5xx like 500). In practice frameworks tolerate it as long as the first digit is meaningful, and some private APIs use unregistered codes like `419 Authentication Timeout` (Laravel) or `420 Method Failure` (deprecated Twitter API). For new public APIs stick to registered codes and put detail in the response body — clients ignore unknown codes uniformly enough that the extra information value is small.

Related concepts

HTTP status codes are 3-digit integers that the server returns alongside the response. The first digit identifies the **class**: `1xx` informational (rare, protocol-specific), `2xx` success, `3xx` redirection, `4xx` client error, `5xx` server error. RFC 9110 (June 2022) consolidated the previous status-code definitions from RFC 7231 / 7232 / 7233 / 7234 / 7235 into a single document and is the current normative reference. The IANA HTTP Status Code Registry holds the authoritative list of allocated values.

The semantic difference between adjacent codes matters more than people expect. `200` and `204` both say "success" but `204` carries no body — clients should not parse one. `201` confirms creation and the response carries the new resource's representation or a `Location` header. `301` and `308` are both "permanent redirect" but `308` preserves the HTTP method; `301` historically rewrites POST to GET. `409 Conflict` and `422 Unprocessable Content` both mean "I refused your write" but `409` is for state conflicts (concurrent edits, duplicate key) and `422` is for validation failures (bad email format). Picking the right code is signaling, not pedantry — caches, retry libraries, and observability tools all react to the code without reading the body.

Three adjacent concepts shape day-to-day API design. **Idempotency** classifies methods (`GET`, `PUT`, `DELETE` are idempotent; `POST` is not) and decides safe retry behavior; status code design works alongside this so a client knows whether to retry on `503`. **Caching** (RFC 9111) determines which responses get stored — `200`, `203`, `204`, `300`, `301`, `404`, `405`, `410`, `414`, `501` are cacheable by default; others need explicit headers. **Content negotiation** uses headers like `Accept`, `Accept-Language`, and returns `406 Not Acceptable` when none of the offered representations match. Status codes sit in the middle of all three, which is why getting them right pays off across the stack.

Related articles

Related tools