Troubleshooting
Cloudflare Error 1015 Rate Limited: Causes and Backoff in Code
Cloudflare error 1015 means a site's rate limiting rule blocked you. How the rules count, the 429 status, and Python backoff that stops the retries.
By ZeroCaptcha Engineering6 min readPublished Updated
Cloudflare error 1015, “You are being rate limited”, means the site’s owner has a rate limiting rule and your client sent more matching requests than it allows in its counting period. Cloudflare answers a rate-limited request with HTTP 429 by default (the owner can choose any code from 400 to 499), and keeps doing so for the rule’s duration, which ranges from 10 seconds to one day depending on the owner’s plan and settings. The fix is on your side and in your code: send fewer requests, back off when you see 429 or 1015, and never retry in a tight loop, which Cloudflare warns “may extend the block.”
Only automate sites you are allowed to: your own, a client’s, or one whose terms permit it. See responsible captcha automation.
What Cloudflare’s docs say about error 1015
The error page (checked 1 October 2026) explains that “The website you are trying to visit has received too many requests and has temporarily blocked you from accessing it”, and names rate limiting rules as the cause. Its advice to visitors: “Wait for a period of time”, and “Do not repeatedly try to access the website within a short period of time, as this may extend the block.” It also tells visitors to contact the site owner, since the owner sets the rule. Its advice to owners is to review their thresholds, and, if a rule blocks within a very short period such as one second, to try increasing the period to 10 seconds.
How a rate limiting rule counts
A rate limiting rule matches requests with an expression, like any other WAF rule, then counts them. Its parameters, as Cloudflare documents them:
- Characteristics: what makes requests count as coming from the same client. IP address on every plan; more options, such as headers, cookie, ASN, country, path or JA3/JA4 fingerprint, with Enterprise’s Advanced Rate Limiting.
- Period and requests per period: the rate that triggers the rule.
- Duration: how long the action applies once triggered.
- Behavior: “Perform action during the selected duration” applies the rule’s action to every request received during the duration; “Throttle requests over the maximum configured rate”, an Enterprise add-on, acts only on the requests over the limit and lets the others through.
What each plan allows (checked 1 October 2026):
| Plan | Rules | Counting period | Duration (mitigation timeout) | Characteristics |
|---|---|---|---|---|
| Free | 1 | 10 s | 10 s | IP |
| Pro | 2 | Up to 1 minute | Up to 1 hour | IP |
| Business | 5 | Up to 10 minutes | Up to 1 day | IP, IP with NAT support |
| Enterprise | 100 | Up to 65,535 s | Up to 1 day | IP, IP with NAT support; with Advanced Rate Limiting also query, host, headers, cookie, ASN, country, path, JA3/JA4, custom |
Two details matter for a client. First, Cloudflare says “Rate limiting rules are not designed to
allow a precise number of requests to reach your origin server”: counters can update several
seconds late, so don’t plan to run right at the limit. Second, a rate limiting rule’s action is not
always a block. It can be block, a Non-Interactive, Managed or Interactive Challenge, or log,
so a rate limit can also show up as a challenge page. See Cloudflare challenge
types for those.
What your client receives
- The status. “The default value is
429(Too many requests)”, and an owner can enter any value “between400and499”. On Pro plans and higher the owner can also set the response body and content type, so the page may not be Cloudflare’s. - The code. 1xxx errors “appear in the HTML body of the response”, so a default block page names 1015 in its body.
Retry-After. Cloudflare’s rate limiting docs don’t say that aRetry-Afterheader is sent with a 1015 block (checked 1 October 2026). Its general 429 page says a server “may include aRetry-Afterheader”. Use it when it is there; don’t depend on it.
Back off in code
This Python helper uses requests (pip install requests). It treats a 429, or a 4xx page that
names 1015, as a rate limit; waits for Retry-After when the site sends one; otherwise doubles its
wait from 10 seconds with random jitter; and gives up after six tries, or when asked to wait longer
than ten minutes, instead of hammering.
import randomimport timefrom datetime import datetime, timezonefrom email.utils import parsedate_to_datetime
import requests
def is_rate_limited(response): if response.status_code == 429: return True # An owner can pick another 4xx code; Cloudflare puts the 1xxx code in the HTML body. return 400 <= response.status_code < 500 and "1015" in response.text
def retry_after_seconds(response): value = response.headers.get("Retry-After") if not value: return None if value.isdigit(): return int(value) try: return max(0.0, (parsedate_to_datetime(value) - datetime.now(timezone.utc)).total_seconds()) except (TypeError, ValueError): return None
def get_politely(session, url, tries=6, first_wait=10.0, longest_wait=600.0): for attempt in range(tries): response = session.get(url, timeout=30) if not is_rate_limited(response): return response wait = retry_after_seconds(response) if wait is None: # Double the wait each time, with jitter so parallel workers don't retry together. wait = random.uniform(0.5, 1.0) * min(longest_wait, first_wait * 2**attempt) if attempt == tries - 1 or wait > longest_wait: break time.sleep(wait) raise RuntimeError(f"still rate limited after {attempt + 1} tries: {url}")
session = requests.Session()for url in ["https://shop.example.com/catalog?page=1", "https://shop.example.com/catalog?page=2"]: page = get_politely(session, url) print(url, page.status_code) time.sleep(2) # a steady pace between pages, not a burstThe waits run 10, 20, 40, 80 and 160 seconds (each shortened by jitter), which covers the Free plan’s 10-second duration many times over and gives a longer block room to end. If six tries are not enough, the rule’s duration is longer than your job can wait: stop and look at your request rate rather than raising the retry count.
Stay under the limit
Backoff handles the error; pacing prevents it.
- Send requests at a steady rate. Start slow and measure. Because counting is per period, a burst of parallel requests trips a rule that the same number spread out would not.
- Cap concurrency across workers. Ten workers each pausing politely are still ten times the rate. Share one limit between them.
- Fetch less. Cache what you already have, request only pages that changed, and skip assets you don’t need.
- Treat a 1015 as a signal for the whole job, not for one URL. When one request is limited, the others from the same client are about to be.
Spread load over time, not over addresses. Rotating IP addresses so that each stays under a per-IP counter defeats a limit the owner set on purpose; if you need a higher rate, ask the owner, who can raise the threshold or exempt your traffic.
What a CAPTCHA solver does not change
A rate limit counts requests; no token or cookie resets the count. Cloudflare’s Challenge Passage documentation says “The Challenge Passage does not apply to rate limiting rules”, and a Cloudflare Turnstile token only proves a check on one form submission. ZeroCaptcha solves Cloudflare Turnstile, and has no feature for rate limits. If your client meets a challenge page rather than error 1015, the Cloudflare WAF and 5-second challenge solver page and the cf_clearance cookie explained cover that case. ZeroCaptcha’s own API has limits of its own, described in rate limits and concurrency.
For a hard refusal rather than a limit, see Cloudflare error 1020, and for how rate limiting rules sit among other rules, Cloudflare WAF rules explained.
Sources
- Cloudflare: Error 1015 (checked 1 October 2026)
- Cloudflare: 1xxx errors (checked 1 October 2026)
- Cloudflare: Error 429 (checked 1 October 2026)
- Cloudflare: Rate limiting rules (checked 1 October 2026)
- Cloudflare: Rate limiting parameters (checked 1 October 2026)
- Cloudflare: Create a rate limiting rule, for custom responses on Pro plans and above (checked 1 October 2026)
- Cloudflare: Challenge Passage (checked 1 October 2026)
The team that builds and runs the ZeroCaptcha API. Articles are drafted with AI tools, then checked against the API's code and the primary sources each one cites.