HTTP status codes

Every HTTP status code worth knowing, from 200 and 301 to 429 and 503, with a line on when to reach for it rather than a paraphrase of the RFC.

Class
100 ContinueInformational

The client may send the body it asked about.

101 Switching ProtocolsInformational

The upgrade to WebSocket was accepted.

200 OKSuccess

It worked, and the body is the result.

201 CreatedSuccess

A resource now exists; put its URL in Location.

202 AcceptedSuccess

Queued. The work has not happened yet.

204 No ContentSuccess

It worked and there is nothing to send back. A DELETE, usually.

206 Partial ContentSuccess

The range the client asked for, for resumable downloads.

207 Multi-StatusSuccess

A per-item result for a batch. Almost nothing understands it; a 200 with a result list is what people ship.

301 Moved PermanentlyRedirect

The URL changed for good. Search engines move their index.

302 FoundRedirect

A temporary redirect that may switch the method to GET. Prefer 307.

303 See OtherRedirect

After a POST, send the client to a page it should GET.

304 Not ModifiedRedirect

Their cached copy is still good. No body.

307 Temporary RedirectRedirect

Temporary, and the method and body are kept.

308 Permanent RedirectRedirect

Permanent, and the method and body are kept.

400 Bad RequestClient error

The request itself is malformed. Not for a failed validation rule.

401 UnauthorizedClient error

No credentials, or bad ones. It means unauthenticated.

402 Payment RequiredClient error

Reserved for years, now used by APIs for a plan that has run out.

403 ForbiddenClient error

Authenticated, and still not allowed.

404 Not FoundClient error

No such resource, or you are hiding its existence on purpose.

405 Method Not AllowedClient error

The URL exists; that verb does not. List the ones that do in Allow.

408 Request TimeoutClient error

The client took too long to send it. Often a proxy talking, not your app.

409 ConflictClient error

The state moved under them: a duplicate, or a stale version.

410 GoneClient error

It existed and will not come back. Kinder to crawlers than a 404.

413 Content Too LargeClient error

The body is over your limit. Say what the limit is in the response.

414 URI Too LongClient error

The URL is over the server's limit, which usually means a query that wanted to be a POST.

415 Unsupported Media TypeClient error

The Content-Type is not one you take.

418 I'm a TeapotClient error

A joke from 1998 that refuses to die. Never ship it.

422 Unprocessable ContentClient error

Well-formed, but the rules say no. The one to use for validation.

423 LockedClient error

Someone else is holding it. WebDAV by origin, borrowed by editors and CMSs.

425 Too EarlyClient error

A replayed early-data request you would rather not process.

426 Upgrade RequiredClient error

The protocol or version you are on is no longer accepted.

428 Precondition RequiredClient error

You want the client to send If-Match so two writers cannot overwrite each other.

429 Too Many RequestsClient error

Rate limited. Send Retry-After, always.

431 Request Header Fields Too LargeClient error

Usually one enormous cookie.

451 Unavailable for Legal ReasonsClient error

Removed by law rather than by choice. The number is a Bradbury reference.

500 Internal Server ErrorServer error

You broke. Log it, and never leak the reason.

501 Not ImplementedServer error

The server does not know this method at all.

502 Bad GatewayServer error

Something upstream answered with nonsense.

503 Service UnavailableServer error

Down or overloaded, and expected back. Send Retry-After.

504 Gateway TimeoutServer error

Something upstream never answered.

511 Network Authentication RequiredServer error

A captive portal, not your API. Airport wifi speaking.

Questions

401 or 403?+

401 means unauthenticated: no credentials, or bad ones, and the client should try again with some. 403 means authenticated and still not allowed, so trying again with the same identity changes nothing. If you send 401, send a WWW-Authenticate header with it; that is what the status is defined to mean.

400 or 422?+

400 for a request that is malformed: broken JSON, a missing required field, the wrong shape entirely. 422 for a request that parsed fine and failed your rules, which is most validation. If your framework only offers 400, that is fine too; what matters is that the body says which field failed and why.

Which redirect should I use?+

308 for permanent and 307 for temporary: both keep the method and the body. 301 and 302 are older and may turn a POST into a GET, which is rarely what anyone wants. For a browser navigation the difference rarely shows; for an API it changes what arrives.

200, 201 or 204?+

200 when there is a body worth reading. 201 when something now exists, with its address in a Location header. 204 when it worked and there is nothing to say, which is the usual answer to a DELETE. A 204 with a body is a contradiction, and some clients will drop it.

404 or 410?+

404 says not found, which leaves open that it might turn up later. 410 says it existed and will not come back. Crawlers treat 410 as final and drop the URL faster, so it is the kinder answer for a page you deliberately retired.

When is 409 the right answer?+

When the request is valid but the current state refuses it: a duplicate email on signup, an edit against a version that has since moved, a resource someone else already claimed. 409 tells the client to re-read and try again rather than to fix its request.

What should I send when a client is rate limited?+

429, always with a Retry-After header, in seconds or as a date. Without it every client invents its own backoff, and the polite ones end up punished. 503 also takes Retry-After and is for the whole service being unavailable rather than one client asking too often.

500, 502, 503 or 504?+

500 is your own code failing. 502 is something upstream answering with nonsense. 503 is you being down or overloaded on purpose, and it should carry Retry-After. 504 is something upstream never answering at all. The last three usually come from a proxy rather than from your application.

The URL exists but the method is wrong. 404 or 405?+

405, with an Allow header listing the methods that do work. Answering 404 hides a routing mistake and sends the client looking for a typo in the path that is not there.

Is it acceptable to return 200 with an error in the body?+

For a plain REST endpoint, no: monitoring, caches, retries and every client library read the status first, and a 200 tells all of them nothing went wrong. The genuine exceptions are protocols that carry their own error channel, such as GraphQL, where a 200 with an errors array is the specified behaviour.

What does 304 mean and why is my request not reaching the server?+

304 means the copy the client already has is still good, so the server sends no body. It happens when the request carried If-None-Match or If-Modified-Since and matched. If you are changing a file and seeing stale content, that exchange is usually why, and a changed ETag or a new URL is the fix.

403 or 404 for something the user may not see?+

404 when the existence of the resource is itself private, which is the usual choice for another tenant's data: 403 would confirm it exists. 403 when the resource is plainly public knowledge and the user simply lacks the right, such as an admin page. Whichever you pick, be consistent, or the difference becomes an oracle.

What should a bulk endpoint return when only some items fail?+

207 exists for exactly this and almost nothing understands it. In practice return 200 with a per-item result list, and document that the caller must read it. Returning 400 for a batch where nine of ten items succeeded throws away the nine.

Why do I sometimes see status 0 in the browser?+

Because there was no response to read: a CORS preflight that failed, a request the network dropped, or one the page aborted. The server may well have answered fine; the browser refused to hand it over. Look at the console and the preflight rather than at your status codes.

Which codes are worth learning first?+

200, 201, 204, 301, 400, 401, 403, 404, 409, 422, 429 and 500 cover almost every response a normal API sends. The rest of this list is for the day something odd turns up in a log.

Related tools

The tools are free. So is most of the library.

1935 blocks and 989 pieces for shadcn/ui and Tailwind, built on the same tokens these tools write. Install one with a command and the code is yours.

No signup for the tools. MIT for free blocks, commercial licence for Pro.

Markdown version