HTTP 429 Too Many Requests

Too Many Requests

HTTP 429 is Too Many Requests: the client has sent too many requests in a given amount of time. It isn’t in RFC 9110; RFC 6585 section 4 defines it. The response should explain the condition and may carry Retry-After saying how long to wait. RFC 6585 deliberately leaves open how the server identifies the client and how it counts.

The exchange

HTTP/1.1 429 Too Many Requests
Retry-After: 30
Content-Type: application/problem+json

{"title": "Rate limit exceeded", "status": 429, "detail": "100 requests per minute; try again in 30 seconds"}

Retry-After is either a number of seconds or an HTTP date such as Fri, 16 Oct 2026 00:00:00 GMT (RFC 9110 section 10.2.3). Many APIs also report their counters in headers like X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset. Those are conventions, not a standard, so check each API’s documentation for what the reset value counts.

What the client should do

Wait. Honor Retry-After when it’s there; otherwise back off exponentially with random jitter, so a fleet of clients doesn’t retry in lockstep, and cap the number of attempts. A tight retry loop only keeps you over the limit. Not every API uses 429 for this: GitHub’s REST API answers a spent rate limit with 403 or 429 and x-ratelimit-remaining: 0.

Caching

RFC 6585 says a response with 429 must not be stored by a cache, so a CDN shouldn’t hand one client’s 429 to another.

Search engines

Google treats 429 as a server error, not as a 4xx: Googlebot slows down, and pages already indexed stay unless the errors go on. That makes 429 or 503 the way to ask a crawler to ease off, where 401 or 403 would get pages dropped.

Who sends it, and who sends something else

  • AWS API Gateway throttling answers 429.
  • An AWS WAF rate-based rule blocks with 403 unless you configure a custom response.
  • nginx’s limit_req and limit_conn reject with 503 unless you set limit_req_status and limit_conn_status.
  • Kubernetes ingress-nginx’s nginx.ingress.kubernetes.io/limit-rps annotation also rejects with 503, unless the controller’s ConfigMap sets limit-req-status-code: "429".

A rate limit is the client’s doing and 429 says so; a 503 tells the client the server is in trouble.

In your stack

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;
    }
}
import { rateLimit } from 'express-rate-limit';
app.use('/api', rateLimit({ windowMs: 60_000, limit: 100 }));    // Express: 429 past 100 a minute
raise HTTPException(status_code=429, detail="Rate limit exceeded",
                    headers={"Retry-After": "30"})                # FastAPI
w.Header().Set("Retry-After", "30")
http.Error(w, "rate limit exceeded", http.StatusTooManyRequests)

Search 429 503 in the tool below to compare the two.

Try it in the HTTP Status Codes

429 Too Many Requests

  1. 429Too Many Requests4xx Client error

    The client has sent too many requests in a given time. Retry-After says how long to wait, and the limit is usually described in RateLimit headers or in the body.

    When to use it

    Rate limits and quotas on public endpoints, including the ones you impose to keep one client from taking the lot.

    Common mistakes

    Returning it without Retry-After, and counting timeouts or errors of your own as if the client had asked too often.

    Not cacheable by defaultRFC 6585

Every code, by class

Codes marked unofficial come from one server’s own convention — nginx, Cloudflare, cPanel, Microsoft — and are not in the IANA registry.

Runs in your browser. Nothing you enter is sent anywhere.