HTTP 429 Too Many Requests (rate limiting)
The server understood your request — it just will not do that many of them right now. Here is how to read 429, wait correctly, and stop hammering an API.
What 429 is saying
Status classes: 4xx = your request is the problem this time. With 429 the problem is volume or frequency, not usually the URL path or JSON shape. Proxies, CDNs, API gateways, WAFs and the app itself can all emit 429.
HTTP/1.1 429 Too Many Requests
Retry-After: 30
RateLimit-Limit: 60
RateLimit-Remaining: 0
RateLimit-Reset: 1699999999
Content-Type: application/json
{"error":"rate_limit_exceeded","message":"Try again in 30 seconds"}
Headers worth reading
- Retry-After — seconds as an integer, or an HTTP-date. Wait at least that long before retrying the same call.
- RateLimit-* / X-RateLimit-* — common vendor variants for limit, remaining and reset time (unix seconds or window length).
- No Retry-After — use exponential backoff with jitter (e.g. 1s, 2s, 4s… capped) and stop after a few attempts; do not tight-loop.
429 vs lookalikes
| Code | Means | Typical fix |
|---|---|---|
| 401 / 403 | Not authenticated / not allowed | Token, role, ownership — not “wait and spam again” |
| 429 | Too many requests in a window | Slow down, cache, batch, raise quota |
| 503 | Service unavailable / overloaded | Retry later; often infra, not your per-key quota |
| 502 | Bad gateway / origin reply | Upstream health, timeouts, proxy config |
Some older stacks misuse 403 for “you are rate limited”. If the body says rate limit and a Retry-After appears, treat it like 429.
Client checklist
- Honor
Retry-After; add random jitter so every client does not wake at once. - Cache GETs and dedupe identical in-flight requests (tabs, React Strict Mode double mounts, webhook storms).
- Batch or paginate instead of one HTTP call per row.
- Use the documented quota for your plan; a second API key is not a stealth unlimited pipe if the limit is per account.
- Distinguish user-driven clicks from background polls — poll slower when the tab is hidden.
Server / gateway checklist
- Return 429 (not 403) with a clear JSON/body reason and
Retry-After. - Limit on a stable key: authenticated user id preferred over raw IP (NATs share IPs).
- Separate burst vs sustained limits; document both.
- Log aggregate counts, not full request bodies with secrets.
- Load tests and scrapers should hit a staging host, not production quotas.
# See the status line without downloading a huge body
curl -sI https://example.com/api/things
# Look for HTTP/2 429 and Retry-After
Related
HTTP 503 Service Unavailable · HTTP 504 Gateway Timeout · HTTP 401 vs 403 · 502 Bad Gateway · 431 Request Header Fields Too Large · 413 Request Entity Too Large · TypeError: Failed to fetch · CSRF token missing · Anvil HTTP status · Wirebook: when sites get tired
Questions
What does HTTP 429 Too Many Requests mean?
The server or a proxy refused the request because you exceeded a rate limit for your IP, key, user or route. Slow down and honor Retry-After.
How do I fix a 429 error?
Wait for Retry-After (or use exponential backoff with jitter), reduce call volume, cache responses, and check your API plan’s quota. Raising the limit on the server only helps if you control it.
Is 429 the same as 403 Forbidden?
No. 403 is permission; 429 is volume. Some older APIs misuse 403 for rate limits — read the body and headers.
What is the Retry-After header?
Either a number of seconds to wait, or an HTTP-date when you may try again. Clients should not retry sooner.
Should I retry 429 automatically?
Yes, carefully: honor Retry-After, add jitter, cap attempts, and never retry non-idempotent POSTs without knowing it is safe.
Why do I get 429 only in production?
Shared NAT IPs, aggressive health checks, SSR that fetches per request, or a CDN WAF with a tighter default than localhost.
Published .