HTTP status codes

Каждый HTTP-ответ начинается со статуса: три цифры + reason phrase. HTTP/1.1 200 OK. Первая цифра — категория, две остальные — конкретный код. Определены в RFC 9110.

Пять категорий

ДиапазонКатегорияСмысл
1xxInformational«Продолжай», предварительный ответ
2xxSuccessВсё окей
3xxRedirectionИди в другое место
4xxClient errorТы неправильно попросил
5xxServer errorЯ не смог

1xx

2xx — успех

КодЗначение
200 OKОбычный успех
201 CreatedСоздан новый ресурс (обычно после POST/PUT)
202 AcceptedПринято к обработке, но ещё не готово (async job)
204 No ContentУспех, но тела нет (типа DELETE)
206 Partial ContentRange-запрос, частичный контент (докачка)

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 AllowedURL есть, но метод не подходит (сервер шлёт Allow)
406 Not AcceptableНе могу отдать в запрошенном формате (Accept)
408 Request TimeoutКлиент долго молчал
409 ConflictКонфликт состояний (например Etag не совпал при PUT)
410 GoneРесурс был, удалён навсегда, не приходи больше
411 Length RequiredНужен Content-Length
412 Precondition FailedIf-Match / If-None-Match не выполнился
413 Payload Too LargeТело слишком большое
414 URI Too LongURL слишком длинный
415 Unsupported Media TypeНе тот Content-Type
416 Range Not SatisfiableЗапрошенный Range за пределами файла
418 I'm a teapotПервоапрельская шутка RFC 2324, живёт до сих пор
422 Unprocessable EntityJSON валидный, но семантика неправильная (валидация полей)
425 Too EarlyНе хочу обрабатывать 0-RTT данные, повтори без Early Data
428 Precondition RequiredСервер требует If-Match (защита от lost update)
429 Too Many RequestsRate 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 DownCloudflare non-standard: origin недоступен
522 Connection Timed OutCloudflare non-standard
523 Origin Is UnreachableCloudflare non-standard
524 A Timeout OccurredCloudflare non-standard: origin долго думал

Тонкости

См. также