Free Handy Tools

HTTP Status Codes

The pairs that get picked wrongly

  • 401 Unauthorized403 Forbidden

    Would different credentials change the answer?

    Yes means 401: the caller has not proved who they are, and the WWW-Authenticate header tells them how. No means 403: identity is established and the answer is still no. The names are backwards — 401 is the unauthenticated one — which is why this pair is the most misused in HTTP.

  • 302 Found307 Temporary Redirect

    May the client turn your POST into a GET?

    302 lets it. RFC 9110 records that browsers have always rewritten the method for 302, so a redirected POST arrives as a bodyless GET. 307 forbids the rewrite: method and body survive. Redirect a form submission with 302 and the data silently disappears; use 303 if you want the GET, 307 if you want the POST.

  • 301 Moved Permanently308 Permanent Redirect

    The same question, permanently.

    301 tolerates the method changing to GET; 308 does not. For a marketing URL that only ever serves GET, 301 is fine and is what caches and search engines are most used to. For an API path, 308 is the honest one — and it is also the one that will not turn a permanent PUT redirect into a lost request body.

  • 409 Conflict422 Unprocessable Content

    Is the request wrong, or is the world wrong?

    422 says the body is well-formed but invalid on its own terms: a negative quantity, a malformed email. Resending it unchanged will always fail. 409 says the body is fine but clashes with current state: the username is taken, the version is stale. Resending it later, or after a refetch, may well work.

  • 418 I'm a Teapot

    Why does a teapot have a status code?

    RFC 2324 defined the Hyper Text Coffee Pot Control Protocol as an April Fools joke in 1998, and 418 is its refusal to brew coffee in a teapot. RFC 7168 extended the joke to teapots asked for coffee. It has never been in the HTTP specification, an attempt to reclaim the number in 2017 was withdrawn after protest, and frameworks still ship it.

A number matches by prefix, so 41 lists the whole 41x row. Text matches the name, the meaning and the guidance.

Every registered code, in numeric order.

63 of 63 codes
  • 100

    Continue

    RFC 9110 §15.2.1

    The request headers are acceptable and the client should send the body.

    Send it when Only in reply to a request carrying Expect: 100-continue, so a large upload is not sent to a server that would reject it.

  • 101

    Switching Protocols

    RFC 9110 §15.2.2

    The server is changing to the protocol named in the Upgrade header.

    Send it when The WebSocket handshake, and effectively nothing else in practice.

  • 102

    Processing

    RFC 2518 §10.1

    A WebDAV interim response saying the request was accepted but is not finished.

    Send it when Never in new work: RFC 4918 removed it because it was unused and unhelpful.

  • 103

    Early Hints

    RFC 8297

    Carries Link headers so the client can start preloading before the real response.

    Send it when When the final response is slow to compute and the assets it will reference are known now.

  • 200

    OK

    RFC 9110 §15.3.1

    The request succeeded and the body is the result.

    Send it when The default success for GET, and for POST or PUT where the response carries the resulting state.

  • 201

    Created

    RFC 9110 §15.3.2

    One or more resources were created.

    Send it when A POST or PUT that made something new. Send a Location header pointing at it.

  • 202

    Accepted

    RFC 9110 §15.3.3

    The request was accepted but has not been acted on yet, and may still fail.

    Send it when Work handed to a queue. Give the client somewhere to poll for the outcome.

  • 203

    Non-Authoritative Information

    RFC 9110 §15.3.4

    The payload was modified in transit by a proxy or transforming intermediary.

    Send it when Sent by that intermediary, not by the origin server.

  • 204

    No Content

    RFC 9110 §15.3.5

    Success, and deliberately no body. Headers may still carry metadata.

    Send it when A DELETE that succeeded, or a PUT whose result the client already has.

  • 205

    Reset Content

    RFC 9110 §15.3.6

    Success, and the client should clear the form that produced the request.

    Send it when Data-entry screens that submit repeatedly. Rare on the web.

  • 206

    Partial Content

    RFC 9110 §15.3.7

    The body is the byte range the Range header asked for.

    Send it when Resumed downloads and media seeking. Requires a Content-Range header.

  • 207

    Multi-Status

    RFC 4918 §11.1

    The body is XML holding a separate status for each resource touched.

    Send it when WebDAV operations over a collection, where one code cannot describe the outcome.

  • 208

    Already Reported

    RFC 5842 §7.1

    A binding already listed earlier in this Multi-Status response is not repeated.

    Send it when Inside a 207 body, to keep a recursive WebDAV report finite.

  • 226

    IM Used

    RFC 3229 §10.4.1

    The response is the result of applying instance manipulations to the current instance.

    Send it when Delta encoding, which almost nothing implements.

  • 300

    Multiple Choices

    RFC 9110 §15.4.1

    Several representations exist and the client or user must pick.

    Send it when Agent-driven negotiation. There is no standard format for the list, which is why it is rare.

  • 301

    Moved Permanently

    RFC 9110 §15.4.2

    The resource has a new permanent URL, and clients may rewrite the method to GET.

    Send it when A URL that has genuinely moved for good, on a GET-shaped resource.

  • 302

    Found

    RFC 9110 §15.4.3

    A temporary redirect that clients also rewrite to GET in practice.

    Send it when Legacy code paths. New work wants 303 or 307, which say what they mean.

  • 303

    See Other

    RFC 9110 §15.4.4

    The result of the request is at another URL, retrieved with GET.

    Send it when After a successful POST, so a refresh does not resubmit the form.

  • 304

    Not Modified

    RFC 9110 §15.4.5

    The cached copy is still current; no body is sent.

    Send it when A conditional GET whose If-None-Match or If-Modified-Since still holds.

  • 305

    Use Proxy

    RFC 9110 §15.4.6

    Deprecated. It once named a proxy the client had to use.

    Send it when Never. It was a security problem and clients ignore it.

  • 306

    (Unused)

    RFC 9110 §15.4.7

    Reserved. Defined in an early draft, never standardised.

    Send it when Never. The number is kept reserved so nothing reuses it.

  • 307

    Temporary Redirect

    RFC 9110 §15.4.8

    A temporary redirect that forbids changing the method or dropping the body.

    Send it when Any temporary redirect of a POST, PUT, PATCH or DELETE.

  • 308

    Permanent Redirect

    RFC 9110 §15.4.9

    A permanent redirect that forbids changing the method.

    Send it when A permanent move of anything that is not purely a GET target.

  • 400

    Bad Request

    RFC 9110 §15.5.1

    The server will not process the request because it is malformed.

    Send it when Broken syntax: unparseable JSON, a missing required parameter, a header that makes no sense.

  • 401

    Unauthorized

    RFC 9110 §15.5.2

    No valid credentials were supplied. The name is a misnomer for unauthenticated.

    Send it when A missing, expired or invalid token. A WWW-Authenticate header is mandatory.

  • 402

    Payment Required

    RFC 9110 §15.5.3

    Reserved for future use, with no defined payment mechanism.

    Send it when Some APIs use it for an unpaid account. Nothing interoperable depends on it.

  • 403

    Forbidden

    RFC 9110 §15.5.4

    The server understood who you are and is refusing anyway.

    Send it when An authenticated caller without the right permission, or a rule that no credentials would satisfy.

  • 404

    Not Found

    RFC 9110 §15.5.5

    No representation exists for this target, and the server will not say whether it ever did.

    Send it when An unknown path, and deliberately in place of 403 when even the existence of the resource is private.

  • 405

    Method Not Allowed

    RFC 9110 §15.5.6

    The target exists but does not support this method.

    Send it when A POST to a read-only endpoint. An Allow header listing the supported methods is mandatory.

  • 406

    Not Acceptable

    RFC 9110 §15.5.7

    No representation matches the Accept headers sent.

    Send it when Rarely worth sending; serving your default type is usually kinder than refusing.

  • 407

    Proxy Authentication Required

    RFC 9110 §15.5.8

    Like 401, but the proxy is the one demanding credentials.

    Send it when Sent by a proxy, with a Proxy-Authenticate header.

  • 408

    Request Timeout

    RFC 9110 §15.5.9

    The server gave up waiting for the request to arrive.

    Send it when An idle connection the server is closing. Not for a slow handler — that is 504.

  • 409

    Conflict

    RFC 9110 §15.5.10

    The request conflicts with the current state of the resource.

    Send it when A duplicate that must be unique, a lost update, or an edit against a stale version.

  • 410

    Gone

    RFC 9110 §15.5.11

    The resource existed and has been removed for good.

    Send it when A deleted account or retired endpoint, when telling crawlers to stop asking is worth the bookkeeping.

  • 411

    Length Required

    RFC 9110 §15.5.12

    The request needs a Content-Length header and did not have one.

    Send it when A server that cannot accept a chunked body.

  • 412

    Precondition Failed

    RFC 9110 §15.5.13

    A condition in If-Match or If-Unmodified-Since did not hold.

    Send it when Optimistic concurrency: the ETag the client sent no longer matches.

  • 413

    Content Too Large

    RFC 9110 §15.5.14

    The body is larger than the server is willing to process.

    Send it when An upload over your limit. Renamed from Payload Too Large in RFC 9110.

  • 414

    URI Too Long

    RFC 9110 §15.5.15

    The request target is longer than the server will accept.

    Send it when A GET whose query string should have been a POST body.

  • 415

    Unsupported Media Type

    RFC 9110 §15.5.16

    The body is in a format this endpoint does not accept.

    Send it when XML sent to a JSON-only API, or a missing Content-Type on a request that needs one.

  • 416

    Range Not Satisfiable

    RFC 9110 §15.5.17

    The requested byte range lies outside the resource.

    Send it when A resumed download against a file that has since shrunk.

  • 417

    Expectation Failed

    RFC 9110 §15.5.18

    The Expect header cannot be met.

    Send it when In practice, only in reply to an Expect the server does not support.

  • 418

    I'm a Teapot

    RFC 2324 §2.3.2

    The server refuses to brew coffee because it is a teapot.

    Send it when Never seriously. It is a 1998 April Fools joke that survives because implementers kept it.

  • 421

    Misdirected Request

    RFC 9110 §15.5.20

    This connection cannot produce a response for the authority requested.

    Send it when HTTP/2 connection reuse, where one TLS certificate covers hosts served by different backends.

  • 422

    Unprocessable Content

    RFC 9110 §15.5.21

    The syntax is fine but the content is semantically wrong.

    Send it when Validation failures: a well-formed JSON body with an email field that is not an email.

  • 423

    Locked

    RFC 4918 §11.3

    The resource is locked.

    Send it when WebDAV, against a resource someone else holds a lock on.

  • 424

    Failed Dependency

    RFC 4918 §11.4

    The request failed because an earlier request it depended on failed.

    Send it when Inside a WebDAV batch where one member has already failed.

  • 425

    Too Early

    RFC 8470 §5.2

    The server will not risk processing a replayable early-data request.

    Send it when TLS 1.3 0-RTT data on a non-idempotent request.

  • 426

    Upgrade Required

    RFC 9110 §15.5.22

    The client must switch to a different protocol to continue.

    Send it when Forcing TLS or a newer HTTP version. Requires an Upgrade header.

  • 428

    Precondition Required

    RFC 6585 §3

    The request must be conditional.

    Send it when An unconditional PUT to a resource where a lost update would matter.

  • 429

    Too Many Requests

    RFC 6585 §4

    The client has sent too many requests in a given period.

    Send it when Rate limiting. Send Retry-After so the client knows when to come back.

  • 431

    Request Header Fields Too Large

    RFC 6585 §5

    The headers are collectively or individually too large.

    Send it when Usually a cookie that has grown unbounded.

  • 451

    Unavailable For Legal Reasons

    RFC 7725 §3

    Access is denied as a result of a legal demand.

    Send it when A takedown or a geographic block, with a Link header describing the blocking authority.

  • 500

    Internal Server Error

    RFC 9110 §15.6.1

    The server hit an unexpected condition and cannot be more specific.

    Send it when An unhandled exception. Anything you can describe deserves a narrower code.

  • 501

    Not Implemented

    RFC 9110 §15.6.2

    The server does not support the functionality the method requires.

    Send it when A method the server does not recognise at all. Compare 405, which is per-resource.

  • 502

    Bad Gateway

    RFC 9110 §15.6.3

    A proxy got an invalid response from the server behind it.

    Send it when Sent by the proxy: the upstream crashed, closed the connection or spoke nonsense.

  • 503

    Service Unavailable

    RFC 9110 §15.6.4

    The server cannot handle the request right now, but the condition is temporary.

    Send it when Maintenance, an overloaded queue, a dependency that is down. Retry-After belongs here.

  • 504

    Gateway Timeout

    RFC 9110 §15.6.5

    A proxy timed out waiting for the server behind it.

    Send it when A handler slower than the gateway limit. Distinct from 408, which is about the request arriving.

  • 505

    HTTP Version Not Supported

    RFC 9110 §15.6.6

    The major HTTP version in the request is not supported.

    Send it when Almost never, since version negotiation happens earlier.

  • 506

    Variant Also Negotiates

    RFC 2295 §8.1

    Transparent negotiation has produced a circular reference.

    Send it when A misconfigured negotiating server. Effectively a server bug report.

  • 507

    Insufficient Storage

    RFC 4918 §11.5

    The server cannot store the representation needed to finish the request.

    Send it when WebDAV, out of quota or out of disk.

  • 508

    Loop Detected

    RFC 5842 §7.2

    An infinite loop was found while processing the request.

    Send it when A WebDAV bind cycle that a recursive operation would never escape.

  • 510

    Not Extended

    RFC 2774 §7

    The request needs further extensions to be handled.

    Send it when Never in new work: RFC 9110 records the mechanism as obsolete.

  • 511

    Network Authentication Required

    RFC 6585 §6

    The client must authenticate to gain network access.

    Send it when Captive portals, sent by the intercepting network rather than the origin.

Codes and names follow the IANA HTTP Status Code Registry and each entry cites the document that defines it, so the code, the name and the RFC are checkable rather than remembered. The “send it when” line is editorial: it is the reading most APIs settle on, not something any RFC mandates, and a specification your API already follows beats it. Vendor codes are deliberately absent — 420, 450 and 499 are inventions of particular servers and are not registered anywhere.

A reference for choosing a code, not only for decoding one

Looking up what 412 means takes a second; deciding which code your own endpoint should return takes longer, and that is the decision this page is built around. Every registered code carries what it means, when to send it and the document defining it, and the search box matches a number by prefix or any text in the description, so “retry-after” finds 429 and 503 together.

The citations are worth reading. Most everyday codes were re-specified by RFC 9110 in June 2022, which obsoleted RFC 7231 and, before it, the relevant half of RFC 2616 — so an old answer citing 2616 is three revisions behind. The oddities keep their original homes: WebDAV contributed 207, 423 and 507 through RFC 4918, the rate-limiting codes arrived with RFC 6585, and legal blocking got 451 from RFC 7725.

401 and 403: not authenticated against not allowed

This pair goes wrong most often, partly because the names mislead. 401 is called Unauthorized but means unauthenticated: the request arrived without usable credentials, and RFC 9110 §15.5.2 requires a WWW-Authenticate header saying how to supply them. 403 means the server knows exactly who is asking and is still saying no. The test is whether a different token would change the outcome — if it would, the answer is 401.

A third option is sometimes better than either. Where the existence of a resource is itself private, replying 404 to someone not entitled to see it leaks nothing, whereas 403 confirms the record exists — which is why the choice here is a security decision rather than a stylistic one. When a proxy rather than the origin wants credentials, the code is 407.

302, 307, 301 and 308: does the method survive?

All four redirect. What separates them is whether the client may rewrite your POST into a GET: 302 and 301 permit it, 307 and 308 forbid it, and 301 and 308 are the permanent pair.

The permission is not theoretical. Early browsers rewrote the method on a 302 whatever the specification said, and the behaviour survives today — so a form POSTed to a URL answering 302 arrives as a GET with no body, and the submitted data is gone. RFC 9110 §15.4.4 gives 303 for when that conversion is what you want, which is the standard defence against a refresh resubmitting a payment. For an API that must keep the method and body, 307 or 308 is the only safe choice.

409 against 422, and why a teapot has a number

Both reject a request the server understood. 422 Unprocessable Content, now in RFC 9110 §15.5.21 after starting life in WebDAV, means the body parsed but its contents are invalid on their own terms — a quantity of −3, a date in the wrong century — so resending it unchanged can never succeed. 409 Conflict means the body is fine and the world disagrees with it: the email address is taken, the document was edited since you fetched it. Resending after a refetch may well work, which is a different instruction to the client.

418 is the famous one. RFC 2324, an April Fools joke from 1998, defined a protocol for controlling coffee pots and gave teapots a code with which to refuse to brew; RFC 7168 later extended the joke. It has never been part of HTTP, an attempt to free the number in 2017 was abandoned after public objection, and it remains implemented in framework after framework as a piece of shared folklore.

Choosing between 401, 429 and 410

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

It is common and it is a poor idea. Caches, retry logic, monitoring and client libraries all key off the status line, so a failure wearing a 200 is invisible to every one of them. Let the status code say what happened and the body carry the detail.

Which code should a rate limiter return?

429 Too Many Requests, from RFC 6585 §4, together with a Retry-After header giving either a delay in seconds or a date. Without that header the client has no basis for a backoff and will usually guess badly.

What is the difference between 502 and 504?

Both come from something in front of your application. A 502 means the proxy got an invalid or truncated response from upstream; a 504 means it got nothing in time. The first points at a crash, the second at a slow handler or a timeout set too low.

Do I need 410 Gone, or is 404 enough?

404 is enough for most cases. 410 earns its bookkeeping when you want crawlers to stop asking permanently: it asserts the resource existed and will not return, which 404 deliberately declines to say either way.

Why are 420, 450 and 499 missing from the list?

Because they are not in the IANA registry. Each was invented by a single vendor — 499 by nginx, for a client that disconnected before replying — so nothing outside that ecosystem is obliged to understand them.

Should a successful POST return 200 or 201?

201 Created is the better answer when the request made something new, because it carries a Location header pointing at the thing that now exists. Use 200 when the work is done but nothing new has an address of its own.

When is 204 the right response?

When the request succeeded and there is genuinely nothing to send back — a DELETE that removed a row, or a PUT that changed one.

Is 202 Accepted right for a job I queue rather than run?

202 says the request was accepted and the processing has not finished, which is exactly the situation. It promises nothing about the outcome, so pair it with a URL the client can poll; otherwise the caller has been told only that you took the message.

What is the difference between 406 and 415?

They fail on opposite halves of the request. 415 Unsupported Media Type rejects the body you sent, because its Content-Type is something the endpoint cannot parse. 406 Not Acceptable rejects the format you asked for in Accept, because the server has nothing to offer in that type. A client sending XML to a JSON-only endpoint gets 415; a client asking for XML back gets 406.

How long does a browser remember a 301?

Longer than you will like. Permanent redirects are cached hard, and some browsers keep one until the profile is cleared, so a 301 published by mistake can outlive the fix by months. Use 302 or 307 while you are still deciding.

Is 400 acceptable as a catch-all for anything the client got wrong?

It is valid, and it throws away information. A client that receives 400 learns only that something was wrong somewhere, whereas 401, 404, 409, 413, 415 and 422 each tell it something it can act on without parsing your prose.