Вирішення проблемПосібник
429 Too Many Requests від AI API: повтори з відступом
Що означає 429 від AI API і як його обробити: експоненційний відступ із джиттером, Retry-After і паралельність агента, з кодом на Python і JavaScript.

На цій сторінці
429 Too Many Requests від AI API означає, що запит відхилено, бо ви надіслали забагато занадто швидко або досягли ліміту на своєму акаунті. Рішення — зачекати й повторити з експоненційним відступом і джиттером, використовувати заголовок Retry-After, коли він є у відповіді, та обмежити кількість запитів, які ваш агент надсилає паралельно. Не повторюйте 429, який насправді є лімітом витрат або балансу: очікування це не виправить.
Цей посібник базується на офіційних посібниках з обмежень швидкості OpenAI та Anthropic, обидва перевірено 22 жовтня 2026 року. Жодна сторінка не показує дату останнього оновлення.
Що означає 429#
OpenAI описує 429 як запит, відхилений через перевищення обмеження швидкості (rate_limit_error, з кодом slow_down, коли трафік зростає занадто швидко), або через досягнення жорсткого ліміту витрат. Anthropic також використовує rate_limit_error для 429. 429 через ліміт витрат не має заголовка retry-after і продовжує збоїти, доки доступ не відновиться.
Двох сусідів легко з ним сплутати. 503 server_ від OpenAI та 529 overloaded_ від Anthropic — це умови перевантаження, а не ваше обмеження швидкості. Зазвичай їх обробляють тим самим циклом повторів, але вони говорять про іншу причину.
Отже, є три випадки, і кожен потребує різної реакції:
Прокрутіть таблицю праворуч →
| Відповідь | Причина | Що робити |
|---|---|---|
| 429 обмеження швидкості | Забагато запитів або токенів за хвилину | Зачекати, повторити з відступом |
| 429 ліміт витрат або балансу | Досягнуто ліміту акаунта | Не повторювати; виправити ліміт або поповнити баланс |
| 503 / 529 перевантажено | Сторона провайдера зайнята | Повторити з відступом, з обмеженням |
Якщо ваш баланс вичерпано, натомість прочитайте помилку "not enough tokens". Для збоїв на рівні мережі, як-от тайм-аути та відмови в з'єднанні, дивіться поширені помилки з'єднання.
Прочитайте заголовки, перш ніж вгадувати затримку#
OpenAI документує ці заголовки у відповідях з обмеженням швидкості: Retry-After, а також x-, x-, x- з варіантами -tokens. Інші API можуть надсилати підмножину з них або жодного, тому напишіть клієнт так, щоб використовувати Retry-After, коли він присутній, і повертатися до власного графіка, коли його немає.
Поради OpenAI щодо повторів, коротко:
- Вважайте
Retry-Afterмінімальним очікуванням і додайте зверху невелику випадкову затримку. - Без нього використовуйте експоненційний відступ із джиттером.
- Обмежте як кількість спроб, так і загальний час повторів.
- Не накладайте власні повтори поверх повторів SDK.
- Не повторюйте помилки квоти або білінгу.
- Невдалі запити все одно зараховуються до ліміту за хвилину, тож агресивний цикл робить гірше.
- Для стрімінгу не відтворюйте запит після того, як ви вже спожили з нього вивід.
Python: відступ із джиттером#
Офіційний пакет openai працює з будь-якою сумісною з OpenAI кінцевою точкою. Вимкніть власні повтори SDK (max_retries=0), щоб вони не множилися з вашими. Ідентифікатор моделі береться з документації CheapTokens; ідентифікатори різняться між провайдерами.
import os
import random
import time
from openai import OpenAI, APIStatusError
client = OpenAI(
base_url="https://api.cheaptokens.dev/v1",
api_key=os.environ["CHEAPTOKENS_API_KEY"],
max_retries=0, # we retry ourselves
)
RETRYABLE = {429, 500, 502, 503, 504}
def chat_with_retry(model, messages, max_attempts=5, max_total=60.0):
started = time.monotonic()
for attempt in range(max_attempts):
try:
return client.chat.completions.create(model=model, messages=messages)
except APIStatusError as err:
last = attempt == max_attempts - 1
if err.status_code not in RETRYABLE or last:
raise
header = err.response.headers.get("retry-after")
if header and header.replace(".", "", 1).isdigit():
delay = float(header) + random.uniform(0, 1) # minimum wait + jitter
else:
delay = random.uniform(0, min(30.0, 2.0 ** attempt)) # full jitter
if time.monotonic() - started + delay > max_total:
raise
time.sleep(delay)Верхня межа затримки без заголовка зростає 1, 2, 4, 8 секунд (з обмеженням у 30), а random.uniform вибирає випадкове значення нижче неї, тож багато воркерів не прокидаються всі в один момент. Retry-After також може бути HTTP-датою; наведений вище код обробляє числову форму, а інакше повертається до відступу.
JavaScript: той самий цикл#
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.cheaptokens.dev/v1",
apiKey: process.env.CHEAPTOKENS_API_KEY,
maxRetries: 0, // we retry ourselves
});
const RETRYABLE = new Set([429, 500, 502, 503, 504]);
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
export async function chatWithRetry(model, messages, maxAttempts = 5, maxTotalMs = 60000) {
const started = Date.now();
for (let attempt = 0; attempt < maxAttempts; attempt++) {
try {
return await client.chat.completions.create({ model, messages });
} catch (err) {
const last = attempt === maxAttempts - 1;
if (!RETRYABLE.has(err.status) || last) throw err;
const header = Number(err.headers?.get?.("retry-after"));
const delayMs = Number.isFinite(header) && header > 0
? header * 1000 + Math.random() * 1000 // minimum wait + jitter
: Math.random() * Math.min(30000, 2 ** attempt * 1000); // full jitter
if (Date.now() - started + delayMs > maxTotalMs) throw err;
await sleep(delayMs);
}
}
}Коли це спрацьовує, виклик з обмеженням швидкості просто триває довше, а потім повертає звичайне завершення. Коли він усе ще збоїть після останньої спроби, викидається початкова помилка, тож ваш код може її залогувати або поставити завдання в чергу на потім.
Як агентам обробляти 429#
Цикл агента надсилає багато коротких викликів, і кілька агентів або викликів інструментів можуть виконуватися одночасно. Повторів самих по собі недостатньо; знижуйте частоту запитів у джерелі:
- Обмежте паралельність. Семафор на 3–5 паралельних викликів — розумний початок; підвищуйте його, лише поки помилки залишаються рідкісними.
- Спільний обмежувач. Якщо кілька воркерів використовують той самий ключ, вони поділяють ті самі ліміти, тож одного циклу повторів на воркер недостатньо: використовуйте одну чергу або один семафор для процесу.
- Відступайте глобально. Коли один виклик отримує 429 із затримкою, призупиніть увесь пул на цей час, а не лише виклик, що збоїть.
- Робіть запити меншими. Менше токенів на запит означає менший тиск на ліміти токенів за хвилину: скоротіть історію та вивід інструментів. Дивіться як оцінити вартість AI-агента, щоб зрозуміти, куди йдуть токени.
- Зупиняйтеся на помилках, що не підлягають повтору. 401, 400 або помилка балансу самі не виправляться; швидко завершуйте з помилкою та повідомляйте.
import asyncio
limit = asyncio.Semaphore(4) # at most 4 requests in flight
async def run(job):
async with limit:
return await call_model(job) # your async call with the retry loop aboveЗапускайте цикли агентів на CheapTokens#
Для циклів агентів із багатьма короткими викликами CheapTokens пропонує MiniMax-M2.7: одна ціна в будь-який час доби, контекст 180K, до 8 192 токенів на відповідь і один баланс для всіх моделей. Вивід коштує $0.15 за 1M токенів, а загалом, з урахуванням вхідних і вихідних разом, це дешевше за OpenRouter. Він працює через сумісну з OpenAI кінцеву точку https:/. Наведений вище код уже вказує на цю кінцеву точку; задайте ідентифікатор моделі з документації CheapTokens і запускайте.
Актуальні ціни для навантаження 500 000 вхідних і 100 000 вихідних:
| Модель | Вхід $/1М | Вихід $/1М | Вартість | OpenRouter |
|---|---|---|---|---|
| GLM-5.3-Flash | $0.02 | $0.04 | $0.014 | $0.0282 |
| DeepSeek-V4-Flash | $0.015 | $0.10 | $0.0175 | $0.0394 |
| MiniMax-M2.7 | $0.05 | $0.15 | $0.04 | $0.27 |
500 000 вхідних і 100 000 вихідних токенів загалом. Ціни за 1 млн токенів актуальні та змінюються разом із нашими тарифами; стовпець OpenRouter показує довідкові ціни для того самого навантаження.
Дивіться усі ціни, документацію з налаштування і створіть ключ, щоб надіслати свій перший запит.
Якщо все ще не працює#
- 429 на найпершому запиті. Прочитайте тип і повідомлення помилки в тілі відповіді: 429 через ліміт витрат або акаунта продовжує збоїти при повторі, доки ліміт не підвищать або доступ не відновиться, тоді як 429 через обмеження швидкості зникає після паузи.
- 429 продовжує надходити з довгим циклом. Можливо, ви накладаєте повтори: повтори SDK помножені на ваші повтори. Встановіть повтори SDK на нуль, як у прикладах.
- Помилки надходять хвилями на початку пакета. Нарощуйте поступово, а не запускайте всіх воркерів одразу; OpenAI повідомляє
slow_downдля трафіку, що зростає занадто швидко. - Стрім-виклик збійв посередині. Не відтворюйте його наосліп після того, як ви спожили вивід; вирішіть, чи перезапустити всю відповідь, чи продовжити з того, що маєте.
- Немає Retry-After у відповіді. Код повертається до відступу з джиттером, тож жодних змін не потрібно.



