Error reference HTTP status

How to fix and avoid 429 Too Many Requests

A 429 Too Many Requests response means the server counted your requests against a quota — per IP, per account, or per endpoint — and you exceeded it. It is throttling, not blocking: the server is telling you to slow down, and often exactly how long to wait. The durable fix combines client-side pacing with distributing traffic across more IPs.

429 Too Many Requests

What 429 Too Many Requests means

HTTP 429 is the standard rate-limiting response. Servers track request volume against a quota — commonly requests per minute per IP address, but also per API key, per account, per session cookie, or per endpoint — and answer 429 once you cross it. Many include a Retry-After header stating how many seconds to wait, or X-RateLimit-* headers showing your quota and reset time.

The most important diagnostic question is what the limit is keyed on. If it is keyed on your IP, spreading requests across more IPs solves it directly. If it is keyed on an API key, account, or session, no amount of IP rotation helps — ten IPs sharing one token still count as one client. Read the response body and headers; APIs usually say which.

Also distinguish 429 from soft blocking. A real 429 is a well-behaved throttle that resets on schedule. If you see CAPTCHAs, 403s, or empty 200s alongside it, the site has escalated past rate limiting into bot detection, which needs a different response — better request hygiene, not just slower requests.

429 Too Many Requests

How to fix a 429 error, step by step

Fix the immediate throttle first (steps 1-3), then re-architect so you stop hitting it (steps 4-8).

  1. Honor Retry-After. If the header is present, wait exactly that long before retrying — hammering through the penalty window often lengthens it. Treat the header as authoritative over your own backoff schedule.
  2. Add exponential backoff with jitter for 429s without Retry-After: wait 1s, 2s, 4s, 8s with a random offset, so parallel workers do not retry in lockstep and re-trigger the limit together.
  3. Cut concurrency per target. Total throughput matters less than per-host pressure — cap simultaneous connections to any single host and add a small delay between requests to the same domain.
  4. Identify the rate-limit key. Send one request from a fresh IP: if it succeeds instantly, the limit is per-IP and rotation is your lever; if it still 429s, the key rides your API token, account, or cookies.
  5. Spread traffic across more IPs. For per-IP limits, distribute requests over a rotating pool so each address stays under the threshold. Residential IPs help further because per-IP budgets for consumer address space are typically more generous than for datacenter ranges.
  6. Cache and deduplicate. The cheapest request is the one you do not send — cache stable responses, honor ETag/If-Modified-Since, and dedupe URL queues so retries and re-crawls do not double-spend quota.
  7. Smooth bursts with a token-bucket limiter in your client. Most sites tolerate a steady drip far better than idle periods punctuated by bursts of hundreds of requests.
  8. Check for shared-IP contention. On shared or datacenter proxies, other tenants may have already spent an IP's quota before your first request — cleaner pools mean your requests start from a lower counter.
429 Too Many Requests

Rate limits and proxy strategy

429 is the error where proxy choice genuinely matters most. Per-IP rate limits are the most common kind, and they are precisely what IP rotation addresses: instead of one address absorbing your entire request rate, a rotating pool spreads it so each exit stays under the site's threshold. The math is straightforward — divide your target request rate by what one IP can sustain, and you know how much rotation you need.

Session design is the other half. Sticky sessions concentrate requests on one exit, which is right for logged-in flows where the site expects one user from one IP — but wrong for high-volume crawling, where stickiness turns a pool back into a single rate-limited address. Match the session model to the workload (see /use-web-scraping/), not the other way around.

Rotation as rate-limit spreading

Budget Unlimited (/plan-unlimited/) rotates each port on an interval across a 1.5M+ residential pool, so sustained crawls distribute naturally across exits. For request-level control, vary -session-<id> per worker or per batch — every distinct session ID is its own sticky exit, giving you deliberate sharding instead of luck.

Sticky where the site expects a user

Login flows, carts, and paginated dashboards often throttle erratic IP switching harder than steady traffic from one address. Use -session-<id> (sticky up to 24 hours) with -ttl-<seconds> to hold one exit for exactly the lifetime of the flow, then release it. One user, one IP, one session — from the site's perspective, normal behavior.

IP quality changes your quota

How much a site lets one IP do depends on what that IP looks like. Platinum ISP residential (/plan-platinum/) provides Tier-1 ISP-quality addresses with country, state, city, and ASN targeting, and Mobile (/plan-mobile/) provides real 4G/5G carrier IPs — address space many real users share, which sites tend to throttle more cautiously. Both are pay-as-you-go per GB, which fits these lower-volume, higher-value workloads.

429 Too Many Requests

Backoff plus rotation in Python

This client honors Retry-After when present, falls back to exponential backoff with jitter, and rotates to a fresh exit on each retry so a per-IP limit does not stall the whole worker.

import random
import time
import uuid
import requests

def proxied(session_id):
    user = f"USERNAME-country-us-session-{session_id}"
    p = f"http://{user}:[email protected]:10000"
    return {"http": p, "https": p}

def fetch(url, attempts=5):
    for i in range(attempts):
        r = requests.get(url, proxies=proxied(uuid.uuid4().hex[:8]), timeout=30)
        if r.status_code != 429:
            return r
        retry_after = r.headers.get("Retry-After")
        wait = float(retry_after) if retry_after else (2 ** i) + random.random()
        time.sleep(wait)
    return r

print(fetch("https://example.com/api/items").status_code)
FAQ

Frequently asked questions

Will rotating proxies always fix 429 errors?
Only when the limit is keyed on your IP address. If the server counts requests per API key, account, or session cookie, every IP you rotate through still increments the same counter. Test with one request from a fresh IP: instant success means per-IP limiting; another 429 means the key is in your credentials or cookies.
How long should I wait after a 429?
If the response includes a Retry-After header, wait exactly that many seconds — it is the server telling you when the window resets. Without it, use exponential backoff starting around one second and doubling per attempt, with random jitter so parallel workers do not retry simultaneously and immediately re-trigger the limit together.
Why do I get 429 on my very first request?
The counter was not at zero when you arrived. On shared or datacenter proxy IPs, other users may have already spent that address's quota. Some sites also apply preemptive throttles to entire datacenter ranges. Moving to residential or ISP-grade IPs typically starts you from a much cleaner per-IP budget.
Should I use sticky sessions or rotation to avoid 429s?
Match the site's expectations. High-volume crawling across many pages wants rotation, so no single exit absorbs the full request rate. Authenticated flows want a sticky session (-session-<id>) because sites often treat mid-session IP changes as suspicious. Many scrapers combine both: sticky per logged-in identity, rotating for anonymous page fetches.

Spread your traffic before sites throttle it Start routing today.

Per-port interval rotation across a 1.5M+ residential pool, sticky sessions up to 24 hours, and targeting in 200+ countries.

ProxyOmega ProxyOmega

90M+ ethically-sourced IPs across 200+ countries and 30,000+ cities. Residential, mobile, ISP and IPv6 proxies for scraping and AI agents.

GDPRCCPA
Product
Premium Unlimited Budget Unlimited Residential / ISP Mobile IPv6 Chrome Extension
Solutions
Web scraping AI agents Price monitoring SERP & SEO Integrations All use cases
Resources
Glossary Error codes Free tools Proxies by platform Locations
Company
About Blog Docs Reseller program Affiliate Contact Sign in
© 2026 ProxyOmega Ltd. All rights reserved.