Skip to main content
4xx Client Error

429 Too Many Requests

The user has sent too many requests in a given amount of time (rate limiting).

Meaning & Description

The HTTP 429 Too Many Requests status code indicates that the user has sent too many requests in a given amount of time. It is the standard response for rate limiting and API quota enforcement. Servers use this code to protect against denial-of-service (DoS) attacks, brute-force attempts, and to ensure fair usage of resources among all clients. A 429 response should ideally include a `Retry-After` header indicating how long the client must wait before making a new request.

Common Causes

  • Aggressive polling or infinite loops in client application code.
  • Insufficient API rate limits for a legitimate high-traffic application.
  • Malicious behavior such as DDoS attacks or credential stuffing.

How to fix a 429 error

  1. Check the `Retry-After` response header to see how many seconds you need to wait before retrying.
  2. Inspect custom rate limit headers (e.g., `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`) to understand the quota rules.
  3. Implement exponential backoff and jitter in your application's retry logic.
  4. If you are a legitimate high-volume user, contact the API provider to request a limit increase or upgrade your pricing tier.

Browser & SEO Behaviour

Browser Behavior

Browsers treat 429 like any other client error and simply display the response body. If an automated script running in the browser triggers a 429, the JavaScript fetch/XHR promise resolves normally, but the status will be 429, which the developer must handle manually.

SEO Impact

If a search engine crawler hits a 429, it will slow down its crawl rate. Returning a `Retry-After` header helps crawlers know exactly when it is safe to return without penalizing the site's ranking.

CDN Behavior

CDNs and WAFs frequently issue 429 responses directly to clients to protect origin servers from DDoS attacks or scraping, terminating the request at the edge.

Code Examples

HTTP
GET /api/v1/users HTTP/1.1
Host: api.example.com
Authorization: Bearer my-token
Node.js (Express)
const rateLimit = require('express-rate-limit');

const apiLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100, // Limit each IP to 100 requests per window
  standardHeaders: true, // Return rate limit info in the RateLimit-* headers
  legacyHeaders: false, // Disable the X-RateLimit-* headers
  message: { error: "Too Many Requests, please try again later." }
});

app.use('/api/', apiLimiter);
Python (FastAPI)
from fastapi import Request, HTTPException
from slowapi import Limiter, _rate_limit_exceeded_handler
from slowapi.util import get_remote_address

limiter = Limiter(key_func=get_remote_address)
app.state.limiter = limiter
app.add_exception_handler(429, _rate_limit_exceeded_handler)

@app.get("/data")
@limiter.limit("5/minute")
def get_data(request: Request):
    return {"data": "This is protected by rate limiting"}
Go (net/http)
import "golang.org/x/time/rate"

var limiter = rate.NewLimiter(1, 3) // 1 request per second, burst of 3

func limitMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        if !limiter.Allow() {
            w.Header().Set("Retry-After", "2")
            http.Error(w, "Too Many Requests", 429)
            return
        }
        next.ServeHTTP(w, r)
    })
}
C# (ASP.NET Core)
// Program.cs setup required for Microsoft.AspNetCore.RateLimiting
builder.Services.AddRateLimiter(options => {
    options.AddFixedWindowLimiter("Fixed", opt => {
        opt.PermitLimit = 100;
        opt.Window = TimeSpan.FromMinutes(1);
        opt.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
        opt.QueueLimit = 0;
    });
    options.OnRejected = async (context, token) => {
        context.HttpContext.Response.StatusCode = 429;
        await context.HttpContext.Response.WriteAsync("Rate limit exceeded.", token);
    };
});
curl
curl -i https://api.twitter.com/2/tweets
# Response contains X-RateLimit-* headers

Raw HTTP Response Example

HTTP Response
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 60
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1672531260

{
  "error": "Rate limit exceeded. Please wait 60 seconds before retrying."
}

Real-world Examples

Twitter / X API: Strictly enforces rate limits (e.g., 900 requests/15 mins), returning 429 and providing custom X-RateLimit headers.
Cloudflare: Cloudflare WAF uses 429 responses when triggering custom rate-limiting rules to protect backends.
Discord API: Uses 429 extensively. If a bot ignores 429s and continues spamming, Discord may issue a temporary IP ban.

Frequently Asked Questions

What does HTTP Error 429 mean?

HTTP 429 Too Many Requests means you have exceeded the number of allowed requests for a given time period on a specific server or API.

How do I bypass a 429 error?

You cannot typically 'bypass' it. The correct approach is to wait the amount of time specified in the `Retry-After` header. Implementing an exponential backoff retry strategy in your code is highly recommended.

Is 429 a ban?

No, a 429 is a temporary pause (rate limit). However, if you aggressively ignore 429 responses, some services may escalate to a permanent ban (403 Forbidden).

What is the Retry-After header?

It's an HTTP header that tells the client how long to wait before making another request. It can be formatted as an integer representing seconds, or a specific HTTP date.

What is exponential backoff?

Exponential backoff is a standard error-handling strategy where an application waits longer between each subsequent retry attempt (e.g., 1s, 2s, 4s, 8s) to avoid overwhelming the server.

Did You Know?

Before 429 was standardized in 2012 (RFC 6585), Twitter famously returned a 420 Enhance Your Calm status code for rate limiting.

There is a standardized draft for generic RateLimit headers (`RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`), aiming to replace the varied `X-RateLimit-*` vendor-specific headers.

A 429 does not necessarily apply globally; it might apply to a specific IP, a specific API token, or a specific endpoint.

Developer Tips

  • Always return a `Retry-After` header with a 429 response. It makes client integration much easier and helps automated tools back off efficiently.
  • Include informational headers (like `X-RateLimit-Remaining`) even on successful 200 responses, so clients can throttle themselves proactively.
  • Use a distributed cache like Redis to track rate limits if you run multiple instances of your API backend.
  • Consider implementing distinct rate limits for authenticated vs. unauthenticated users.

Interview Questions

These are questions you might face in a backend or API design interview that touch on HTTP 429.

What status code is used for API rate limiting, and what header should ideally accompany it?

The 429 Too Many Requests status code is used for rate limiting. It should ideally be accompanied by the `Retry-After` header.

What is the difference between 429 Too Many Requests and 503 Service Unavailable?

429 is a client error indicating a specific client is making too many requests and being throttled. 503 is a server error indicating the server is overloaded globally and cannot handle requests from *anyone*.

How would you design a robust client application to handle 429 responses?

I would implement an interceptor or middleware that catches 429s, reads the `Retry-After` header, pauses execution for that duration, and then automatically retries the request. I'd also add exponential backoff with jitter as a fallback.

Common Interview Mistakes

  • Saying that 429 is a server crash or database failure.
  • Confusing rate limiting with DDoS protection at the network layer (layer 3/4). 429 is an application layer (layer 7) response.
  • Failing to mention the `Retry-After` header or the concept of exponential backoff.