Learning & reference

HTTP status codes, with the bit that actually matters

Every code, what it really means, and the QA note that goes with it — plus the four confusions (401/403, 302/307, 502/504, and 200-with-an-error-body) that cause the most bugs.

The five classes

The first digit is the whole story: 1xx still going, 2xx it worked, 3xx look elsewhere, 4xx you made a mistake, 5xx the server made a mistake.

1xx Informational

An interim response. The real one is still coming.

2xx Success

The request was received, understood and accepted.

3xx Redirection

Further action is needed, usually at a different URL.

4xx Client error

The request is wrong. Repeating it unchanged will not help.

5xx Server error

The request was fine; the server failed. Often worth a retry.

1xx Informational

CodeNameWhat it meansQA note
100ContinueHeaders received; send the body.Emitted when a client sends Expect: 100-continue before a large upload.
101Switching ProtocolsUpgrading, usually to WebSocket.The handshake response for Upgrade: websocket.
103Early HintsPreload hints before the real response.Some clients and proxies mishandle it - worth testing.

2xx Success

CodeNameWhat it meansQA note
200OKSuccess, with a body.Watch for APIs returning 200 with an error object inside - clients then never see a failure.
201CreatedA new resource exists.Must include a Location header pointing at it.
202AcceptedQueued, not finished.Asynchronous work. The client needs somewhere to poll.
204No ContentSuccess, no body at all.A body here is a protocol violation; some clients hang waiting for one.
206Partial ContentA byte range, not the whole file.Powers resumable downloads and video seeking. Test with Range:.

3xx Redirection

CodeNameWhat it meansQA note
301Moved PermanentlyPermanent new URL.Aggressively cached by browsers - a wrong 301 is very hard to undo.
302FoundTemporary redirect.Historically rewrites POST to GET, which is why 307 exists.
303See OtherFetch the result with GET.The correct POST-redirect-GET response.
304Not ModifiedYour cached copy is current.Sent when If-None-Match / If-Modified-Since match. Has no body.
307Temporary RedirectTemporary, method preserved.A POST stays a POST - unlike 302.
308Permanent RedirectPermanent, method preserved.The modern 301 for non-GET requests.

4xx Client error

CodeNameWhat it meansQA note
400Bad RequestMalformed - the server cannot parse it.Should not be a catch-all for validation errors; prefer 422.
401UnauthorizedYou are not authenticated.Misnamed. Must include WWW-Authenticate. Log in and retry.
403ForbiddenAuthenticated, but not allowed.Retrying with the same credentials will never work. The 401/403 mix-up is the classic auth bug.
404Not FoundNo such resource.Also used to hide existence from users who lack permission.
405Method Not AllowedWrong verb for this URL.Must list the valid verbs in an Allow header.
406Not AcceptableCannot satisfy Accept.Rare in practice; most servers just return their default type.
408Request TimeoutThe client was too slow sending.Test by opening a connection and stalling mid-body.
409ConflictClashes with current state.Duplicate keys, edit conflicts, optimistic-locking failures.
410GoneDeleted on purpose, permanently.Stronger than 404 - tells crawlers to drop the URL.
411Length RequiredNo Content-Length.
412Precondition FailedAn If-* header did not hold.The other half of optimistic concurrency with ETags.
413Content Too LargeBody exceeds the limit.The one to test with big uploads - many servers drop the connection instead.
414URI Too LongThe URL exceeds the limit.Usually ~8 KB. Hit it by putting a huge payload in the query string.
415Unsupported Media TypeWrong Content-Type.Common when a client forgets application/json.
416Range Not SatisfiableThe byte range is out of bounds.Test by requesting a range past end-of-file.
418I'm a teapotAn April Fools joke from 1998.Kept alive by popular demand. Handy as a unique sentinel in tests.
422Unprocessable ContentUnderstood, but semantically invalid.The right code for validation failures on a well-formed body.
425Too EarlyReplay risk on a 0-RTT request.TLS 1.3 early data.
428Precondition RequiredSend an If-Match.Forces clients into safe concurrent updates.
429Too Many RequestsRate limited.Should include Retry-After. Verify your client honours it instead of hammering.
431Header Fields Too LargeHeaders exceed the limit.Usually an oversized cookie.
451Unavailable For Legal ReasonsBlocked by law.The number references Fahrenheit 451.

5xx Server error

CodeNameWhat it meansQA note
500Internal Server ErrorUnhandled failure.Should never leak a stack trace to the client - check that in every environment.
501Not ImplementedThe server does not support the method.
502Bad GatewayAn upstream returned garbage.The proxy reached your app and disliked the answer.
503Service UnavailableDown or overloaded, probably briefly.Should carry Retry-After. The correct code during deploys and maintenance.
504Gateway TimeoutThe upstream never answered.The proxy gave up waiting - distinct from 502.
505HTTP Version Not Supported
507Insufficient StorageThe server is out of space.
511Network Authentication RequiredA captive portal is intercepting.Seen on hotel and airport Wi-Fi.

The four confusions worth testing

401 vs 403

401 = we do not know who you are, authenticate and try again. 403 = we know exactly who you are and you still may not. Returning 403 to a logged-out user sends them to a dead end instead of the login page.

302 vs 307

A 302 after a POST is historically rewritten to a GET, silently dropping the body. 307 and 308 preserve the method. If a form submission mysteriously loses data on redirect, this is why.

502 vs 504

502 means the upstream answered with something invalid; 504 means it never answered at all. They point at completely different failures.

200 with an error body

The worst anti-pattern: HTTP 200 wrapping {"error": "..."}. Every retry, alert and monitor treats it as success, so failures are invisible.

Trigger any status on demand

The HEXAQA worker returns whatever code you ask for, so you can prove your client handles it - including retries, redirect chains and timeouts.

Any status

gen.hexaqa.com/status/503

Redirect chain

gen.hexaqa.com/redirect/5

Stall before responding

gen.hexaqa.com/delay?ms=5000

Open the generator MIME types →