---
title: "HTTP Status Codes Cheatsheet"
slug: "http-status-codes"
category: "cheatsheets"
tags: ["cheatsheets", "http", "api", "rest", "reference"]
status: "stable"
last_updated: 2026-05-14
summary: "Full table of HTTP status codes with meaning and when each is correct, plus a 'what to use when' guide for API design."
related:
  [
    "[[backend/fastapi]]",
    "[[frontend/forms]]",
    "[[cheatsheets/css-selectors]]",
    "[[ops/cloudflare]]",
    "[[cheatsheets/index|Cheatsheets]]",
  ]
---

## Overview

Pick the status code by intent, not by tradition. The class (1xx, 2xx, 3xx, 4xx, 5xx) tells the client what to do next; the specific code adds a reason. This card lists every code worth using in an API plus the "what to use when" map. For the umbrella API rules, see [[backend/fastapi]].

## 1xx Informational

Rare in app code; mostly handled by the protocol layer.

| Code                    | Meaning                             | When                                  |
| ----------------------- | ----------------------------------- | ------------------------------------- |
| 100 Continue            | Server accepts a request body.      | Used with `Expect: 100-continue`.     |
| 101 Switching Protocols | Server upgrading the connection.    | Used for WebSocket upgrades.          |
| 103 Early Hints         | Headers sent before final response. | Preload hints during slow processing. |

Almost no application code should emit a 1xx response directly.

## 2xx Success

Pick the most specific success code.

| Code                | Meaning                                | When                                                                      |
| ------------------- | -------------------------------------- | ------------------------------------------------------------------------- |
| 200 OK              | Generic success with a body.           | Default for `GET` and most `POST` results.                                |
| 201 Created         | Resource was created.                  | `POST` or `PUT` that created a new entity; include the `Location` header. |
| 202 Accepted        | Request accepted for async processing. | Job queued; return a job ID and a polling URL.                            |
| 204 No Content      | Success, no response body.             | `DELETE`, `PUT` that does not need to echo the resource.                  |
| 206 Partial Content | Range request honored.                 | Video streaming, resumable downloads.                                     |

`201` is correct for resource creation. `200` is acceptable but loses the "newly created" signal.

## 3xx Redirection

The browser usually handles these without app code looking.

| Code                   | Meaning                                          | When                                                        |
| ---------------------- | ------------------------------------------------ | ----------------------------------------------------------- |
| 301 Moved Permanently  | Resource has a new URL forever.                  | URL restructure; search engines update.                     |
| 302 Found              | Temporary redirect; keeps method only by chance. | Avoid; pick 303 or 307.                                     |
| 303 See Other          | After `POST`, GET this URL.                      | Post-Redirect-Get pattern for form submissions.             |
| 304 Not Modified       | Cached copy is still valid.                      | Sent in response to `If-None-Match` or `If-Modified-Since`. |
| 307 Temporary Redirect | Temporary, keep the method.                      | Use for non-GET temporary redirects.                        |
| 308 Permanent Redirect | Permanent, keep the method.                      | Permanent redirect for `POST` and `PUT`.                    |

Use `308` for permanent redirects that must keep the request method. `301` rewrote `POST` to `GET` in old clients.

## 4xx Client errors

The most common API responses. Be specific; clients debug from the code.

| Code                              | Meaning                                     | When                                                                        |
| --------------------------------- | ------------------------------------------- | --------------------------------------------------------------------------- |
| 400 Bad Request                   | Malformed request the server cannot parse.  | JSON syntax error, missing required field.                                  |
| 401 Unauthorized                  | No or bad credentials.                      | Authentication failure. The name is misleading; it means "unauthenticated." |
| 402 Payment Required              | Reserved; some APIs use for plan limits.    | Stripe and a few others.                                                    |
| 403 Forbidden                     | Authenticated but not allowed.              | Authorization failure.                                                      |
| 404 Not Found                     | Resource does not exist.                    | Unknown id, wrong path.                                                     |
| 405 Method Not Allowed            | Wrong verb for this route.                  | Include `Allow:` header.                                                    |
| 406 Not Acceptable                | No representation matches `Accept`.         | Content negotiation failure.                                                |
| 408 Request Timeout               | Client took too long to send.               | Idle connection; rare.                                                      |
| 409 Conflict                      | State conflict, retry will not help.        | Optimistic concurrency, duplicate insert.                                   |
| 410 Gone                          | Resource existed; intentionally removed.    | Stronger signal than 404 for sunset URLs.                                   |
| 411 Length Required               | Server requires `Content-Length`.           | Streaming uploads.                                                          |
| 412 Precondition Failed           | `If-Match` or `If-Unmodified-Since` failed. | Optimistic locking.                                                         |
| 413 Payload Too Large             | Body exceeds server limit.                  | File upload over the limit.                                                 |
| 414 URI Too Long                  | URL itself is too long.                     | Switch to `POST` body.                                                      |
| 415 Unsupported Media Type        | `Content-Type` not handled.                 | Wrong serialization.                                                        |
| 422 Unprocessable Entity          | Body parsed but semantically invalid.       | Validation failure on parsed JSON.                                          |
| 423 Locked                        | Resource is locked.                         | WebDAV; rare elsewhere.                                                     |
| 425 Too Early                     | Replay risk.                                | TLS 0-RTT.                                                                  |
| 428 Precondition Required         | Use `If-Match` or similar.                  | Force optimistic locking.                                                   |
| 429 Too Many Requests             | Rate limit exceeded.                        | Include `Retry-After:` header.                                              |
| 451 Unavailable For Legal Reasons | Blocked by legal demand.                    | Censorship, takedowns.                                                      |

`401` vs `403` trips engineers up. `401` means "the server does not know who you are." `403` means "I know who you are; you cannot do this."

## 5xx Server errors

Server bugs or upstream failures. These should page someone.

| Code                                | Meaning                                 | When                                |
| ----------------------------------- | --------------------------------------- | ----------------------------------- |
| 500 Internal Server Error           | Unhandled exception.                    | The default when nothing else fits. |
| 501 Not Implemented                 | The method is not supported at all.     | Stub endpoints.                     |
| 502 Bad Gateway                     | Upstream returned an invalid response.  | Proxy or gateway error.             |
| 503 Service Unavailable             | Server is overloaded or in maintenance. | Include `Retry-After:`.             |
| 504 Gateway Timeout                 | Upstream did not reply in time.         | Slow database or downstream API.    |
| 507 Insufficient Storage            | Out of disk.                            | WebDAV; rare.                       |
| 511 Network Authentication Required | Captive portal.                         | Cafe Wi-Fi.                         |

`503` is the correct choice for planned maintenance; `500` is the wrong code for "we are deploying."

## API design: what to use when

The most common decisions in one place.

| Action                                 | Status                                     |
| -------------------------------------- | ------------------------------------------ |
| Created a resource                     | 201 with `Location:` header.               |
| Updated a resource (no body returned)  | 204.                                       |
| Updated a resource (body returned)     | 200.                                       |
| Deleted a resource                     | 204 (or 200 with confirmation body).       |
| Validation failed on JSON body         | 422 with field errors.                     |
| Missing required header or query param | 400.                                       |
| User not authenticated                 | 401 with `WWW-Authenticate:` header.       |
| Authenticated user lacks permission    | 403.                                       |
| Resource missing                       | 404 (or 410 if it was deleted on purpose). |
| Duplicate insert / version conflict    | 409.                                       |
| Rate limit hit                         | 429 with `Retry-After:`.                   |
| Async job accepted                     | 202 with `Location:` to a status URL.      |
| Maintenance window                     | 503 with `Retry-After:`.                   |

## Common gotchas

- `200 OK` with `{"error": "..."}` in the body is wrong. The status code is part of the API.
- `401 Unauthorized` is really "unauthenticated." Use `403` when the user is known but lacks permission.
- `302` historically rewrote `POST` to `GET`. Use `303` for the Post-Redirect-Get pattern or `307` for "same method."
- Returning `200` from a `POST` that created a resource loses information that `201` carries.
- `404` and `410` are both "not here." Use `410` when the URL is intentionally retired so caches and crawlers stop trying.
- `Retry-After:` is a header that pairs with `429` and `503`. Clients honor it; omitting it forces blind retries.

## Related

- [[backend/fastapi]]
- [[frontend/forms]]
- [[cheatsheets/css-selectors]]
- [[ops/cloudflare]]
- [[cheatsheets/index|Cheatsheets]]
