November 2, 2026
Rate Limit Bypass Techniques: A Bug Bounty Hunter’s Field Guide
Why rate limits are worth your time

By Devansh Patel
8 min read
- 1 Why rate limits are worth your time
- 2 First, learn what the limiter counts
- 3 Common algorithms matter too. A fixed window resets at a boundary, so you can fire a full quota at the end of one window and again at the start of the next. Token and leaky buckets refill steadily, so slow pacing just under the refill rate can be unlimited in practice.
- 4 Technique 1: Spoof the client IP with headers
- 5 Technique 2: Vary the request so it looks new
Why rate limits are worth your time
A rate limit bypass is only as valuable as the endpoint it protects: on a login, OTP or password-reset flow it can lead to account takeover; on a search or export endpoint it is usually informative. Most rate limiters key on one attribute of the client (an IP, a token, a session), and most bypasses work by changing that attribute while the real target stays the same.
This guide groups the techniques by what they change: who the server thinks you are, what request it thinks you sent, and how many requests it thinks it saw.
High-value targets to test first:
- Login and 2FA/OTP verification
- OTP, SMS and email sending (cost and spam impact)
- Password reset token and code submission
- Coupon, gift card, voucher and referral code redemption
- Signup, invite and contact forms
- Expensive API calls: search, export, report generation, AI or third-party paid calls
Ground rules. Only test in-scope assets on programs that allow it, and read the policy: many programs exclude rate-limit findings on non-sensitive endpoints, and some forbid high-volume testing outright. Use your own test accounts, keep volume to the minimum that proves the bypass (often 50–200 requests), and never brute-force real users' credentials.
First, learn what the limiter counts
Every bypass starts with one question: what is the counting key, and where is it computed? Find the limit, then change one variable at a time until the counter resets.
Common algorithms matter too. A fixed window resets at a boundary, so you can fire a full quota at the end of one window and again at the start of the next. Token and leaky buckets refill steadily, so slow pacing just under the refill rate can be unlimited in practice.
Read the responses closely: 429 Too Many Requests, Retry-After, and X-RateLimit-Limit / -Remaining / -Reset headers tell you the quota and window. Also note where the limit lives: a CDN or WAF, an API gateway, or application code. Edge limiters often key on IP alone, while the app may trust a forwarded header.
Technique 1: Spoof the client IP with headers
This is the most common real-world bypass. Apps behind a proxy read the client IP from a forwarding header, and if they trust that header from anyone, you choose your own IP. Add one header at a time, change its value when you hit the limit, and watch whether the counter resets.
POST /api/auth/verify-otp HTTP/1.1
Host: target.example
X-Forwarded-For: 203.0.113.17
Content-Type: application/json
{"phone":"+15550100","code":"000123"}POST /api/auth/verify-otp HTTP/1.1
Host: target.example
X-Forwarded-For: 203.0.113.17
Content-Type: application/json
{"phone":"+15550100","code":"000123"}Headers worth trying:
X-Forwarded-For,X-Real-IP,X-Client-IP,X-Originating-IPX-Remote-IP,X-Remote-Addr,X-Host,X-Forwarded-HostTrue-Client-IP(Akamai/Cloudflare style),CF-Connecting-IP,Fastly-Client-IPForwarded: for=203.0.113.17(the RFC 7239 standard form)X-ProxyUser-Ip,X-Cluster-Client-IP,Client-IP
Variations that often matter:
- Chains.
X-Forwarded-For: 203.0.113.17, 127.0.0.1— some apps take the first entry, some the last. Change only the one the app reads. - Duplicates. Send the same header twice with different values, or several different headers together.
- Internal values.
127.0.0.1,localhost, or an RFC 1918 address can land on an allowlist that skips limiting entirely. - Format tricks. IPv6, padded or decimal forms (
0177.0.0.1), or a trailing space can produce a fresh counter key while still parsing as valid.
If headers fail, the limit is likely keyed on the real socket IP at the edge. Genuine IP rotation (cloud egress IPs, IPv6 ranges, mobile networks) is a legitimate test of that, but check program rules: some treat it as out of scope or as noise rather than a vulnerability.
Technique 2: Vary the request so it looks new
When the limiter keys on the exact URL or the exact identifier, a request that the backend treats as identical but the limiter treats as different gets a fresh counter.
Path variations (the router normalises these; the limiter often doesn't):
Identifier variations (the limiter counts per string; the backend normalises to the same account):
- Case:
Victim@Example.comvsvictim@example.com - Whitespace and control characters: trailing space,
%20,%09,%0d%0a,%00 - Email tricks:
victim+1@example.com, dots in Gmail local parts, URL-encoded @ as%40 - Phone formats:
+15550100,15550100,+1 555 0100, leading zeros
Parameter and body tricks:
- Parameter pollution:
email=a@x.com&email=b@x.com— the limiter may read one value and the app the other. - Switch content types: form-encoded, JSON, XML, or multipart for the same endpoint.
- Wrap values:
{"email":["victim@example.com"]}or a nested object, if the parser accepts it. - Add junk parameters or change parameter order to break cache- or hash-based keys.
Method switching: try GET, PUT, PATCH or HEAD on a POST endpoint, or X-HTTP-Method-Override: POST on a GET. The limit is often bound to one method only.
Header rotation: change User-Agent, Accept-Language, Referer and Origin. This only works when the limiter fingerprints on headers, but that is more common than you'd expect.
Technique 3: Rotate sessions, tokens and keys
If the counter lives in the session, a new session is a new counter. Test these in order:
- Drop the session cookie entirely and resend. Some limiters only count requests that carry a session.
- Request a fresh session or CSRF token (load the login page again) before each attempt.
- Switch between authenticated and unauthenticated calls to the same function.
- Rotate API keys or OAuth tokens you legitimately own, if the limit is per key rather than per account or target.
- Log in, then log out, then retry: some apps reset failure counters on any successful login, including to an attacker's own account from the same session.
The last point generalises. If a successful action anywhere resets the failed-attempt counter, interleaving one valid request (your own account, a correct CAPTCHA) every N attempts can keep you under the limit forever.
CAPTCHA as a rate limit. Treat CAPTCHA as part of the limiter and test it the same way: remove the CAPTCHA parameter, send it empty, reuse one solved token across many requests, or call the mobile or API version of the endpoint, which often has no CAPTCHA at all.
Technique 4: Make many attempts look like one
These attack the counter itself rather than the key it uses.
Race conditions. Many limiters read the counter, process the request, then increment. Send 20–30 requests in the same instant and they all read "0 used". Burp Repeater's "send group in parallel" (single-packet attack over HTTP/2) and Turbo Intruder are the standard tools. Compare how many succeeded against the stated limit.
HTTP/2 multiplexing. Some edge limiters count connections, not streams. Many streams over one connection can slip through as a single client event.
GraphQL aliases and batching. One HTTP request can carry dozens of operations:
mutation {
a1: verifyOtp(code: "000001") { ok }
a2: verifyOtp(code: "000002") { ok }
a3: verifyOtp(code: "000003") { ok }
}mutation {
a1: verifyOtp(code: "000001") { ok }
a2: verifyOtp(code: "000002") { ok }
a3: verifyOtp(code: "000003") { ok }
}If the limit counts HTTP requests, each request tries many codes. Also try array batching ([{query…},{query…}]) when the server accepts it.
REST batch endpoints. Look for /batch, /bulk, or JSON-RPC endpoints that accept arrays of calls, and for array values in a single field ("code": ["0001","0002",…]).
Window-edge timing. With a fixed window, send a full quota just before the reset and another just after: double the throughput, and it proves the window is the weakness.
Slow and low. If the window is short, pacing requests just under the threshold can be effectively unlimited. On a 6-digit OTP that never expires, that is still a finding; on a code valid for 5 minutes, it usually is not.
Technique 5: Find the door without a lock
The best bypasses skip the limiter entirely by reaching the same function another way.
- Alternate clients. Mobile app APIs, legacy web versions, partner APIs and internal admin routes often share the backend but not the gateway rules. Proxy the mobile app and compare.
- Old API versions.
/v1/endpoints frequently survive with none of the protections added to/v3/. - Parallel flows. The login form is limited, but "login with magic link", "verify email", "change phone" or an SSO callback validates the same secret with no limit.
- Counter resets on resend. Requesting a new OTP may reset the attempt counter without invalidating the old code, giving fresh attempts at the same code.
- Limit without lockout. The API returns 429 but still processes the request, or the limit blocks the response body but a different status code or length still reveals a correct guess. Always check whether the correct value behaves differently while rate limited.
- Client-side limits. The countdown or "too many attempts" message is enforced in JavaScript only. Replay the raw request.
- Per-target vs per-attacker. Limits that count per attacker IP but not per victim account allow spreading attempts on one victim; limits that count per victim but not globally allow spraying one password across many accounts.
- Subdomains and regions.
api-eu.,staging., or region-specific hosts may route to the same data with different edge config.
A repeatable testing workflow
- Map sensitive endpoints. Walk every auth, OTP, reset, redemption and paid-action flow on web and mobile. Note each request in Burp.
- Establish a baseline. Send requests with a fixed bad value until you get blocked. Record the limit, the window, the block response (status, body, length, headers) and how long until it clears.
- Identify the key. Change one thing at a time (IP header, cookie, identifier format, path) and see which change resets the counter.
- Apply the matching technique family from sections above, cheapest first: headers, then request variation, then sessions, then concurrency, then alternate flows.
- Prove it with a correct value. Plant your own valid code or password after N failed attempts. A bypass that never shows a successful hit past the limit is hard to rate highly.
- Measure and stop. Record how many attempts got through versus the stated limit, then stop. You need proof, not exhaustion.
Tools that cover nearly everything:
Writing a report that gets paid
Triage teams close "no rate limit" reports as informative every day. What gets paid is a bypass tied to concrete impact, with numbers.
Include in every report:
- Summary: endpoint, the limit you observed, and the technique that bypassed it, in two sentences.
- Baseline evidence: the blocked response after N attempts.
- Bypass evidence: the modified request and the successful responses beyond the limit.
- Proof of impact: your own account's correct code accepted after the limit, with the attempt count.
- Math: keyspace versus achievable rate (a 6-digit code is 1,000,000 values; at 100 req/s that is under 3 hours, faster with parallelism).
- Fix: one or two specific remediation lines (next section).
Keep the PoC minimal and reproducible. A short Burp sequence or a description of the race setup beats a large automation script.
How defenders close these gaps
OWASP files missing or weak limits under API4:2023 Unrestricted Resource Consumption, the successor to the 2019 "Lack of Resources and Rate Limiting" category. The fixes map one-to-one onto the techniques above:
- Trust forwarding headers only from your own proxies, and read the right hop. Never take the client IP from a header the client controls.
- Count on the target, not just the attacker. Limit attempts per account, per phone number and per code, in addition to per IP.
- Normalise before counting. Canonicalise paths, emails, phone numbers and case before building the rate-limit key.
- Apply limits at the function level across every route, version, method and client that reaches it, including GraphQL resolvers and batch endpoints.
- Use atomic counters (e.g. Redis
INCRbefore processing) so concurrent requests cannot race past the check. - Make secrets expire. Invalidate an OTP after a few wrong guesses or on resend, and keep validity short.
- Don't reset counters on unrelated success, and return identical responses for wrong guesses while blocked.
If you want to read more stories like these:
Unauthenticated Image Access and EXIF Location Leak, Easy P4, you can find under 2 mins Unauthenticated Image Access and EXIF Location Leak, Easy P4, you can find under 2 mins FREE LINK Hello people. Here's…
How I hacked a website just by looking at the source code Part-2 This is a very easy P4 bug.
Stay curious. Stay dangerous. 💻🕶