HTTP статус коды: полная таблица с описанием (1xx–5xx)

← Вернуться к статьям

Введение

Каждый раз, когда ваш браузер или приложение отправляет запрос к серверу, в ответ приходит трёхзначный числовой код — HTTP статус код. Этот код сообщает, что произошло: запрос выполнен успешно, ресурс переехал, клиент ошибся или сервер сломался.

Знание HTTP кодов — обязательный навык для любого разработчика, работающего с API, веб-приложениями или микросервисами. Без понимания этих кодов вы не сможете корректно обрабатывать ошибки, отлаживать запросы и строить надёжные системы.

В этой статье вы найдёте:

📋 Содержание

Что такое HTTP статус коды

HTTP статус код (HTTP Status Code) — это трёхзначное число, которое сервер возвращает клиенту в ответ на HTTP-запрос. Код сообщает о результате обработки запроса: был ли он успешен, требуется ли перенаправление, допустил ли клиент ошибку или произошёл сбой на сервере.

Простыми словами:

HTTP статус коды — это язык общения между клиентом и сервером. Клиент спрашивает: «Дай мне данные», а сервер отвечает числом: 200 — «Держи», 404 — «Не нашёл», 500 — «У меня всё сломалось».

Каждый HTTP-ответ содержит статус код в первой строке:

HTTP/1.1 200 OK
Content-Type: application/json

{"message": "Успех!"}

Здесь 200 — это статус код, а OK — текстовое описание (reason phrase).

Структура кодов (5 классов)

Все HTTP статус коды делятся на 5 классов по первой цифре. Зная только первую цифру, вы уже понимаете общий смысл ответа:

Класс Диапазон Значение Пример
1xx 100–103 Информационные — запрос принят, продолжайте 100 Continue
2xx 200–206 Успех — запрос выполнен успешно 200 OK
3xx 300–308 Перенаправление — нужно дополнительное действие 301 Moved Permanently
4xx 400–429 Ошибка клиента — проблема на стороне клиента 404 Not Found
5xx 500–504 Ошибка сервера — проблема на стороне сервера 500 Internal Server Error

Правило большого пальца:

1xx — Информационные коды

Информационные коды сообщают, что сервер принял запрос и продолжает обработку. В повседневной разработке они встречаются редко, но знать их полезно.

Код Название Описание
100 Continue Сервер получил заголовки запроса и клиент может продолжить отправку тела. Используется при отправке больших файлов — клиент сначала спрашивает «можно?», сервер отвечает «давай».
101 Switching Protocols Сервер переключается на другой протокол по запросу клиента. Самый частый случай — переход с HTTP на WebSocket (заголовок Upgrade: websocket).
102 Processing Сервер принял запрос, но ещё не завершил обработку. Предотвращает таймаут у клиента при долгих операциях (WebDAV).
103 Early Hints Позволяет серверу отправить предварительные заголовки (например, Link) до финального ответа. Браузер может начать предзагрузку ресурсов (CSS, JS) раньше.

2xx — Успех

Коды класса 2xx означают, что запрос клиента был принят и успешно обработан. Это самые желанные коды в ответе API.

Код Название Когда использовать
200 OK Стандартный успешный ответ. Используйте для GET (получение данных), PUT/PATCH (обновление с возвратом результата).
201 Created Ресурс успешно создан. Используйте для POST, когда создаётся новый объект. В заголовке Location возвращайте URL нового ресурса.
202 Accepted Запрос принят, но обработка ещё не завершена. Используйте для асинхронных операций: отправка email, генерация отчёта, запуск длительного процесса.
204 No Content Запрос успешен, но тело ответа пустое. Используйте для DELETE (удаление) или PUT/PATCH, когда возвращать данные не нужно.
206 Partial Content Сервер возвращает только часть ресурса. Используется для загрузки файлов по частям (заголовок Range), стриминга видео.

Примеры использования 200 и 201

// 200 OK — получение данных
fetch('/api/users')
  .then(res => {
    if (res.status === 200) {
      return res.json();
    }
  });

// 201 Created — создание нового ресурса
fetch('/api/users', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ name: 'Иван' })
}).then(res => {
  if (res.status === 201) {
    console.log('Пользователь создан');
    // Заголовок Location содержит URL нового ресурса
    console.log(res.headers.get('Location'));
  }
});

⚠️ Частая ошибка: всегда возвращать 200

Многие API на любой запрос возвращают 200 OK и кладут статус ошибки в тело ответа. Это антипаттерн. Используйте правильные коды: 201 для создания, 204 для удаления, 4xx для ошибок клиента.

3xx — Перенаправление

Коды класса 3xx сообщают, что для завершения запроса клиенту нужно выполнить дополнительное действие — обычно перейти по другому URL.

Код Название Описание Метод сохраняется?
301 Moved Permanently Ресурс навсегда перемещён на новый URL. Поисковые системы обновят индекс. Используйте при смене домена или структуры URL. Нет (может стать GET)
302 Found Ресурс временно доступен по другому URL. Поисковые системы сохраняют старый URL в индексе. Нет (может стать GET)
304 Not Modified Ресурс не изменился с момента последнего запроса. Клиент может использовать кэшированную версию. Экономит трафик.
307 Temporary Redirect Временное перенаправление с гарантией сохранения HTTP-метода. POST останется POST. Да
308 Permanent Redirect Постоянное перенаправление с сохранением HTTP-метода. Аналог 301, но метод не изменяется. Да

301 vs 302 vs 307 vs 308 — когда какой?

4xx — Ошибки клиента

Коды класса 4xx означают, что ошибка на стороне клиента. Сервер не может обработать запрос из-за некорректных данных, отсутствия авторизации или обращения к несуществующему ресурсу. Это самый важный класс для API-разработки.

400 Bad Request

Сервер не может обработать запрос из-за некорректного синтаксиса или невалидных данных.

Когда возникает:

// Пример: отправляем невалидный JSON
fetch('/api/users', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: '{ invalid json }'
});
// Ответ: 400 Bad Request
// { "error": "Invalid JSON in request body" }

401 Unauthorized

Клиент не авторизован. Требуется предоставить учётные данные (токен, логин/пароль).

Когда возникает:

// Запрос без токена авторизации
fetch('/api/profile');
// Ответ: 401 Unauthorized
// { "error": "Token is missing or expired" }

// Правильный запрос с токеном
fetch('/api/profile', {
  headers: { 'Authorization': 'Bearer eyJhbGciOi...' }
});
// Ответ: 200 OK

403 Forbidden

Сервер понял запрос, но отказывает в доступе. Авторизация пройдена, но прав недостаточно.

Когда возникает:

⚠️ Частая ошибка: путать 401 и 403

401 — «Я не знаю, кто ты. Представься.» (нужна авторизация)

403 — «Я знаю, кто ты, но тебе сюда нельзя.» (нет прав)

404 Not Found

Запрашиваемый ресурс не найден на сервере.

Когда возникает:

// Запрос к несуществующему ресурсу
fetch('/api/users/99999');
// Ответ: 404 Not Found
// { "error": "User with ID 99999 not found" }

405 Method Not Allowed

HTTP-метод не поддерживается для данного ресурса.

Когда возникает:

// Endpoint принимает только GET
fetch('/api/reports', { method: 'DELETE' });
// Ответ: 405 Method Not Allowed
// Заголовок Allow: GET, POST

408 Request Timeout

Сервер устал ждать запрос от клиента. Клиент слишком долго отправлял данные.

409 Conflict

Запрос конфликтует с текущим состоянием сервера.

Когда возникает:

// Попытка зарегистрировать существующий email
fetch('/api/users', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ email: 'ivan@example.com' })
});
// Ответ: 409 Conflict
// { "error": "User with this email already exists" }

413 Payload Too Large

Тело запроса слишком большое. Сервер отказывается его обрабатывать.

Когда возникает:

415 Unsupported Media Type

Сервер не поддерживает формат данных в запросе.

Когда возникает:

422 Unprocessable Entity

Сервер понял запрос, синтаксис корректен, но не может обработать содержащиеся в нём данные.

Когда возникает:

// Отправляем невалидные данные
fetch('/api/users', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ email: 'not-an-email', age: -5 })
});
// Ответ: 422 Unprocessable Entity
// {
//   "errors": {
//     "email": "Некорректный формат email",
//     "age": "Возраст должен быть положительным числом"
//   }
// }

⚠️ 400 vs 422 — когда что?

400 — запрос синтаксически некорректен (сломанный JSON, неправильный формат).

422 — запрос синтаксически корректен, но данные не прошли валидацию бизнес-логики.

429 Too Many Requests

Клиент отправил слишком много запросов за единицу времени (rate limiting).

Когда возникает:

// Ответ при превышении лимита
// HTTP/1.1 429 Too Many Requests
// Retry-After: 60
// X-RateLimit-Limit: 100
// X-RateLimit-Remaining: 0
// X-RateLimit-Reset: 1708700000

// Обработка 429 с повторной попыткой
async function fetchWithRetry(url, retries = 3) {
  const response = await fetch(url);

  if (response.status === 429 && retries > 0) {
    const retryAfter = response.headers.get('Retry-After') || 5;
    console.log(`Rate limit. Повтор через ${retryAfter}с...`);
    await new Promise(r => setTimeout(r, retryAfter * 1000));
    return fetchWithRetry(url, retries - 1);
  }

  return response;
}

5xx — Ошибки сервера

Коды класса 5xx означают, что проблема на стороне сервера. Запрос клиента был корректным, но сервер не смог его обработать. Обычно это повод для алерта в мониторинге.

500 Internal Server Error

Универсальная ошибка сервера. Что-то пошло не так, и сервер не может точнее описать проблему.

Причины:

// Серверный код (Node.js) — необработанное исключение
app.get('/api/data', async (req, res) => {
  // Если DB недоступна, выбросится исключение
  const data = await db.query('SELECT * FROM users');
  // Без try/catch клиент получит 500
  res.json(data);
});

// Правильная обработка
app.get('/api/data', async (req, res) => {
  try {
    const data = await db.query('SELECT * FROM users');
    res.json(data);
  } catch (error) {
    console.error('DB Error:', error);
    res.status(500).json({ error: 'Внутренняя ошибка сервера' });
  }
});

501 Not Implemented

Сервер не поддерживает запрошенную функциональность. Endpoint существует, но метод ещё не реализован.

Пример: API в разработке, где некоторые endpoints заглушены.

502 Bad Gateway

Промежуточный сервер (nginx, load balancer, CDN) получил некорректный ответ от upstream-сервера.

Причины:

503 Service Unavailable

Сервер временно недоступен. Обычно из-за перегрузки или планового обслуживания.

Причины:

// Заголовок Retry-After указывает, когда повторить
// HTTP/1.1 503 Service Unavailable
// Retry-After: 120
// { "error": "Сервис временно недоступен. Повторите через 2 минуты." }

504 Gateway Timeout

Промежуточный сервер не дождался ответа от upstream-сервера.

Причины:

⚠️ 502 vs 504 — в чём разница?

502 Bad Gateway — upstream ответил, но ответ некорректный (приложение упало).

504 Gateway Timeout — upstream не ответил вообще в отведённое время (приложение зависло).

В обоих случаях проблема на backend — проверяйте логи приложения и nginx.

Как обрабатывать статус коды в коде

Рассмотрим примеры правильной обработки HTTP кодов на трёх языках.

JavaScript (fetch)

async function apiRequest(url, options = {}) {
  const response = await fetch(url, options);

  switch (response.status) {
    case 200:
    case 201:
      return await response.json();
    case 204:
      return null;
    case 400:
      throw new Error('Некорректный запрос');
    case 401:
      throw new Error('Необходима авторизация');
    case 403:
      throw new Error('Доступ запрещён');
    case 404:
      throw new Error('Ресурс не найден');
    case 422: {
      const body = await response.json();
      throw new Error(`Ошибка валидации: ${JSON.stringify(body.errors)}`);
    }
    case 429:
      throw new Error('Слишком много запросов');
    case 500:
      throw new Error('Ошибка сервера');
    case 502:
      throw new Error('Сервер недоступен (Bad Gateway)');
    case 503:
      throw new Error('Сервис временно недоступен');
    case 504:
      throw new Error('Таймаут сервера');
    default:
      throw new Error(`Неизвестная ошибка: ${response.status}`);
  }
}

// Использование
try {
  const users = await apiRequest('/api/users');
  console.log(users);
} catch (error) {
  console.error(error.message);
}

Python (requests)

import requests

def api_request(url, method='GET', **kwargs):
    response = requests.request(method, url, **kwargs)

    if response.status_code == 200:
        return response.json()
    elif response.status_code == 201:
        return response.json()
    elif response.status_code == 204:
        return None
    elif response.status_code == 400:
        raise Exception('Некорректный запрос')
    elif response.status_code == 401:
        raise Exception('Необходима авторизация')
    elif response.status_code == 403:
        raise Exception('Доступ запрещён')
    elif response.status_code == 404:
        raise Exception('Ресурс не найден')
    elif response.status_code == 422:
        errors = response.json().get('errors', {})
        raise Exception(f'Ошибка валидации: {errors}')
    elif response.status_code == 429:
        retry_after = response.headers.get('Retry-After', 5)
        raise Exception(f'Rate limit. Повторите через {retry_after}с')
    elif response.status_code >= 500:
        raise Exception(f'Ошибка сервера: {response.status_code}')
    else:
        raise Exception(f'Неизвестная ошибка: {response.status_code}')

# Использование
try:
    users = api_request('https://api.example.com/users')
    print(users)
except Exception as e:
    print(f'Ошибка: {e}')

PHP (cURL)

<?php

function apiRequest(string $url, string $method = 'GET', ?array $data = null): mixed
{
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);

    if ($data !== null) {
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json'
        ]);
    }

    $response = curl_exec($ch);
    $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    return match (true) {
        $statusCode === 200, $statusCode === 201 => json_decode($response, true),
        $statusCode === 204 => null,
        $statusCode === 400 => throw new Exception('Некорректный запрос'),
        $statusCode === 401 => throw new Exception('Необходима авторизация'),
        $statusCode === 403 => throw new Exception('Доступ запрещён'),
        $statusCode === 404 => throw new Exception('Ресурс не найден'),
        $statusCode === 429 => throw new Exception('Слишком много запросов'),
        $statusCode >= 500   => throw new Exception("Ошибка сервера: {$statusCode}"),
        default               => throw new Exception("Неизвестная ошибка: {$statusCode}"),
    };
}

// Использование
try {
    $users = apiRequest('https://api.example.com/users');
    print_r($users);
} catch (Exception $e) {
    echo "Ошибка: " . $e->getMessage();
}

Самые частые ошибки при работе с API

✅ Правила хорошего тона

  1. Используйте правильные коды — не возвращайте 200 для ошибок
  2. Добавляйте описание ошибки — в теле ответа объясняйте, что пошло не так
  3. Будьте консистентны — один формат ошибок во всём API
  4. Не раскрывайте внутренности — не отправляйте stack trace клиенту
  5. Логируйте 5xx ошибки — это баги, которые нужно чинить

❌ Антипаттерны

⚠️ Формат ошибок — будьте консистентны

Используйте единый формат ошибок во всём API:

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Ошибка валидации данных",
    "details": {
      "email": "Некорректный формат email",
      "age": "Должно быть положительным числом"
    }
  }
}

FAQ

❓ Чем отличается 401 от 403?

Ответ: 401 Unauthorized означает, что клиент не предоставил учётные данные или они недействительны — нужно авторизоваться. 403 Forbidden означает, что сервер знает, кто вы (авторизация пройдена), но отказывает в доступе — у вас нет прав.

401 → «Кто ты? Покажи пропуск»  (нет токена / токен невалидный)
403 → «Я тебя знаю, но сюда нельзя» (нет прав на ресурс)

❓ Когда использовать 200 vs 201 vs 204?

Ответ:

  • 200 OK — для GET, PUT, PATCH, когда возвращаете данные в теле ответа
  • 201 Created — для POST, когда создан новый ресурс. Добавьте заголовок Location с URL нового ресурса
  • 204 No Content — для DELETE или когда тело ответа не нужно (успешное обновление без возврата данных)

❓ Что делать при получении 429 Too Many Requests?

Ответ:

  1. Проверьте заголовок Retry-After — он указывает, через сколько секунд можно повторить запрос
  2. Реализуйте exponential backoff — увеличивайте паузу между повторами (1с → 2с → 4с → 8с)
  3. Кэшируйте ответы, чтобы уменьшить количество запросов к API
  4. Проверьте заголовки X-RateLimit-Limit и X-RateLimit-Remaining для контроля лимитов

❓ Чем отличается 502 от 504?

Ответ: Оба кода означают проблему за прокси-сервером (nginx, load balancer), но причины разные:

  • 502 Bad Gateway — upstream-сервер ответил, но ответ некорректный (приложение упало, вернулась ошибка)
  • 504 Gateway Timeout — upstream-сервер не ответил вообще за отведённое время (запрос завис, таймаут)
502 → Backend ответил чушь (crash, невалидный ответ)
504 → Backend молчит (зависание, долгий запрос к БД)

Заключение

📝 Сводная таблица HTTP статус кодов

Класс Значение Ключевые коды Действие клиента
1xx Информация 100, 101, 103 Продолжить запрос
2xx Успех 200, 201, 204 Обработать ответ
3xx Перенаправление 301, 302, 304, 307 Перейти по новому URL
4xx Ошибка клиента 400, 401, 403, 404, 422, 429 Исправить запрос
5xx Ошибка сервера 500, 502, 503, 504 Повторить позже

HTTP статус коды — фундамент общения между клиентом и сервером. Правильное использование кодов делает ваш API понятным, предсказуемым и удобным для разработчиков. Неправильное — приводит к часам отладки и бесконечным вопросам от клиентов «а почему не работает?».

💡 Три главных правила:

  1. Используйте правильные коды — 201 для создания, 204 для удаления, 4xx для ошибок клиента
  2. Всегда объясняйте ошибку — код + понятное сообщение в теле ответа
  3. Обрабатывайте все коды на клиенте — не надейтесь, что сервер всегда вернёт 200

🎯 Тестируйте HTTP коды с LightBox API

Хотите проверить, как ваше приложение обрабатывает разные HTTP статус коды?

LightBox API позволяет создать Mock API с любыми статус кодами — настройте ответы 200, 400, 401, 404, 500 и тестируйте обработку ошибок.

Попробовать бесплатно →

Статья опубликована: 23 февраля 2026
Автор: LightBox API Team