Перейти к основному содержимому
Версия: 2026.2.4

Ограничения скорости

Voice реализует ограничения скорости (rate limiting) для запросов к HTTP API в соответствии с RFC 6585 — подробнее о самом факте ограничений см. раздел «Rate Limiting» в справочнике по API. Здесь описано, как именно это работает: какие заголовки возвращает сервер, что происходит при превышении лимита и как правильно организовать клиентский код, чтобы не полагаться на захардкоженные значения.

Заголовки​

Каждый ответ HTTP API, затронутый ограничением скорости, содержит набор заголовков, описывающих состояние текущего «окна» (bucket) на момент ответа:

ЗаголовокОписание
X-RateLimit-LimitЧисло запросов, которое разрешено выполнить в этом bucket'е за период его действия
X-RateLimit-RemainingСколько запросов из этого лимита осталось на момент ответа
X-RateLimit-ResetUnix-время (в секундах, с плавающей точкой), когда bucket сбросится и Remaining снова станет равным Limit
X-RateLimit-Reset-AfterСколько секунд осталось до сброса bucket'а — в отличие от Reset, не требует синхронизации часов клиента с сервером, поэтому предпочтительнее для расчётов
X-RateLimit-BucketХэш bucket'а, к которому относится этот запрос — см. «Bucket'ы ограничений»
X-RateLimit-ScopeОбласть действия лимита: user — привязан к вашему токену; global — общий лимит на все вызовы токена; shared — bucket, разделяемый между несколькими маршрутами
Ориентируйтесь на заголовки, а не на захардкоженные значения

Значения лимитов могут отличаться для разных маршрутов, меняться со временем и зависеть от статуса бота (см. «Боты» — у ботов отдельный набор ограничений). Не храните лимиты в коде библиотеки как константы — читайте их из заголовков ответа и стройте локальный счётчик запросов на их основе.

Превышение ограничения скорости​

Если bucket исчерпан, сервер отвечает HTTP 429 Too Many Requests вместо обычной обработки запроса.

Структура ответа при превышении лимита​

ПолеТипОписание
messagestringСообщение о том, что запрос ограничен по скорости
retry_afterfloatСколько секунд нужно подождать перед повторной попыткой
globalbooleanПризнак того, что сработал именно глобальный лимит, а не лимит конкретного маршрута
code?integerЧисловой код ошибки — присутствует не для всех видов ограничений

Обратите внимание, что обычные заголовки ограничения скорости, описанные выше, тоже присутствуют в этом ответе. Ответ выглядит примерно так:

Пример ответа: превышен пользовательский лимит​

< HTTP/1.1 429 TOO MANY REQUESTS
< Content-Type: application/json
< Retry-After: 65
< X-RateLimit-Limit: 10
< X-RateLimit-Remaining: 0
< X-RateLimit-Reset: 1470173023.123
< X-RateLimit-Reset-After: 64.57
< X-RateLimit-Bucket: abcd1234
< X-RateLimit-Scope: user

{
"message": "Превышено ограничение скорости.",
"retry_after": 64.57,
"global": false
}

Пример ответа: превышен лимит на ресурс​

< HTTP/1.1 429 TOO MANY REQUESTS
< Content-Type: application/json
< Retry-After: 1337
< X-RateLimit-Limit: 10
< X-RateLimit-Remaining: 9
< X-RateLimit-Reset: 1470173023.123
< X-RateLimit-Reset-After: 64.57
< X-RateLimit-Bucket: abcd1234
< X-RateLimit-Scope: shared

{
"message": "Ограничена скорость запросов к этому ресурсу.",
"retry_after": 1336.57,
"global": false
}

Пример ответа: превышен глобальный лимит​

< HTTP/1.1 429 TOO MANY REQUESTS
< Content-Type: application/json
< Retry-After: 65
< X-RateLimit-Global: true
< X-RateLimit-Scope: global

{
"message": "Превышено ограничение скорости.",
"retry_after": 64.57,
"global": true
}
Не увеличивайте частоту запросов в ответ на 429

Получив 429, дождитесь retry_after и повторите запрос один раз — не открывайте параллельные попытки и не уменьшайте паузу между запросами. Клиенты, которые систематически игнорируют 429, могут быть лишены API-ключей и заблокированы на платформе (см. «Rate Limiting»).

Глобальное ограничение скорости​

Любой бот может выполнять до 50 запросов в секунду к нашему API. Если заголовок авторизации не передан, лимит применяется к IP-адресу. Это ограничение не связано с лимитами на отдельные маршруты — исчерпание одного не влияет на остаток другого, а ответ 429 всегда указывает (X-RateLimit-Global и "global": true), какой именно лимит сработал. Если ваш бот достаточно крупный, в зависимости от его функциональности может оказаться невозможным оставаться ниже 50 запросов в секунду при обычной работе.

Проблемы с глобальным лимитом обычно проявляются как повторяющиеся временные блокировки уже на старте работы бота (см. ниже). Если ваш бот время от времени ненадолго блокируется, скорее всего, дело не в глобальном лимите — вероятнее, произошёл всплеск ошибок, который не был должным образом обработан, и был превышен порог некорректных запросов.

Если в рамках обычной работы бота вы регулярно сталкиваетесь с временными блокировками, обратитесь в поддержку Voice — возможно, для вашего бота стоит увеличить глобальный лимит.

Вызовы InteractionsApi не подчиняются описанному здесь глобальному лимиту HTTP API — это отдельный gRPC-сервис со своими правилами (см. «Interactions API»).

Ограничение на некорректные запросы​

IP-адреса, с которых поступает слишком много некорректных HTTP-запросов, автоматически и временно ограничиваются в доступе к API Voice. Сейчас этот лимит — 10 000 запросов за 10 минут. Некорректным считается запрос, завершившийся статусом 401, 403 или 429.

Все приложения должны предпринимать разумные усилия, чтобы избегать некорректных запросов, например:

  • ответов 401 можно избежать, передавая корректный токен в заголовке авторизации там, где он требуется, и прекращая дальнейшие запросы после того, как токен стал недействительным;
  • ответов 403 можно избежать, проверяя права роли или канала и не выполняя запросы, ограниченные такими правами;
  • ответов 429 можно избежать, проверяя описанные выше заголовки ограничения скорости и не выполняя запросы к исчерпанным bucket'ам до их сброса. Ответы 429 с X-RateLimit-Scope: shared не учитываются в этом лимите.

Крупным приложениям, особенно тем, что потенциально могут выполнять 10 000 запросов за 10 минут (устойчивые 16–17 запросов в секунду), стоит логировать и отслеживать долю некорректных запросов, чтобы не упереться в этот жёсткий лимит.

Кроме того, ожидается, что вы разумно обрабатываете и другие некорректные статусы. Например, если вебхук отвечает статусом 404, повторно обращаться к нему не следует — систематические попытки сделать это приведут к временному ограничению.

Bucket'ы ограничений​

Ограничение скорости считается не «по эндпоинту» в буквальном смысле URL, а по bucket'у — группе маршрутов, которая может учитывать не только сам маршрут, но и его «главный параметр» (например, ID группы или канала в пути запроса). Два разных маршрута могут делить один bucket (тогда X-RateLimit-Scope будет shared), а один и тот же маршрут с разными путевыми параметрами — иметь разные bucket'ы.

Так как соответствие «маршрут → bucket» не документируется как часть контракта API и может меняться, правильный способ группировать лимиты в клиентской библиотеке — по значению заголовка X-RateLimit-Bucket, а не по строке URL. Это единственный стабильный идентификатор:

GET /groups/{groupId}/channels → X-RateLimit-Bucket: abcd1234
GET /groups/{groupId}/members → X-RateLimit-Bucket: abcd1234 // тот же bucket