OpenAI 429 Rate Limit Exceeded: Causes, Fixes & Prevention
OpenAI returns HTTP 429 when you exceed your RPM, TPM, or RPD limits — or hit your monthly billing hard cap. This guide explains how to tell the two apart, read x-ratelimit headers proactively, implement exponential backoff in Python and TypeScript, and upgrade your usage tier.
Quick diagnosis: which 429 do you have?
- “Rate limit reached for requests” — RPM limit hit. Fix: exponential backoff retry.
- “Rate limit reached for tokens” — TPM limit hit. Fix: reduce prompt size or batch smaller.
- “You exceeded your current quota” — billing hard cap reached. Fix: raise spend limit at platform.openai.com/settings/billing.
Rate limits by tier
OpenAI uses a five-tier system. Limits increase automatically as you spend more. The table below shows gpt-4o limits — gpt-4o-mini has higher TPM ceilings at each tier.
| Tier | Requirement | RPM | RPD | TPM |
|---|---|---|---|---|
| Free | Verified phone number | 3 | 200 | 40,000 |
| Tier 1 | $5 payment | 500 | 10,000 | 200,000 |
| Tier 2 | $50 spend + 7 days | 5,000 | — | 2,000,000 |
| Tier 3 | $100 spend + 7 days | 5,000 | — | 4,000,000 |
| Tier 4 | $250 spend + 14 days | 10,000 | — | 10,000,000 |
Source: platform.openai.com/docs/guides/rate-limits. Limits vary by model — verify yours at platform.openai.com/settings/organization/limits.
Step 1 — Read x-ratelimit headers
Every response from the OpenAI API includes six rate-limit headers. Read them before hitting the wall so you can slow down proactively:
x-ratelimit-limit-requests: 500
x-ratelimit-limit-tokens: 200000
x-ratelimit-remaining-requests: 12
x-ratelimit-remaining-tokens: 180423
x-ratelimit-reset-requests: 2026-07-17T12:00:05.123Z
x-ratelimit-reset-tokens: 2026-07-17T12:00:00.882Z Access them from the raw HTTP response in Python and TypeScript:
# Python — read headers from the raw httpx response
from openai import OpenAI
import os
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
response = client.chat.completions.with_raw_response.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Hello"}],
)
remaining = int(response.headers.get("x-ratelimit-remaining-requests", 999))
reset_at = response.headers.get("x-ratelimit-reset-requests", "")
print(f"Requests remaining this minute: {remaining}")
print(f"Resets at: {reset_at}")
completion = response.parse()
print(completion.choices[0].message.content) // TypeScript — read headers via the APIResponse wrapper
import OpenAI from "openai";
const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const response = await client.chat.completions
.withResponse()
.create({
model: "gpt-4o",
messages: [{ role: "user", content: "Hello" }],
});
const remaining = response.response.headers.get("x-ratelimit-remaining-requests");
const resetAt = response.response.headers.get("x-ratelimit-reset-requests");
console.log(`Remaining: ${remaining}, resets at: ${resetAt}`);
console.log(response.data.choices[0].message.content); Step 2 — Implement exponential backoff
When you receive a 429, wait before retrying. Each retry doubles the wait with added random jitter to prevent thundering herd. OpenAI's Python SDK does not auto-retry 429s by default — you must add this yourself:
Python — manual backoff
import time, random, os
from openai import OpenAI, RateLimitError
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
def chat_with_backoff(messages, model="gpt-4o", max_retries=5):
for attempt in range(max_retries):
try:
return client.chat.completions.create(
model=model,
messages=messages,
)
except RateLimitError as e:
if attempt == max_retries - 1:
raise
wait = (2 ** attempt) + random.random()
print(f"429 rate limited. Retry {attempt + 1}/{max_retries} in {wait:.1f}s...")
time.sleep(wait)
result = chat_with_backoff([{"role": "user", "content": "Hello"}])
print(result.choices[0].message.content) Python — production grade with tenacity
# pip install tenacity
import os
from openai import OpenAI, RateLimitError
from tenacity import (
retry,
stop_after_attempt,
wait_random_exponential,
retry_if_exception_type,
)
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
@retry(
retry=retry_if_exception_type(RateLimitError),
wait=wait_random_exponential(min=1, max=60),
stop=stop_after_attempt(6),
)
def chat(messages, model="gpt-4o"):
return client.chat.completions.create(model=model, messages=messages)
result = chat([{"role": "user", "content": "Summarize this document..."}])
print(result.choices[0].message.content) TypeScript / Node.js — backoff with p-retry
// npm install p-retry openai
import OpenAI from "openai";
import pRetry, { AbortError } from "p-retry";
const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
async function chat(messages: OpenAI.ChatCompletionMessageParam[]) {
return pRetry(
async () => {
const res = await client.chat.completions.create({
model: "gpt-4o",
messages,
});
return res;
},
{
retries: 5,
minTimeout: 1000,
maxTimeout: 60000,
factor: 2,
onFailedAttempt: (error) => {
// only retry on 429; abort on 401/400
if (error.status !== 429) throw new AbortError(error.message);
console.log(`429 rate limit — attempt ${error.attemptNumber}, retrying...`);
},
}
);
}
const result = await chat([{ role: "user", content: "Hello" }]);
console.log(result.choices[0].message.content); Step 3 — Reduce token consumption
Switch high-volume calls to gpt-4o-mini
gpt-4o-mini has 5× higher TPM limits than gpt-4o at every tier and costs <10× less per token. Use it for classification, summarization, extraction, and other tasks that don't need frontier reasoning:
# Use gpt-4o-mini for high-volume tasks
response = client.chat.completions.create(
model="gpt-4o-mini", # was "gpt-4o"
messages=[{"role": "user", "content": prompt}],
max_tokens=256, # cap output tokens
) Use the Batch API for non-real-time workloads
The Batch API runs jobs asynchronously with a 24-hour window and has separate, higher rate limits that do not share quota with your synchronous requests. It also costs 50% less per token. Ideal for: nightly data processing, bulk embeddings, evaluation pipelines, large-scale classification.
Cache repeated prompts
If the same prompt is sent multiple times (e.g. a system prompt + identical user question), cache the response in Redis or an in-memory store. OpenAI also offers prompt caching for long system prompts — repeated prefixes are stored server-side and billed at 50% of input token cost.
Step 4 — Upgrade your rate limit tier
Tier upgrades happen automatically when you cross spend thresholds. To accelerate:
- Add a payment method and make a minimum $5 payment at platform.openai.com/settings/billing to exit the free tier and reach Tier 1 (500 RPM).
- Check your current tier at platform.openai.com/settings/organization/limits — it shows your tier, current limits, and next tier requirements.
- Raise your monthly billing cap — even if you have room under your RPM limit, a low spend cap will trigger “You exceeded your current quota” 429s. Go to Settings → Billing → Usage limits.
- Request manual quota increase for Tier 5 or above-Tier-4 needs: click “Request limit increase” on the limits page and describe your production use case. Reviews take 2–3 business days.
Get an email the next time OpenAI goes down
Outage alerts for OpenAI, straight to your inbox. No account needed, unsubscribe in every email.
Watching more than one service? A free account covers 5 services + a daily digest — and Pro is currently free.
Frequently asked questions
What does OpenAI error 429 rate limit exceeded mean?
A 429 response means your application sent more requests or tokens than your current usage tier allows in a given time window, or you hit your monthly billing hard cap. The response body contains a type: "requests" or type: "tokens" field to disambiguate RPM/TPM limits from quota exhaustion.
What's the difference between RPM, TPM, and RPD rate limits?
RPM (requests per minute) caps how many API calls you can fire per minute. TPM (tokens per minute) caps total input+output tokens per minute. RPD (requests per day) is a daily ceiling applied on the free tier and Tier 1. All three are independent — a single large request can hit TPM before RPM.
How do I read the x-ratelimit-remaining-requests header?
In Python, use client.chat.completions.with_raw_response.create(...) and access response.headers["x-ratelimit-remaining-requests"]. In TypeScript, use .withResponse().create(...) and read response.response.headers.get("x-ratelimit-remaining-requests"). When this approaches 0, add a short delay before your next call.
How do I upgrade my OpenAI API rate limit or request higher quota?
Tiers 1–4 unlock automatically as you spend more. Make a $5 payment to exit the free tier immediately. For Tier 5 or custom limits, submit a quota increase request at platform.openai.com/settings/organization/limits — click “Request limit increase” and describe your use case. Processing takes 2–3 business days.
OpenAI quota vs rate limit — what's the difference?
A rate limit is a per-minute or per-day request/token ceiling that resets automatically. A quota (billing hard limit) is a cumulative monthly spend cap that you set manually. Both return 429, but quota errors say “You exceeded your current quota” and do not resolve with retry — you must raise the spend limit in your billing settings.