HTTP status codes
Каждый HTTP-ответ начинается со статуса: три цифры + reason phrase. HTTP/1.1 200 OK. Первая цифра — категория, две остальные — конкретный код. Определены в RFC 9110.
Пять категорий
| Диапазон | Категория | Смысл |
|---|---|---|
| 1xx | Informational | «Продолжай», предварительный ответ |
| 2xx | Success | Всё окей |
| 3xx | Redirection | Иди в другое место |
| 4xx | Client error | Ты неправильно попросил |
| 5xx | Server error | Я не смог |
1xx
- 100 Continue — «продолжай отправлять тело после Expect: 100-continue».
- 101 Switching Protocols — WebSocket upgrade, HTTP/2 upgrade, HTTPUpgrade.
- 102 Processing — WebDAV, «работаю».
- 103 Early Hints — «пока думаю, можешь начать грузить эти ресурсы» (server push для HTTP/2).
2xx — успех
| Код | Значение |
|---|---|
| 200 OK | Обычный успех |
| 201 Created | Создан новый ресурс (обычно после POST/PUT) |
| 202 Accepted | Принято к обработке, но ещё не готово (async job) |
| 204 No Content | Успех, но тела нет (типа DELETE) |
| 206 Partial Content | Range-запрос, частичный контент (докачка) |
3xx — редиректы
| Код | Значение | Метод меняется? | Кэшируется |
|---|---|---|---|
| 301 Moved Permanently | Перемещено навсегда | Исторически да (POST→GET), спорно | Да, надолго |
| 302 Found | Временный редирект | Исторически да (POST→GET) | По Cache-Control |
| 303 See Other | Смотри там (POST→GET forced) | Да, всегда GET | Нет |
| 304 Not Modified | Кэш свежий (ответ на If-None-Match / If-Modified-Since) | — | — |
| 307 Temporary Redirect | Временный, но метод НЕ меняется | Нет | Нет |
| 308 Permanent Redirect | Постоянный, метод НЕ меняется | Нет | Да |
Ключевая разница: 301/302 исторически меняли POST→GET (браузеры так делали). 307/308 — гарантированно сохраняют метод. Для новых редиректов лучше 308/307.
4xx — клиент ошибся
| Код | Значение |
|---|---|
| 400 Bad Request | Запрос кривой (невалидный JSON, missing headers) |
| 401 Unauthorized | Не залогинен (нужен Authorization). Возвращается с WWW-Authenticate |
| 403 Forbidden | Залогинен, но прав нет |
| 404 Not Found | Нету такого ресурса |
| 405 Method Not Allowed | URL есть, но метод не подходит (сервер шлёт Allow) |
| 406 Not Acceptable | Не могу отдать в запрошенном формате (Accept) |
| 408 Request Timeout | Клиент долго молчал |
| 409 Conflict | Конфликт состояний (например Etag не совпал при PUT) |
| 410 Gone | Ресурс был, удалён навсегда, не приходи больше |
| 411 Length Required | Нужен Content-Length |
| 412 Precondition Failed | If-Match / If-None-Match не выполнился |
| 413 Payload Too Large | Тело слишком большое |
| 414 URI Too Long | URL слишком длинный |
| 415 Unsupported Media Type | Не тот Content-Type |
| 416 Range Not Satisfiable | Запрошенный Range за пределами файла |
| 418 I'm a teapot | Первоапрельская шутка RFC 2324, живёт до сих пор |
| 422 Unprocessable Entity | JSON валидный, но семантика неправильная (валидация полей) |
| 425 Too Early | Не хочу обрабатывать 0-RTT данные, повтори без Early Data |
| 428 Precondition Required | Сервер требует If-Match (защита от lost update) |
| 429 Too Many Requests | Rate limit. Обычно с Retry-After |
| 431 Request Header Fields Too Large | Заголовки слишком большие |
| 451 Unavailable For Legal Reasons | Заблокировано по закону (роскомнадзор, DMCA). Отсылка к 451°F |
5xx — сервер обосрался
| Код | Значение |
|---|---|
| 500 Internal Server Error | Общая «что-то сломалось внутри» |
| 501 Not Implemented | Метод не реализован |
| 502 Bad Gateway | Прокси не смог получить ответ от upstream |
| 503 Service Unavailable | Временно перегружен / на обслуживании. С Retry-After |
| 504 Gateway Timeout | Прокси ждал ответ, не дождался |
| 505 HTTP Version Not Supported | Не понимаю такой HTTP |
| 507 Insufficient Storage | Нет места на диске (WebDAV) |
| 508 Loop Detected | Циклический редирект |
| 521 Web Server Is Down | Cloudflare non-standard: origin недоступен |
| 522 Connection Timed Out | Cloudflare non-standard |
| 523 Origin Is Unreachable | Cloudflare non-standard |
| 524 A Timeout Occurred | Cloudflare non-standard: origin долго думал |
Тонкости
- 200 OK с ошибкой внутри JSON — распространённая антипаттерна REST API (Facebook Graph API). Правильно — использовать 4xx/5xx.
- 404 vs 410. 404 «может появится», 410 «удалено навсегда». SEO различает.
- 401 vs 403. 401 = «залогинься», 403 = «залогинен, но не пущу».
- 418. Юмористический код из RFC 2324 (заваривание кофе через чайник). Nginx поддерживает, Google-серверы возвращают на некоторые запросы, Node.js оставили.