При вызове API 401 Unauthorized, 403 Forbidden и 429 Too Many Requests являются тремя наиболее распространёнными типами ошибок.
Все они относятся к клиентским ошибкам 4xx, но способы их решения совершенно различаются:
- 401: сбой аутентификации — сервер не может подтвердить, «кто вы»
- 403: доступ запрещён — сервер понимает запрос, но не разрешает его выполнить
- 429: слишком много запросов — скорость вызовов или объём использования превышают ограничения
Если не различать типы ошибок и сразу повторять запросы, это не только не решит проблему, но и может вызвать шторм повторных попыток и даже привести к дополнительным ограничениям интерфейса.
В этой статье с помощью чек-листов устранения неполадок, команд curl и кода Node.js будет объяснено, как следует обрабатывать эти три типа ошибок.
¶ Понимание 401, 403 и 429 в одной таблице
| Код состояния | Основное значение | Распространённые причины | Следует ли немедленно повторять запрос |
|---|---|---|---|
401 Unauthorized |
Отсутствуют действительные учётные данные | Неверный API Key, истёкший Token, неверный формат заголовка аутентификации | Не следует повторять в исходном виде |
403 Forbidden |
Сервер отказывается обрабатывать запрос | Недостаточно прав, ограничения IP или региона, политика ресурса, блокировка WAF | Обычно не следует |
429 Too Many Requests |
Запросы превышают ограничения скорости или квоты | Слишком высокая параллельность, превышение QPS, исчерпание квоты | Повторить после ожидания |
Следует отметить, что, хотя английское название 401 — Unauthorized, при практическом устранении неполадок его лучше понимать как «не пройдена аутентификация»; 403 же обычно связан с авторизацией или политиками доступа.
¶ I. 401 Unauthorized: сначала проверьте учётные данные аутентификации

HTTP 401 Unauthorized означает, что в запросе отсутствуют действительные учётные данные аутентификации, необходимые для целевого ресурса. Стандартный ответ 401 обычно сообщает клиенту через заголовок ответа WWW-Authenticate, какую схему аутентификации ожидает сервер.
¶ Распространённые причины
- Не отправлен заголовок запроса
Authorization - API Key или Access Token указан неверно
- Token истёк или был отозван
- Неверная схема аутентификации, например пропущен
Bearer - Переменные окружения не были правильно загружены
- Используется ключ из неверного окружения
- При перенаправлении запроса через прокси или шлюз заголовок аутентификации был утерян
- Разница во времени между клиентом и сервером слишком велика, из-за чего подпись становится недействительной
¶ Распространённые ошибки
Интерфейс требует Bearer Token:
Authorization: Bearer YOUR_ACCESS_TOKEN
Но клиент отправляет:
Authorization: YOUR_ACCESS_TOKEN
Или ошибочно записывает так:
Authentication: Bearer YOUR_ACCESS_TOKEN
Обе ситуации могут вернуть 401.
¶ Устранение неполадок с помощью curl
Не ограничивайтесь просмотром только тела ответа с самого начала. Добавьте -i, чтобы одновременно проверить код состояния и заголовки ответа:
curl -i "https://api.example.com/v1/profile" \
-H "Authorization: Bearer $API_TOKEN" \
-H "Accept: application/json"
Особое внимание проверьте следующее:
- Действительно ли был отправлен
Authorization - Верна ли схема аутентификации
- Нет ли пробелов или переводов строки до или после Token
- Что вернул
WWW-Authenticate - Есть ли в теле ответа такие сообщения об ошибках, как
invalid_token,expired_tokenи другие
Если нужно просмотреть более подробный процесс запроса, можно использовать:
curl -v "https://api.example.com/v1/profile" \
-H "Authorization: Bearer $API_TOKEN"
Внимание: отладочные логи могут содержать Token. Не отправляйте полные логи напрямую в публичные Issue, групповые чаты или заявки в поддержку.
¶ Следует ли повторять 401?
Не следует многократно повторять запрос с одними и теми же недействительными учётными данными.
Рекомендуемый процесс:
- Проверьте, содержит ли запрос информацию аутентификации
- Проверьте, не истёк ли Token, не был ли отозван или неверно скопирован
- Если поддерживается Refresh Token, один раз обновите токен доступа
- Повторите запрос один раз с новым Token
- Если всё ещё возвращается 401, прекратите повторные попытки и зафиксируйте ошибку
Если используется постоянный API Key, следует проверить статус ключа или заменить его действительным ключом, а не повторять запросы в цикле.
¶ II. 403 Forbidden: аутентификация может быть успешной, но запрос всё равно отклонён

403 Forbidden означает, что сервер уже понял запрос, но отказывается его обрабатывать. Для типичной ошибки прав доступа даже повторная аутентификация не решит проблему автоматически; если не изменить запрос или конфигурацию прав, повторные запросы обычно будут по-прежнему завершаться неудачей.
¶ Распространённые причины
- У текущего аккаунта или ключа отсутствуют необходимые права
- Недостаточный Scope у Token
- Выполнен доступ к ресурсу, не принадлежащему текущему проекту или арендатору
- Исходный IP отсутствует в белом списке
- Регион источника запроса ограничен
- Блокировка WAF, брандмауэром или системой защиты от злоупотреблений
- Аккаунт, проект или ресурс отключён
- Интерфейс доступен только для определённых тарифов или ролей
- Подпись действительна, но область ресурса в подписи не соответствует
- В сценарии браузера действуют ограничения политик CSRF, Origin или Referer
¶ Разница между 401 и 403
Быстро определить можно двумя фразами:
- 401: сервер не может подтвердить, кто вы
- 403: сервер знает или понимает вашу личность и запрос, но не разрешает вам это делать
Например, обычный участник с действительным Token вызывает интерфейс «удалить организацию»:
curl -i -X DELETE \
"https://api.example.com/v1/organizations/org_123" \
-H "Authorization: Bearer $API_TOKEN"
Если Token действителен, но аккаунт не является администратором организации, сервер может вернуть:
HTTP/1.1 403 Forbidden
Content-Type: application/json
{
"error": "insufficient_permissions",
"message": "Administrator role is required."
}
¶ Порядок устранения неполадок 403
¶ 1. Прочитайте тело ответа
В первую очередь ищите код ошибки, отсутствующую роль или право, необходимый Scope, отклонённый ID ресурса, а также подсказки об IP, регионе или политике безопасности.
¶ 2. Проверьте Token Scope
Например, для чтения данных может требоваться только data:read, но для создания данных может понадобиться data:write. Действительный Token не означает наличие всех прав.
¶ 3. Проверьте принадлежность ресурса
Убедитесь, что ID проекта, ID организации, ID арендатора, ID пользователя, регион или окружение относятся к тому же аккаунту или области авторизации, что и текущие учётные данные.
¶ 4. Проверьте сетевые политики и политики безопасности
Если код нормально работает локально, но после развертывания возвращает 403, следует в первую очередь проверить исходящий IP сервера, IP-белый список, конфигурацию прокси, CDN, WAF, регион источника запроса и соответствующие заголовки запроса.
¶ Не делайте выводы только по статус-коду
Реальные реализации API не обязательно полностью совпадают. Некоторые платформы при срабатывании ограничения скорости могут возвращать 403, а не 429. Например, GitHub REST API может при превышении лимита скорости возвращать 403 или 429 и указывать состояние ограничения через такие заголовки ответа, как x-ratelimit-remaining, x-ratelimit-reset или retry-after.
Поэтому при возникновении 403 также необходимо комплексно проверить:
- Бизнес-код ошибки в теле ответа
Retry-AfterX-RateLimit-RemainingX-RateLimit-Reset- Официальную документацию платформы
¶ Следует ли повторять запрос при 403?
Для 403, вызванного недостаточными правами, IP-ограничениями или политикой ресурса, повторная отправка запроса без изменений не имеет смысла.
Правильный подход — изменить права или Token Scope, использовать правильный аккаунт или проект, скорректировать белый список и политики безопасности, исправить ID ресурса, а также подтвердить, что сервис или тариф поддерживает данный интерфейс. Только если платформа явно указывает, что этот 403 фактически означает временное ограничение скорости, следует подождать и повторить запрос согласно правилам ограничения скорости.
¶ Три, 429 Too Many Requests: сначала снизьте скорость, затем повторите запрос

429 Too Many Requests означает, что клиент отправил слишком много запросов за определенный период времени, то есть сработало ограничение скорости. Сервер может через Retry-After сообщить клиенту, сколько времени следует подождать перед повторной попыткой.
¶ Распространенные причины
- Слишком большое количество запросов за короткое время
- Слишком высокое количество параллельных задач
- Несколько сервисов используют один и тот же API Key
- В коде повторных попыток отсутствует механизм ожидания
- Планировщики задач массово выполняются в один и тот же момент
- Запросы не кэшируются, одни и те же данные получаются повторно
- Исчерпана квота одного аккаунта, IP или проекта
- Ограничения по использованию тарифа или балансу
¶ Сначала проверьте заголовки ответа
curl -i "https://api.example.com/v1/resources" \
-H "Authorization: Bearer $API_TOKEN"
Обратите особое внимание на:
Retry-After: 30
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1710000000
Названия заголовков ответа на разных платформах могут отличаться, следует руководствоваться документацией платформы.
¶ Правильная обработка Retry-After
Два распространенных формата Retry-After — количество секунд или HTTP-дата:
Retry-After: 30
Retry-After: Wed, 21 Oct 2026 07:28:00 GMT
Клиенту лучше поддерживать оба этих формата.
¶ Почему нельзя повторять запрос немедленно?
Если сразу повторить запрос после его ограничения по скорости, новый запрос также будет ограничен; несколько клиентов также могут повторить запрос одновременно, создавая «стадный эффект». Более надежный подход:
- В первую очередь соблюдать
Retry-After - При отсутствии явного времени ожидания использовать экспоненциальную задержку
- Добавлять случайное отклонение ко времени ожидания
- Устанавливать максимальное количество повторных попыток
- После достижения лимита возвращать понятную ошибку
¶ Node.js:безопасная обработка 429
Приведенный ниже пример использует встроенный в Node.js fetch, в первую очередь разбирает Retry-After; если сервер не предоставил этот заголовок ответа, используется экспоненциальная задержка со случайным отклонением.
const sleep = (ms) =>
new Promise((resolve) => setTimeout(resolve, ms));
function parseRetryAfter(value) {
if (!value) return null;
const seconds = Number(value);
if (Number.isFinite(seconds) && seconds >= 0) {
return seconds * 1000;
}
const timestamp = Date.parse(value);
if (!Number.isNaN(timestamp)) {
return Math.max(0, timestamp - Date.now());
}
return null;
}
async function fetchWithRetry(url, options = {}, config = {}) {
const {
maxRetries = 3,
baseDelayMs = 1000,
maxDelayMs = 30_000,
} = config;
for (let attempt = 0; attempt <= maxRetries; attempt++) {
const response = await fetch(url, options);
if (response.status !== 429) {
return response;
}
if (attempt === maxRetries) {
throw new Error(
`请求持续受到限流,已达到最大重试次数:${maxRetries}`
);
}
const retryAfterMs = parseRetryAfter(
response.headers.get("retry-after")
);
const backoffCap = Math.min(
maxDelayMs,
baseDelayMs * 2 ** attempt
);
const jitterMs = Math.floor(Math.random() * backoffCap);
const delayMs = retryAfterMs ?? jitterMs;
console.warn(
`收到 429,第 ${attempt + 1} 次等待 ${delayMs}ms 后重试`
);
await sleep(delayMs);
}
throw new Error("请求失败");
}
Пример вызова:
const response = await fetchWithRetry(
"https://api.example.com/v1/resources",
{
headers: {
Authorization: `Bearer ${process.env.API_TOKEN}`,
Accept: "application/json",
},
},
{
maxRetries: 3,
baseDelayMs: 1000,
maxDelayMs: 30_000,
}
);
if (!response.ok) {
const errorBody = await response.text();
throw new Error(`API 请求失败:${response.status} ${errorBody}`);
}
const data = await response.json();
console.log(data);
¶ При повторе POST-запросов также нужно учитывать идемпотентность
Не все запросы подходят для автоматического повтора. Запросы на чтение, такие как GET и HEAD, обычно проще безопасно повторять. Для POST-запросов на создание заказа, списание средств, отправку сообщений и подобных операций клиент мог уже успешно отправить запрос, но не получить ответ из-за сетевого сбоя. В этом случае прямое повторение может привести к дублированию операций.
Если платформа поддерживает это, для операций записи следует устанавливать ключ идемпотентности:
curl -i -X POST "https://api.example.com/v1/orders" \
-H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-20260331-0001" \
-d '{
"product_id": "prod_123",
"quantity": 1
}'
Название заголовка запроса для ключа идемпотентности и срок его действия определяются конкретной платформой, следует обратиться к соответствующей документации API.
¶ Контрольный список устранения неполадок в производственной среде
¶ Получен 401
- Содержит ли запрос заголовок аутентификации
- Верна ли схема аутентификации, например
Bearer - Не истек ли Token, не был ли он отозван или скопирован с ошибкой
- Используется ли ключ правильного окружения
- Не удаляет ли прокси или шлюз заголовок аутентификации
- Точно ли установлено время клиента
- Можно ли безопасно обновить Token один раз
¶ Получен 403
- Имеет ли Token необходимый Scope
- Имеет ли текущий аккаунт необходимую роль
- Принадлежит ли ресурс текущему проекту или арендатору
- Находится ли исходящий IP в белом списке
- Не действуют ли региональные ограничения, WAF или политики безопасности
- Явно ли тело ответа указывает на права доступа или ограничение частоты
- Присутствует ли в заголовках ответа информация об ограничении частоты
¶ Получен 429
- Был ли прочитан
Retry-After - Были ли проверены заголовки ответа, связанные с ограничением частоты
- Используются ли экспоненциальная задержка и случайное дрожание
- Установлено ли максимальное количество повторных попыток
- Ограничена ли параллельность
- Кэшируются ли результаты повторяющихся запросов
- Можно ли объединять или отправлять запросы пакетами
- Достигнута ли квота тарифа или верхний предел использования аккаунта
¶ Какую диагностическую информацию рекомендуется записывать?
Рекомендуется записывать в журналы время запроса, имя хоста и путь API, HTTP-метод, код состояния, бизнес-код ошибки, request-id или trace-id, Retry-After, оставшуюся квоту ограничения частоты и время её сброса, количество повторных попыток и фактическое время ожидания.
Но не записывайте полный API Key, полный Access Token, Refresh Token, пароль пользователя или конфиденциальную персональную информацию в теле запроса.
¶ Финальная формула для оценки
401: сначала исправьте учётные данные, не повторяйте попытку со старым Token.
403: сначала исправьте права доступа или политику, не повторяйте тот же запрос без изменений.
429: соблюдайте время ожидания, используйте задержку, снижайте скорость, ограничивайте параллельность.
Код состояния — это лишь точка входа в устранение неполадок, а не весь ответ. Надёжный подход заключается в одновременном использовании HTTP-кода состояния, бизнес-кода ошибки в теле ответа, соответствующих заголовков ответа, документации платформы, ID запроса и журналов сервера, чтобы превратить «ошибку интерфейса» в инженерный механизм, который можно наблюдать, восстанавливать и поддерживать.

