Продукт собирался несколько недель, демо завтра. Вы выкатываете сборку на стейджинг, запускаете нагрузочный тест, и через тридцать секунд логи забиты ответами HTTP 429: Claude API решил, что на эту минуту с вас хватит. Дальше разберём, как Anthropic устроил rate limits, какие рычаги остаются у вас и как построить систему, которая в такой момент деградирует плавно, а не падает.
Haiku у нас тоже есть: в каталоге claude-haiku-5.5 и claude-haiku-4.5, цены на странице моделей. Они работают в канале Premium, в канале Cheap Haiku их нет.
Как устроены rate limits Claude API
Anthropic ограничивает трафик на трёх уровнях, и учитывать нужно все три сразу:
- Requests per minute (RPM): число API-вызовов в скользящем окне в 60 секунд. Ограничивает конкурентность независимо от размера промптов.
- Tokens per minute (TPM): сколько входных + выходных токенов API обработает за 60-секундное окно. Один очень длинный промпт способен выбрать весь бюджет TPM за один вызов.
- Tokens per day (TPD): дневной потолок общей пропускной способности по токенам. Даже в пределах RPM и TPM при достаточно долгой нагрузке можно исчерпать и его.
У каждой модели свои лимиты. Щедрее всего они у Haiku: её дешевле всего обслуживать. Строже всего у Opus, потому что каждый запрос съедает много вычислительных ресурсов. Sonnet посередине. Это не баг: так Anthropic подсказывает, какую модель брать для высоконагруженных задач.
Лимиты действуют на API-ключ и на модель. Ключ с 4000 RPM к Sonnet и другой ключ с 4000 RPM к Haiku живут в независимых корзинах. А два сервиса на одном ключе и одной модели делят одну корзину.
Заголовки, которые стоит читать
В каждом ответе Claude API приходят заголовки с состоянием лимитов:
anthropic-ratelimit-requests-limit: 4000
anthropic-ratelimit-requests-remaining: 3842
anthropic-ratelimit-requests-reset: 2026-04-29T12:01:00Z
anthropic-ratelimit-tokens-limit: 400000
anthropic-ratelimit-tokens-remaining: 312000
anthropic-ratelimit-tokens-reset: 2026-04-29T12:01:00Z
При превышении лимита приходит HTTP 429 Too Many Requests с заголовком retry-after: он сообщает, сколько секунд ждать. В теле ответа лежит объект error с type: "rate_limit_error".
Ошибка HTTP 429: что она означает
Ответ 429 сообщает, что API вас услышал, но просит притормозить. Хуже всего немедленно повторить запрос на полной скорости: так вы останетесь прижатым к лимиту. Лучше уважать заголовок retry-after и применять экспоненциальный backoff.
Так выглядит ответ 429:
{
"type": "error",
"error": {
"type": "rate_limit_error",
"message": "Number of request tokens has exceeded your per-model limit..."
}
}
Типичные причины 429 в продакшене:
- Всплеск трафика: очередь разом разгребается после деплоя
- Большие промпты: одно окно контекста в 100K токенов выедает весь TPM
- Нет backoff: циклы повторов без пауз раскручивают шторм запросов
- Общие ключи: несколько сервисов на одном ключе без согласования
Тарифные уровни Anthropic
Anthropic делит доступ к API на уровни по истории использования и расходам. С каждым уровнем растут и rate limits. На начало 2026 года картина примерно такая:
| Уровень | Месячный расход | Sonnet RPM | Sonnet TPM | Opus RPM | Opus TPM |
|---|---|---|---|---|---|
| Free | $0 | 50 | 40 000 | 5 | 10 000 |
| Build (T1) | $5+ | 1 000 | 80 000 | 100 | 40 000 |
| Build (T2) | $40+ | 2 000 | 160 000 | 200 | 80 000 |
| Scale (T3) | $200+ | 4 000 | 400 000 | 400 | 200 000 |
| Scale (T4) | $1 000+ | 8 000 | 800 000 | 1 000 | 400 000 |
| Enterprise | Индивидуально | Индив. | Индив. | Индив. | Индив. |
На что обратить внимание:
- Переход с Free на Build даёт резкий скачок: 20× по RPM для Sonnet.
- Разрыв между T3 и T4 требует серьёзных расходов, зато удваивает всё.
- Enterprise получает индивидуальные лимиты по договорённости с отделом продаж Anthropic, нередко
>80 000RPM на Sonnet. - Лимиты Haiku обычно в 2-4 раза выше, чем у Sonnet, на каждом уровне.
Холодный старт нового ключа
Новые API-ключи стартуют с нижнего уровня. Если продукту нужны лимиты T3 с первого дня, подтвердите их у провайдера до запуска. codexkey не гарантирует более высокий уровень или дополнительную ёмкость.
Как справляться с rate limits
1. Экспоненциальный backoff с джиттером
Эталонная логика повторов. На каждый 429 ждём всё дольше по экспоненте и добавляем случайный джиттер, чтобы клиенты не бросились повторять одновременно («эффект громового стада»).
Версия на Python:
import anthropic
import time
import random
def call_with_backoff(
client: anthropic.Anthropic,
max_retries: int = 5,
base_delay: float = 1.0,
**kwargs,
) -> anthropic.types.Message:
for attempt in range(max_retries):
try:
return client.messages.create(**kwargs)
except anthropic.RateLimitError as e:
if attempt == max_retries - 1:
raise
# Уважаем заголовок retry-after, если он есть
retry_after = getattr(e, "response", None)
if retry_after and retry_after.headers.get("retry-after"):
delay = float(retry_after.headers["retry-after"])
else:
delay = base_delay * (2 ** attempt)
# Джиттер: 0–50% от задержки
jitter = delay * random.uniform(0, 0.5)
time.sleep(delay + jitter)
raise RuntimeError("Unreachable")
Версия на TypeScript:
import Anthropic from "@anthropic-ai/sdk";
async function callWithBackoff(
client: Anthropic,
params: Anthropic.MessageCreateParams,
maxRetries = 5,
baseDelay = 1000,
): Promise<Anthropic.Message> {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await client.messages.create(params);
} catch (err) {
if (
err instanceof Anthropic.RateLimitError &&
attempt < maxRetries - 1
) {
const retryAfter = err.headers?.["retry-after"];
const delay = retryAfter
? parseFloat(retryAfter) * 1000
: baseDelay * 2 ** attempt;
const jitter = delay * Math.random() * 0.5;
await new Promise((r) => setTimeout(r, delay + jitter));
continue;
}
throw err;
}
}
throw new Error("Unreachable");
}
2. Очередь запросов
Вместо того чтобы слать запросы с максимальной скоростью, кладите их в очередь и разбирайте с заданной скоростью. Особенно это важно при всплесках: пользователь загрузил 50 документов, и каждый нужно обработать.
import asyncio
from collections import deque
class RateLimitedQueue:
def __init__(self, rpm: int = 1000):
self.interval = 60.0 / rpm
self.queue: deque = deque()
self.semaphore = asyncio.Semaphore(rpm // 10) # потолок конкурентности
async def submit(self, coro):
await self.semaphore.acquire()
try:
result = await coro
await asyncio.sleep(self.interval)
return result
finally:
self.semaphore.release()
3. Пакетная обработка через Batch API
Если нагрузка выдерживает задержку до 24 часов, Batch API от Anthropic обрабатывает запросы вдвое дешевле и с отдельными rate limits. Подходит для классификации, извлечения данных, массового реферирования и ночных пайплайнов.
import anthropic
client = anthropic.Anthropic()
batch = client.messages.batches.create(
requests=[
{
"custom_id": f"doc-{i}",
"params": {
"model": "claude-sonnet-5",
"max_tokens": 1024,
"messages": [
{"role": "user", "content": f"Резюмируй: {doc}"}
],
},
}
for i, doc in enumerate(documents)
]
)
# Опрашиваем batch.id для получения результатов, до 24ч
Batch API остаётся одной из самых недоиспользуемых возможностей Claude API. Если хотя бы 30% трафика не критичны к задержке, перенос их в пакеты освобождает RPM и TPM реального времени для запросов, которым они действительно нужны.
Маршрутизация моделей: главный рычаг
Opus нужен не каждому запросу. Большинству не нужен даже Sonnet. Продуманный маршрутизатор моделей способен сократить расходы на 60-80% и заметно снизить давление на rate limits, распределяя нагрузку между моделями с разными пулами лимитов.
Принцип простой:
- gpt-5.6-luna: классификация, извлечение, простые вопросы-ответы, валидация, решения о маршруте. Быстрая и дешёвая модель для этого класса задач.
- Sonnet: реферирование, генерация кода, многошаговые рассуждения, создание контента. Рабочая лошадка.
- Opus: сложный анализ, работа с длинными документами, агентные циклы, задачи, где критична точность, а цена вторична.
Маршрутизатор уровня продакшена:
import anthropic
from enum import Enum
class Complexity(Enum):
LOW = "low"
MEDIUM = "medium"
HIGH = "high"
def estimate_complexity(prompt: str, token_count: int) -> Complexity:
"""Маршрутизация по эвристикам. Замените на классификатор для точности."""
# Короткие промпты с чёткими инструкциями → gpt-5.6-luna
if token_count < 2000 and not any(
kw in prompt.lower()
for kw in ["проанализируй", "сравни", "рассуждай пошагово", "architect"]
):
return Complexity.LOW
# Очень длинный контекст или явные требования к рассуждению → Opus
if token_count > 50_000 or "подумай внимательно" in prompt.lower():
return Complexity.HIGH
return Complexity.MEDIUM
MODEL_MAP = {
Complexity.LOW: "gpt-5.6-luna",
Complexity.MEDIUM: "claude-sonnet-5",
Complexity.HIGH: "claude-opus-4.8",
}
def routed_call(client: anthropic.Anthropic, prompt: str, **kwargs):
token_est = len(prompt) // 4 # грубая оценка
complexity = estimate_complexity(prompt, token_est)
model = MODEL_MAP[complexity]
return client.messages.create(
model=model,
messages=[{"role": "user", "content": prompt}],
**kwargs,
)
Версия на TypeScript:
import Anthropic from "@anthropic-ai/sdk";
type Complexity = "low" | "medium" | "high";
function estimateComplexity(prompt: string): Complexity {
const len = prompt.length / 4;
const lower = prompt.toLowerCase();
if (
len < 2000 &&
!["analyze", "compare", "reason step by step"].some((kw) =>
lower.includes(kw),
)
) {
return "low";
}
if (len > 50_000 || lower.includes("think carefully")) {
return "high";
}
return "medium";
}
const MODEL_MAP: Record<Complexity, string> = {
low: "gpt-5.6-luna",
medium: "claude-sonnet-5",
high: "claude-opus-4.8",
};
async function routedCall(
client: Anthropic,
prompt: string,
maxTokens = 4096,
): Promise<Anthropic.Message> {
const complexity = estimateComplexity(prompt);
return client.messages.create({
model: MODEL_MAP[complexity],
max_tokens: maxTokens,
messages: [{ role: "user", content: prompt }],
});
}
Главный вывод: маршрутизация экономит деньги и заодно перераспределяет давление rate limits. Если 60% трафика уходит на gpt-5.6-luna, ёмкость Sonnet остаётся для запросов, которым она действительно нужна.
Prompt caching: как снизить расход токенов
Prompt caching позволяет Anthropic не обрабатывать заново одни и те же входные токены в разных запросах. Если системный промпт, описания инструментов и few-shot примеры совпадают от вызова к вызову, их можно пометить как кэшируемые и при следующих запросах платить за эти токены в 10 раз меньше.
На rate limits влияние косвенное, но заметное: кэшированные токены входят в TPM с пониженным весом, поэтому в то же окно помещается больше запросов.
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
system=[
{
"type": "text",
"text": "Вы: агент поддержки клиентов компании Acme Corp...",
"cache_control": {"type": "ephemeral"},
}
],
messages=[{"role": "user", "content": user_query}],
)
# Проверяем эффективность кэша
print(f"Прочитано из кэша: {response.usage.cache_read_input_tokens}")
print(f"Создано в кэше: {response.usage.cache_creation_input_tokens}")
Возьмём системный промпт в 6 000 токенов, который вызывают 10 000 раз в месяц. Кэширование снижает эффективный расход входных токенов с 60M по $0.33/M ($19.80) до 60M по $0.05/M ($3). Для кэшируемой части это минус 90%.
Шлюз и явный выбор канала
Шлюз меняет эндпоинт и аккаунт, через которые ходит ваш клиент. Ключ codexkey выбирает канал Premium или Cheap, а при необходимости для Cheap можно разрешить резервный Premium по правилам провайдера. API ключей в личном кабинете не даёт настроек квот для ключа и не обещает увеличенного пула запросов. Очереди на стороне клиента, ограниченные повторы и измерение нагрузки по-прежнему нужны.
Вот что меняется в коде:
import anthropic
# До: напрямую к Anthropic
client = anthropic.Anthropic(api_key="sk-ant-...")
# После: через codexkey, тот же SDK, другой base URL
client = anthropic.Anthropic(
api_key="your-codexkey-key",
base_url="https://api.codexkey.ru/v1",
)
# Всё остальное идентично
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Привет"}],
)
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({
apiKey: "your-codexkey-key",
baseURL: "https://api.codexkey.ru/v1",
});
// Совместимый SDK, канал выбран при создании ключа
const response = await client.messages.create({
model: "claude-sonnet-5",
max_tokens: 1024,
messages: [{ role: "user", content: "Привет" }],
});
Перед использованием модели проверьте доступность канала и актуальные клиентские цены в каталоге codexkey. Совместимость шлюза не гарантирует более высоких лимитов или уровня Enterprise у провайдера.
Rate limits у разных провайдеров: сравнение
| Фактор | Anthropic T1 | Anthropic T3 | Anthropic Enterprise | codexkey | OpenAI (GPT-4o) | Together.ai |
|---|---|---|---|---|---|---|
| Sonnet/аналог RPM | 1 000 | 4 000 | Индив. | Не доступны в API ключей | 5 000 (GPT-4o) | 600 |
| Sonnet/аналог TPM | 80 000 | 400 000 | Индив. | Не доступны в API ключей | 800 000 | 100 000 |
| Opus/аналог RPM | 100 | 400 | Индив. | Не доступны в API ключей | 500 (o1) | Н/Д |
| Batch API | Да (скидка 50%) | Да (скидка 50%) | Да (скидка 50%) | Не подтверждено | Да (скидка 50%) | Нет |
| Кэширование промптов | Да (экономия 10×) | Да (экономия 10×) | Да (экономия 10×) | Да (проксирование) | Да (частично) | Нет |
| Мульти-ключ пулинг | Вручную | Вручную | Управляемый | Не гарантируется | Вручную | Вручную |
| Время до лимитов T3+ | Недели | Недели | Переговоры | Не гарантируется | Недели | Н/Д |
| Совместимость SDK | Нативная | Нативная | Нативная | Drop-in | Отдельный SDK | OpenAI-совместимый |
Мониторинг и алерты
Не ждите первых 429, чтобы понять, что лимит близко. Стройте мониторинг на заголовках rate limits:
import anthropic
import logging
logger = logging.getLogger("rate_limits")
def monitored_call(client: anthropic.Anthropic, **kwargs):
response = client.messages.create(**kwargs)
remaining_requests = response._response.headers.get(
"anthropic-ratelimit-requests-remaining"
)
remaining_tokens = response._response.headers.get(
"anthropic-ratelimit-tokens-remaining"
)
if remaining_requests and int(remaining_requests) < 100:
logger.warning(f"RPM на исходе: {remaining_requests} осталось")
if remaining_tokens and int(remaining_tokens) < 50_000:
logger.warning(f"TPM на исходе: {remaining_tokens} осталось")
return response
Настройте алерты на случай, когда остаток ёмкости падает ниже 20% от лимита. Тогда останется время на троттлинг, перемаршрутизацию или масштабирование, пока 429 ещё не начались.
Как собрать всё вместе: архитектура для продакшена
Надёжная система в продакшене сочетает всё перечисленное:
- Маршрутизатор моделей классифицирует входящие запросы и выбирает gpt-5.6-luna, Sonnet или Opus.
- Очередь запросов задаёт предельную скорость разбора для каждой модели.
- Prompt caching снижает расход токенов на повторяющихся системных промптах.
- Повторы с backoff спокойно переживают временные 429.
- Шлюз (codexkey) даёт канал, выбранный для ключа; перед нагрузкой проверьте правила провайдера и доступность модели.
- Мониторинг предупреждает, пока вы ещё не упёрлись в стену, а не после.
- Batch API уводит несрочную работу в отдельный пул лимитов со скидкой 50%.
Это не избыточная инженерия. Любой продакшен-деплой Claude заметного масштаба рано или поздно упирается в rate limits. Вопрос только в том, переживёт ли ваша система это незаметно или кого-то разбудят в 3 часа ночи.
FAQ
Что такое rate limit в Claude API?
Это ограничение на число запросов (RPM), токенов (TPM) или дневных токенов (TPD), которое ваш API-ключ может израсходовать за заданное окно. Превысите любое из них, и API отвечает HTTP 429 до сброса окна.
Как проверить свой тарифный уровень?
Откройте консоль Anthropic и перейдите в настройки API-ключа: уровень показан рядом со статистикой использования. Текущие лимиты и остаток ёмкости видны и в заголовках anthropic-ratelimit-* любого ответа API.
Можно ли попросить Anthropic поднять rate limits?
Да. На уровнях Build и Scale лимиты растут автоматически вместе с месячными расходами. Индивидуальные лимиты выше T4 обсуждаются с отделом продаж Anthropic по Enterprise-соглашению, и обычно оно требует минимального годового обязательства.
Чем RPM отличается от TPM?
RPM (requests per minute) ограничивает число API-вызовов независимо от их размера. TPM (tokens per minute) ограничивает общую пропускную способность по токенам. В TPM можно упереться одним очень длинным промптом, даже когда с RPM всё в порядке. Выдерживать надо оба потолка одновременно.
Есть ли у Batch API отдельные rate limits?
Да. Пакетные запросы идут асинхронно, у них свой пул лимитов, а стоят они на 50% дешевле. Подходит любой нагрузке, которая переносит задержку до 24 часов: пайплайны классификации, ночные отчёты, массовое извлечение данных.
Как prompt caching помогает с rate limits?
Кэшированные токены обрабатываются быстрее и входят в TPM с пониженным весом. Если системный промпт в 6 000 токенов попал в кэш, API обрабатывает только динамическую часть каждого запроса, и пропускная способность в том же окне TPM фактически растёт.
Нарушает ли шлюз вроде codexkey условия Anthropic?
Смотрите условия, которые относятся к вашему аккаунту и договору с провайдером. Настройки ключа codexkey не подтверждают дополнительных квот или пропускной способности, и совместимость шлюза этого не гарантирует.
Как быстрее всего избавиться от ошибок 429?
Сначала прочитайте ошибку и указания провайдера о повторе, если они есть. Для временных сбоев поставьте ограниченную очередь на клиенте и экспоненциальный backoff с джиттером. Смена шлюза более высоких лимитов не гарантирует.
Rate limits есть у любого управляемого API, и Claude не исключение. Но задача решаемая. Лучше всех с ней справляются команды, которые закладывают лимиты в план до релиза, а не разбирают их после первого инцидента. codexkey даёт совместимые эндпоинты и выбор канала. Проверяйте актуальные клиентские цены и правила провайдера: дополнительные квоты и объединённая ёмкость не гарантируются.