429 Too Many Requests: what it means and how to fix it
Kofi Agyem, Founder and CEO, CloudzyroPublished · 5 min read
On this page
A 429 Too Many Requests means you've hit a rate limit. How to fix it as a visitor or API user, how to set limits well, and how Retry-After works.
1. The short answer
A 429 Too Many Requests error means you've sent more requests than the server allows in a set time, so it's refusing more for a while. It's a rate limit, not a ban. Wait, then try again; if the response includes a Retry-After header, it tells you how long.
429 is defined in RFC 6585, not the core HTTP spec. It's a 4xx code because the problem is the client's pace, not a server fault.
2. What you'll see
In a browser: "429 Too Many Requests", "Rate limit exceeded", or "You're doing that too often". From an API: an error with a 429 status, often with Retry-After: 30, and sometimes headers such as RateLimit-Remaining or X-RateLimit-Reset that say how much allowance is left.
3. Common causes
- A script or integration in a tight loop, calling an API with no pause.
- Retries without backoff: each failure triggers an instant retry, which makes it worse.
- A shared IP address. An office, school, VPN or carrier puts many people behind one address.
- Repeated sign-in attempts, which many sites limit hard to stop password guessing.
- A crawler or SEO tool fetching pages faster than the site allows.
- A limit set too low, so normal use trips it, such as a page that loads 40 images through a rate-limited endpoint.
- An attack, where the limit is doing its job.
4. How to fix a 429 as a visitor
- Stop refreshing. Each refresh can extend the wait.
- Wait a few minutes, then try once.
- Close other tabs on the same site and pause extensions that might be calling it.
- Switch off your VPN, or try mobile data, in case your shared address is the one being limited.
- If you're locked out of signing in, use the site's password reset rather than trying more passwords.
5. How to fix a 429 when calling an API
- Read `Retry-After`. It's either a number of seconds or a date. Wait at least that long.
- Back off exponentially, with jitter: 1 s, 2 s, 4 s, 8 s, each plus a random fraction, up to a cap.
- Cache responses that don't change often.
- Batch and spread work. Use bulk endpoints, and queue jobs instead of firing them all at once.
- Check the provider's published limits, and whether they count per key, per user or per IP address.
// Retry politely: honor Retry-After, else back off with jitter
async function fetchWithRetry(url, tries = 5) {
for (let i = 0; i < tries; i++) {
const res = await fetch(url);
if (res.status !== 429) return res;
const after = Number(res.headers.get("retry-after"));
const wait = after > 0 ? after * 1000 : 2 ** i * 1000 + Math.random() * 500;
await new Promise((r) => setTimeout(r, wait));
}
throw new Error("Still rate limited after retries");
}6. How to set rate limits on your own site
Rate limits protect sign-in forms, APIs and expensive pages. Set them so real people never notice.
nginx. limit_req answers 503 by default, not 429. Set limit_req_status 429; so clients know to slow down rather than assume you're down.
# nginx: 10 requests a second per IP, short bursts allowed
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
server {
location /api/ {
limit_req zone=api burst=20 nodelay;
limit_req_status 429;
proxy_pass http://127.0.0.1:3000;
}
}Behind a proxy or CDN, limit by the visitor's real IP address, not the proxy's, or everyone shares one limit. In nginx that's the realip module; in Express, the trust proxy setting.
Node and Express. Libraries such as express-rate-limit send 429 with rate-limit headers. Use a shared store such as Redis if you run more than one copy of the app, or each copy counts separately.
Apache and WordPress. Apache has no built-in per-visitor request limit, so hosts usually rely on ModSecurity or a firewall. WordPress security plugins limit sign-in attempts; check their logs if real customers get blocked.
Cloudflare. Rate limiting rules answer 429 by default, and Security, Events shows which rule matched.
7. On Cloudzyro
Every Sites & Apps site is behind Cloudflare, and traffic Cloudflare blocks as attacks doesn't count toward your plan. A site over its monthly traffic allowance is slowed, never taken offline, so visitors still get pages rather than errors. Any 429 your visitors see from your own code comes from your app's own settings.
8. How to check the status code
# Status and headers
curl -I https://api.example.com/v1/items
# Only the lines that matter
curl -sI https://api.example.com/v1/items | grep -i -E "^HTTP|retry-after|ratelimit"In browser developer tools, the Network tab shows the 429 and its response headers. Look for many requests to the same address in a short time: that's usually the culprit.
9. Related errors
- [503 Service Unavailable](/guides/503-service-unavailable): the whole server is unavailable, or it's nginx's limiter in its default setting.
- [403 Forbidden](/guides/403-forbidden-error): blocked outright, not just slowed.
- [401 Unauthorized](/guides/401-unauthorized): your API key is missing or invalid.