For developers
API Rate Limiting by IP: Benefits, Limits, and Safer Rules
Design better API limits by combining IP, token, account, and organization-level controls.
- Author
- Mojahid Ul Haque
- Updated
- Reading time
- 9 min read
What IP-based rate limiting is
IP-based rate limiting counts the requests arriving from one source address inside a time window and slows or refuses the address once it passes a threshold. The counter can be a fixed window (so many requests per minute), a sliding window, or a token bucket that refills at a steady rate and allows short bursts. Whichever algorithm you pick, the key is the same: the client's address, which is why the technique works before a request has been authenticated and why it breaks down when one address stands for many people.
It is usually applied at the edge: an API gateway, a WAF, a reverse proxy or a CDN rule. It can also live in the application, which is the right place once a limit depends on who the caller is rather than where the packets came from. This guide is about designing the limits; the Node.js rate limiting guide covers the implementation.
Why it is useful
An IP limit needs no account, no API key and no knowledge of the caller, so it protects the endpoints that exist before authentication: login, signup, password reset, search, and anything that costs more to serve than to request. It absorbs accidental client loops, blunt scrapers and brute-force scripts before they reach the database, and it does so cheaply, because the check runs on a counter rather than on business logic.
OWASP lists unrestricted resource consumption among the top API security risks and names rate limiting, per-client quotas and response-size limits as the controls that address it. An IP limit is the simplest of those controls to switch on, which is a reason to have one and also a reason not to stop there.
The 429 response and Retry-After
The status code for a rejected request is 429 Too Many Requests, defined in RFC 6585. The RFC says the response should explain the condition and may carry a Retry-After header telling the client how long to wait. RFC 9110, the current HTTP semantics specification, defines Retry-After as either an HTTP date or a number of seconds. Send it: a well-behaved client will back off exactly as long as you ask, and a client that ignores it has told you something about itself.
Beyond the standard, an IETF working group is drafting RateLimit header fields that let a server advertise the quota, what remains of it and when the window resets, so clients can pace themselves before hitting 429. The draft is still work in progress, but its field names are already widely copied. Whatever headers you choose, keep the response body short and consistent, and log every 429 with the address, the limit that tripped and the endpoint, because those logs are where abuse patterns first show up.
Limits at more than one level
A per-IP limit answers one question: is this address sending too much? It says nothing about whether one customer is consuming more than they paid for or whether a stolen key is being used from a hundred addresses at once. Those need limits attached to identity. In practice a well-designed API has several concentric limits: a generous per-IP limit that mainly catches unauthenticated abuse; a per-key or per-user quota that enforces the plan the caller signed up for; an organization or tenant quota so that one customer with many keys cannot starve the others; and endpoint-specific or cost-weighted limits for the operations that are expensive to serve.
Combining IP with identity is where the real value lies. One key used from many addresses in a short time suggests a leaked credential. Many keys used from one address suggests either a legitimate shared integration server or an account farm; the request pattern tells you which. A per-IP limit that is looser than the per-key quota lets those combinations surface as anomalies instead of hiding them behind a wall of 429s.
Shared addresses: CGNAT, corporate NAT and IPv6
Many people share one public IPv4 address. Mobile carriers and some fixed-line ISPs place customers behind carrier-grade NAT, using the 100.64.0.0/10 shared address space that RFC 6598 set aside for it, and one public address can stand for thousands of subscribers. Offices, universities and hospitals route everyone through a handful of egress addresses. A strict per-address limit hits all of them at once, and the people it hits have no idea why. The CGNAT guide explains how large the pool behind one address can be.
IPv6 has the opposite problem. A single device can hold many addresses inside its /64, and privacy extensions rotate them, so a limit keyed on the full 128-bit address is trivial to sidestep. Count IPv6 traffic by prefix instead: the /64 is the smallest sensible unit, and because RFC 6177 describes end-site assignments in the range of /48 to /56, a determined client can rotate across many /64s, which argues for a second, looser counter at the /56 or /48 level. The IPv4 versus IPv6 guide covers why addresses rotate.
The design consequence is the same for both: treat the IP limit as coarse protection with a high threshold, prefer throttling to blocking when an address is shared, and put the precise quota on the identity layer.
Behind proxies and load balancers
If your API sits behind a load balancer, a CDN or a reverse proxy, the address on the socket is the proxy's, and a per-IP limit keyed on it will throttle your own infrastructure. The real client address arrives in a header: X-Forwarded-For by convention, or the Forwarded header standardized in RFC 7239. Read it only when the connection comes from a proxy you control, and take the address your proxy appended rather than the first one in the list, because anything a client can put in a header, an attacker can forge. A forged header either lets the attacker evade the limit or gets an innocent address throttled.
The X-Forwarded-For guide covers the trust rules in detail, and the Cloudflare proxy guide covers the CDN case.
API abuse signals beyond the counter
A request count is one signal. APIs receive a great deal of automated traffic, so the useful question is not whether a client is automated but whether its behavior matches a legitimate integration. Several IP-level signals help separate the two, and none of them is a verdict on its own.
Hosting ASN. Requests from cloud and hosting networks are normal for server-to-server integrations and abnormal for endpoints only a browser should call. Bots favor cloud servers because they are easy to automate, scale and replace; a checkout or signup endpoint seeing a burst from a hosting range deserves a closer look. The data center versus residential guide explains the classification.
Reputation. An address with recent abuse reports or a high fraud score is a reason to apply a tighter bucket to it, not a reason to reject its traffic outright; shared addresses inherit the reputation of whoever last misbehaved behind them.
Velocity and request pattern. Authentication failures per address, the ratio of errors to successes, an endpoint mix that no real client produces, and sequences such as walking through object IDs in order are the tells of scrapers and credential attacks. A sudden change in the country or ASN behind an established key is worth an alert even when the count is within limits.
Account and IP combinations. Many accounts created or authenticated from one address, one account appearing from many addresses in minutes, or several keys sharing an address they never shared before are patterns that a per-IP counter alone never sees. Location and ISP context also helps support teams explain an unexpected request source to a customer.
Risk-based throttling instead of blocking
The response to a signal should scale with it. Throttle first: give a suspicious address a smaller bucket rather than none. Then require authentication, or a stronger form of it, for the actions that matter, so that abuse has to spend a credential to continue. Reserve outright blocks for clear, repeated abuse, give them an expiry, and record why they were added, because a block on a shared address is a block on people who did nothing.
Measure the outcome. Track how many 429s reach clients that later authenticate successfully, how often support hears from customers behind carrier NAT, and how quickly abusive patterns stop when throttled. Those numbers tell you whether the thresholds are protecting the API or just its metrics, and they are the argument for changing them.
Sources
- RFC 6585: Additional HTTP Status Codes (429 Too Many Requests)
- RFC 9110: HTTP Semantics (Retry-After)
- IETF Internet-Draft: RateLimit header fields for HTTP
- OWASP API Security Top 10 2023: API4 Unrestricted Resource Consumption
- RFC 7239: Forwarded HTTP Extension
- RFC 6598: IANA-Reserved IPv4 Prefix for Shared Address Space
- RFC 6177: IPv6 Address Assignment to End Sites
Frequently asked questions
Keep reading
Related guides
- For developers2 min read
Rate Limiting by IP in Node.js: What You Need to Know First
A practical guide to IP-based rate limiting in Node.js — covering express-rate-limit, proxy trust, shared IPs, and when IP limits are not enough.
Updated
- For developers3 min read
How to Choose an IP Location API: Pricing, Performance, and What Really Matters
How to compare IP location APIs beyond the price tag: accuracy, uptime, rate limits, hidden costs and integration effort, with a checklist for choosing one.
Updated
- For developers7 min read
Webhook IP Allowlisting: Security Benefits and Common Mistakes
Use IP allowlists safely for webhooks while avoiding brittle rules, stale provider ranges, and false confidence.
Updated
- For developers3 min read
Free vs Paid IP Lookup Tools: What the Difference Actually Is
An honest comparison of free and paid IP lookup tools — covering data freshness, API access, rate limits, and when free is genuinely enough.
Updated