HTTP · HTTP 429 · Too Many Requests

429 Too Many Requests in AI APIs

HTTP 429 Too Many Requests means you sent too many requests or tokens in a short period and the server is throttling you. Wait for the number of seconds in the Retry-After header, or retry with a growing delay. If the 429 is caused by exhausted credit or quota, retries will not help — top up the balance.

Updated: · based on the official documentation of IETF, OpenAI, Anthropic, Google

Two different cases behind one code

A temporary rate limit: requests or tokens per minute were exceeded. It clears after a pause. Providers count limits per organization or project, so a new key in the same project usually does not help.

Exhausted quota or balance: OpenAI returns insufficient_quota or credit_balance_exhausted; Anthropic returns a monthly spend-limit 429 without retry-after. It will keep failing until you add credit or raise the limit.

How to tell them apart

Read the error type and code in the body, not only the status. Retry-After (RFC 9110) is either seconds or an HTTP date, so parse both. Anthropic sends anthropic-ratelimit-* headers and OpenAI sends x-ratelimit-remaining-requests and x-ratelimit-reset-tokens, which show which limit ran out.

What to do in code

Retry only transient errors: 429 with Retry-After, 500, 503, 529. Cap attempts, add jitter and do not nest SDK retries inside your own, or load snowballs. Failed requests also count toward per-minute limits.

Lower the rate: a queue with a concurrency cap, batching and a sensible max_tokens. When traffic jumps, ramp it up gradually — Anthropic and OpenAI apply separate acceleration limits.

If the 429 comes from API429

API429 is an API too and can return 429 when a model gets more requests than it can take. Handle it the same way: honour Retry-After and retry with a delay. With the same key you can send the request to another model straight away — change only the model field. One balance covers every model.

Retrying with Retry-After: Python example

import email.utils, os, random, time, requests

URL = "https://gateway.api429.com/v1/chat/completions"
HEADERS = {"Authorization": "Bearer " + os.environ["API429_API_KEY"]}
TRANSIENT = {429, 500, 503, 529}

def retry_after(value):
    if not value:
        return None
    if value.isdigit():
        return int(value)
    return max(0, email.utils.parsedate_to_datetime(value).timestamp() - time.time())

def chat(payload, attempts=5):
    for attempt in range(attempts):
        r = requests.post(URL, headers=HEADERS, json=payload, timeout=120)
        if r.status_code not in TRANSIENT:
            r.raise_for_status()
            return r.json()
        wait = retry_after(r.headers.get("Retry-After"))
        time.sleep(wait if wait is not None else min(60, 2 ** attempt) + random.random())
    r.raise_for_status()

Frequently asked questions

What does a 429 error mean in an API?

The server limits request frequency: you sent more requests or tokens per unit of time than allowed. Wait for Retry-After or retry with a growing delay.

Why does the 429 persist after waiting?

It is probably exhausted quota or balance rather than a rate limit: insufficient_quota at OpenAI, a monthly spend limit at Anthropic, 402 Insufficient Balance at DeepSeek. Top up the account.

Will a new API key help?

Usually not: Gemini, OpenAI and Anthropic count limits per project or organization, not per key.

How should I retry?

Only transient errors, with a capped number of attempts, exponential delay and jitter. If Retry-After is present, wait at least that long.

Sources

Next steps

Other API errors

Telegram