</> ConvertAtlas Developer Tools
Web

API Rate Limiting: How It Works and How to Handle It

Why APIs limit requests, the common algorithms, the headers to watch, and how to back off gracefully.

▮ 429 N requests allowed per window, then 429

Hit an API hard enough and you will meet 429 Too Many Requests. Rate limiting is how services protect themselves from overload and abuse, and how they share capacity fairly. Whether you are consuming an API or building one, understanding rate limiting helps you avoid being throttled and design limits that are fair.

▮ 429 N requests allowed per window, then 429
A rate limiter allows a set number of requests per window, then returns 429 until the window resets.

Why rate limits exist

Without limits, a single buggy client or malicious actor could exhaust a service’s capacity and degrade it for everyone. Rate limiting protects availability, ensures fair sharing among users, and provides a defence against brute-force and scraping attacks. It is a sign of a well-run API, not a hostile one.

Common algorithms

  • Fixed window — a counter that resets every interval (e.g. 100 requests per minute). Simple, but allows bursts at window edges.
  • Sliding window — smooths those edges by considering a rolling time range.
  • Token bucket — tokens refill at a steady rate and each request spends one, allowing controlled bursts while capping the sustained rate.

The headers to watch

Well-behaved APIs tell you where you stand. Look for headers like X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset, which report your quota and when it resets. When you are limited, the response is 429, often with a Retry-After header saying how long to wait. Reading these lets you stay just under the limit rather than blindly retrying.

Try it: Random Token GeneratorGenerate secure random tokens and API keys with custom length and charset.

Backing off gracefully

When you do hit a limit, the worst response is to retry immediately in a tight loop — that just keeps you blocked. Respect Retry-After when present, and otherwise use exponential backoff: wait a little, then double the wait each time you are rejected, with a touch of randomness to avoid synchronised retries. This recovers quickly without hammering the service.