In this Article
Every API worth using limits how fast you can call it, and most integration problems attributed to flaky APIs are really a client that does not pace itself. The good news is that rate limiting is a small, well-understood problem with a correct answer.
This guide covers the three algorithms in use, what the headers mean, the retry pattern that actually works, and where the line sits between handling a limit and going around one.
Key Facts
- Three algorithms cover almost every implementation: fixed window, sliding window and token bucket, and they fail differently at the boundary.
- The headers usually tell you the answer. Limit, remaining and reset are standard enough that a client can pace itself without guessing.
- Retry-After is not advisory. Ignoring it is the fastest route from throttling to a block.
- Fixed-interval retries resynchronise into bursts. Jitter is what stops many clients from retrying in lockstep.
- Per-key limits and per-IP limits are different questions. Routing around a per-key limit is evasion; that distinction is the whole ethical line here.
How is rate limiting implemented?
Three algorithms, and knowing which one you are facing explains the behaviour you see. We call it the 3-part limiter model.
| Algorithm | How it counts | Symptom |
|---|---|---|
| 1. Fixed window | N requests per clock interval, counter resets on the boundary | Double bursts across a boundary, then a hard wall |
| 2. Sliding window | N requests in any trailing interval | Smoother, and no boundary trick to exploit |
| 3. Token bucket | Tokens refill at a steady rate, bucket has a burst capacity | Short bursts allowed, sustained rate enforced |
Token bucket is the most common in practice and the friendliest to work with, because it tolerates a burst and then holds you at the refill rate. If an API lets you fire twenty calls instantly and then slows to a steady trickle, that is what you are looking at, and the correct client behaviour is to pace to the refill rate rather than to the burst size.
What do the headers tell you?
Most APIs return a limit, a remaining count and a reset time, either as individual headers or in the standard combined form. A client that reads them does not need to guess anything.
The pattern worth implementing once and reusing: read remaining after every response, and when it falls below a small threshold, slow down before you hit zero rather than after. Waiting until you are rejected means you have already generated a rejected request, and on some services those count toward abuse scoring even though they returned nothing.
When a 429 does arrive, Retry-After is the server telling you exactly how long to wait. Honour it literally. Retrying sooner is the behaviour that turns a temporary throttle into a longer block, and it is the most common reason an integration goes from slow to banned.
What does correct backoff look like?
Exponential, capped, with jitter, and only on the right errors.
- Retry these: connection failures, timeouts, 429, and 5xx responses. These are transient by definition.
- Do not retry these: 400, 401, 403, 404 and 422. Repeating a request the server has already rejected on its merits achieves nothing and looks like an attack.
- Cap the delay at something sane, commonly a minute, so a long outage does not push retries hours into the future.
- Add jitter. Without it, many clients that failed at the same moment retry at the same moment, and the recovering service gets hit by a synchronised wave. Randomising the delay is what breaks that lockstep.
- Cap attempts and then fail loudly. Infinite retry hides outages instead of surfacing them.
Alongside retries, the cheapest win is usually not sending the request at all: cache responses that do not change often, batch where the API supports it, and use conditional requests so unchanged data costs you a small response instead of a full one.
Where do proxies fit, and where is the line?
| Situation | Use this when | Avoid when |
|---|---|---|
| Per-key limit on an API you authenticate to | Pace to the limit, or buy a higher tier | Routing around it; the limit follows the key, not the address |
| Per-IP limit on public endpoints | Distributed exits, kept polite per host | Terms prohibit automated access |
| Geo-restricted or geo-varying responses | Exits in the relevant country | The response is identical everywhere |
| Testing your own service’s limiter | Many distinct sources, on your own infrastructure | Any system you do not own or have authorization to test |
The first row is the honest line. A limit attached to your API key is part of a commercial agreement, and spreading the same key across many addresses is evasion of that agreement, not engineering. A per-IP limit on a public endpoint is a different question, and there the answer is still to stay polite per host rather than to maximise throughput.
DataImpulse residential covers the second and third rows at $1 per GB across 195 countries with country, city and ZIP targeting.
What else matters?
Limits are often multi-dimensional. Requests per second, requests per day, concurrent connections and payload size can each have their own ceiling, and hitting any one produces the same 429. Read the documentation rather than inferring from one number.
Server-side limiting is cheap to add and worth it. If you run an API, a token bucket per key with clear headers and an accurate Retry-After makes well-behaved clients easy and badly behaved ones obvious.
Rate limits are not only about load. They also cap the damage from a leaked key and slow down enumeration, which is why bypassing them is treated seriously even when your intent is ordinary.
Related: 403 Forbidden explained, HTTP status codes for scrapers.
Frequently Asked Questions
What is API rate limiting?
A cap on how many requests a client may make in a period, implemented as a fixed window, a sliding window or a token bucket. Token bucket is the most common: it allows a short burst and then holds you at a steady refill rate.
How should I handle a 429 response?
Honour Retry-After literally if it is present, otherwise back off exponentially with a cap and random jitter. Retrying sooner than the server asked is the most common reason a temporary throttle becomes a longer block.
Why does everything fail at once after an outage?
Because clients that failed at the same moment retry at the same moment. Fixed-interval backoff resynchronises them into a wave that hits the recovering service. Random jitter on the delay is what breaks the lockstep.
Can I use proxies to get around API rate limits?
Not for limits attached to your API key: the limit follows the key, so spreading it across addresses is evading a commercial agreement rather than solving an engineering problem. Distributed exits are appropriate for per-IP limits on public endpoints, kept polite per host.
How do I reduce API usage without losing data?
Cache responses that change slowly, batch requests where the API supports it, and use conditional requests so unchanged resources cost a small response instead of a full one. The cheapest request is the one you do not send.
When the limit is per address, not per key
Public endpoints that limit by address and responses that vary by country both need exits in the right place. DataImpulse residential proxies cover 195 countries at $1 per GB with country, city and ZIP targeting. Create an account.
Related: HTTP status codes for scrapers · 403 Forbidden when scraping · proxies for web scraping.
Last updated: September 18, 2026.

State/City/Zip/ASN Targeting 



