ReferenceBeginner4-6 min reference
HTTP Status Codes
Status codes are the contract between client and server. Knowing the difference between 401 and 403, or 502 and 504, will save you from filing the wrong bug ticket.
1xx Informational
The request was received and the server is continuing to process it. Rarely surfaces in test assertions — most clients handle these transparently.
| Code | Name | When you'll see it |
|---|---|---|
| 100 | Continue | Client sent Expect: 100-continue and may now send the body |
| 101 | Switching Protocols | Server agreeing to upgrade (e.g. WebSocket handshake) |
| 102 | Processing | WebDAV — request still being processed |
| 103 | Early Hints | Server preloading resources before final response |
2xx Success
The request succeeded.
| Code | Name | Test for it when... |
|---|---|---|
| 200 | OK | Generic success — GET returns a body, etc. |
| 201 | Created | POST that creates a resource (/users, /orders) |
| 202 | Accepted | Async operation queued (jobs, exports) |
| 203 | Non-Authoritative Information | Response was modified by a proxy |
| 204 | No Content | DELETE / PUT with no body to return |
| 205 | Reset Content | Form should be cleared after submit |
| 206 | Partial Content | Range requests (video streaming, resumable downloads) |
3xx Redirection
Further action needed to complete the request.
| Code | Name | Notes |
|---|---|---|
| 300 | Multiple Choices | Several representations available |
| 301 | Moved Permanently | URL has changed for good — clients cache the new one |
| 302 | Found | Temporary redirect (legacy — most APIs now use 307) |
| 303 | See Other | Used after POST to redirect to a GET (PRG pattern) |
| 304 | Not Modified | Cached response is still valid |
| 307 | Temporary Redirect | Like 302 but preserves the HTTP method |
| 308 | Permanent Redirect | Like 301 but preserves the HTTP method |
4xx Client Error
The request was malformed or unauthorised. Most regression tests live here.
| Code | Name | Test for it when... |
|---|---|---|
| 400 | Bad Request | Body fails validation, missing required field, malformed JSON |
| 401 | Unauthorized | No credentials, expired token, invalid signature |
| 402 | Payment Required | Reserved — used by some SaaS billing flows |
| 403 | Forbidden | Authenticated but lacks permission for this resource |
| 404 | Not Found | Resource doesn't exist (or is hidden from this user) |
| 405 | Method Not Allowed | POST to an endpoint that only accepts GET |
| 406 | Not Acceptable | Server can't produce content matching Accept header |
| 408 | Request Timeout | Client took too long to send the request |
| 409 | Conflict | Duplicate key, optimistic-locking failure |
| 410 | Gone | Resource permanently removed (different from 404) |
| 411 | Length Required | Missing Content-Length header |
| 412 | Precondition Failed | If-Match / If-Unmodified-Since failed |
| 413 | Payload Too Large | File upload exceeds server limit |
| 414 | URI Too Long | Query string blew past server limit |
| 415 | Unsupported Media Type | Content-Type the endpoint won't accept |
| 416 | Range Not Satisfiable | Range request beyond resource length |
| 417 | Expectation Failed | Expect header couldn't be met |
| 418 | I'm a teapot | RFC 2324 — easter egg, not for serious use |
| 422 | Unprocessable Entity | Body parses fine but is semantically invalid |
| 423 | Locked | WebDAV — resource is locked |
| 425 | Too Early | Server unwilling to process replayed request |
| 428 | Precondition Required | Server requires conditional headers |
| 429 | Too Many Requests | Rate limited — check Retry-After |
| 431 | Request Header Fields Too Large | Headers blew past server limit |
| 451 | Unavailable For Legal Reasons | Censored or geo-blocked |
401 vs 403 — the rule of thumb
- 401 Unauthorized = "I don't know who you are." Caller needs to authenticate.
- 403 Forbidden = "I know who you are, and you can't do this."
5xx Server Error
The server failed to fulfil a valid request. These should always trigger an alert in production.
| Code | Name | What's happening |
|---|---|---|
| 500 | Internal Server Error | Catch-all for unhandled exceptions |
| 501 | Not Implemented | HTTP method or feature not supported |
| 502 | Bad Gateway | Upstream server returned an invalid response |
| 503 | Service Unavailable | Overloaded or in maintenance — usually transient |
| 504 | Gateway Timeout | Upstream server took too long |
| 505 | HTTP Version Not Supported | Server won't speak the requested HTTP version |
| 507 | Insufficient Storage | WebDAV — server out of space |
| 508 | Loop Detected | WebDAV — infinite loop in PROPFIND |
| 511 | Network Authentication Required | Captive portal / paywall |
502 vs 503 vs 504 — the rule of thumb
- 502 Bad Gateway = upstream replied, but with garbage.
- 503 Service Unavailable = server is up but can't handle the request right now (overloaded, maintenance).
- 504 Gateway Timeout = upstream didn't reply in time.
Common test assertions
// Cypress
cy.request('/api/users/999').its('status').should('eq', 404);
// Playwright
const response = await request.post('/api/login', { data: { email, password: 'wrong' } });
expect(response.status()).toBe(401);
// REST Assured (Java)
given().get('/api/admin/users').then().statusCode(403);