error http

HTTP 429 Too Many Requests

Understanding HTTP 429 Too Many Requests - the user has sent too many requests in a given time period (rate limiting).

What It Means

HTTP 429 Too Many Requests indicates that the user has sent too many requests in a given amount of time (“rate limiting”). The response should include a Retry-After header indicating how long to wait before making a new request.

Common Causes

  • Exceeding API rate limits (e.g., GitHub, Twitter, Stripe APIs)
  • Too many login attempts (brute-force protection)
  • Aggressive polling or scraping without respecting rate limits
  • Missing rate limit handling in client code
  • Multiple services or users sharing the same API key
  • Bot traffic triggering DDoS protection

How to Fix

Client-side: Respect rate limits

async function fetchWithRateLimit(url, options = {}) {
  const response = await fetch(url, options);

  if (response.status === 429) {
    const retryAfter = response.headers.get('Retry-After');
    const waitTime = retryAfter ? parseInt(retryAfter) * 1000 : 60000;

    console.log(`Rate limited. Retrying after ${waitTime}ms`);
    await new Promise(resolve => setTimeout(resolve, waitTime));
    return fetchWithRateLimit(url, options);
  }

  return response;
}

Exponential backoff

async function fetchWithBackoff(url, options = {}, maxRetries = 5) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const response = await fetch(url, options);

    if (response.status !== 429) return response;

    const retryAfter = response.headers.get('Retry-After');
    const delay = retryAfter
      ? parseInt(retryAfter) * 1000
      : Math.min(1000 * Math.pow(2, attempt), 30000);

    await new Promise(resolve => setTimeout(resolve, delay));
  }
  throw new Error('Max retries exceeded');
}

Server-side: Implement rate limiting (Express.js)

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 headers
  legacyHeaders: false,
  message: {
    error: 'Too Many Requests',
    message: 'You have exceeded the rate limit. Please try again later.'
  }
});

app.use('/api/', apiLimiter);

Python requests with retry

import requests
import time

def fetch_with_retry(url, max_retries=5):
    for attempt in range(max_retries):
        response = requests.get(url)
        if response.status_code != 429:
            return response

        retry_after = int(response.headers.get('Retry-After', 60))
        print(f"Rate limited. Waiting {retry_after}s...")
        time.sleep(retry_after)

    raise Exception("Max retries exceeded")

Nginx rate limiting

# Define rate limit zone
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;
    }
}
  • HTTP 503 - Service Unavailable: The server is overloaded, not just rate-limiting you.
  • HTTP 408 - Request Timeout: The request itself took too long.
  • HTTP 403 - Forbidden: Sometimes used instead of 429 for rate limiting.