Skip to content

Explainer

Cloudflare 5-Second Challenge: What It Is Now and How to Pass It

The Cloudflare 5-second challenge is the old name for its JavaScript challenge page. What replaced it, how to recognise it, and how to pass it with an API.

By 5 min readPublished

The Cloudflare 5-second challenge is the old name for Cloudflare’s JavaScript challenge: the interstitial page that checked a visitor’s browser for a few seconds before the site loaded, then let it through with a cf_clearance cookie. The name stuck; the page changed. Today a site’s WAF rule shows a Managed Challenge or a Non-Interactive Challenge (API value js_challenge) in its place, which Cloudflare says “typically takes less than five seconds”, and Under Attack mode “determines whether to block or allow a visitor within five seconds”. Whatever it is called, it is passed the same way: by a browser that runs it to the end, or by a challenge task that does, and the result is the cf_clearance cookie.

This article covers what the name refers to today, how to recognise the page from code, why waiting does not help, and the full request that passes it, as Cloudflare documented it on 1 October 2026. Only automate sites you are allowed to: see responsible captcha automation.

Where the name comes from

Cloudflare’s JavaScript challenge was an interstitial page: the browser ran a script, waited a few seconds while the page said it was checking the browser, then reloaded into the site. People named it after the wait, and the name travelled: scraping forums still say “5-second challenge”, “5 sec challenge” or, in Chinese-language ones, 5秒盾, the “5-second shield”.

Cloudflare’s current names for the same job:

What people call it Cloudflare’s name today API value Who shows it
The 5-second challenge, the JS challenge Non-Interactive Challenge js_challenge A WAF custom or rate limiting rule with that action
The 5-second challenge, “Just a moment…” Managed Challenge managed_challenge A WAF rule with that action; Under Attack mode
“Checking your browser before accessing…” The interstitial challenge page of Under Attack mode (security level) Under Attack mode

The Managed Challenge is the one Cloudflare recommends for most rules: it chooses per request between a non-interactive check and one that asks for an interaction, such as a click. The Cloudflare challenge types article compares all three, with the clearance levels between them.

How to recognise it from code

A 5-second challenge, in any of its current forms, answers the first request with:

  • HTTP status 403;
  • the header cf-mitigated: challenge, which Cloudflare sets on every challenge page;
  • an HTML body, whatever the request asked for, titled “Just a moment…” in our checks, that loads its scripts from the site’s own /cdn-cgi/challenge-platform/ path.

A Block is different: also 403, but no cf-mitigated header, and usually a 1xxx error code such as 1020 in the body. No clearance lifts a Block. The Cloudflare WAF bypass article sorts every response a WAF can give.

Why waiting five seconds does not work

The old page looked like a timer, so a common first attempt is to sleep five seconds and ask again. It does not work, because the wait was never the check. The page runs Cloudflare’s checks in the browser, posts the result to /cdn-cgi/challenge-platform/, and only then does Cloudflare set the cf_clearance cookie. A client that runs no JavaScript, such as curl or Python’s requests, gets the same challenge page every time, however long it waits.

Two things do get through, on sites you may automate:

  1. A real browser that passes the page, then keeps its cookie. Cloudflare notes that browser automation frameworks such as Playwright and Puppeteer “are not supported for solving production challenges”, so an automated browser may never pass; see Playwright and “Just a moment”.
  2. A challenge task that passes the page through your own proxy and hands you the cookie with the user agent it was issued for.

Passing it with one request

ZeroCaptcha’s CloudflareChallengeTask takes the page’s URL and your proxy, and returns the cf_clearance cookie with the user agent it was issued for. The proxy is required: Cloudflare ties the cookie to “the specific visitor and device it was issued to”, so it must be earned from the address that will use it. The whole flow in Python, with every field a real integration sends:

"""Pass a Cloudflare 5-second (JS or managed) challenge, then fetch the page with the clearance."""
import os
import sys
import time
import uuid
import requests
API = os.environ.get("ZEROCAPTCHA_API", "https://api.zerocaptcha.io")
KEY = os.environ.get("ZEROCAPTCHA_KEY") or sys.exit("Set ZEROCAPTCHA_KEY to your API key, zc_live_...")
PROXY = os.environ.get("PROXY_URL") or sys.exit("Set PROXY_URL, such as http://user:pass@proxy.example.net:8080")
PAGE = "https://shop.example.com/"
headers = {"Authorization": f"Bearer {KEY}"}
# 1. Create the task: the page behind the challenge, your proxy, where to POST the result when the
# task ends, and an Idempotency-Key, so a retried request returns the same task instead of a
# second, paid one. A challenge page has no sitekey, so the task takes no websiteKey.
created = requests.post(
f"{API}/v1/tasks",
headers={**headers, "Idempotency-Key": str(uuid.uuid4())},
json={
"type": "CloudflareChallengeTask",
"websiteURL": PAGE,
"proxy": PROXY,
"callbackUrl": "https://example.com/zerocaptcha/callback",
},
timeout=15,
)
created.raise_for_status()
task = created.json()
# 2. Read it every 2 seconds until it ends.
while task["status"] in ("queued", "running"):
time.sleep(2)
task = requests.get(f"{API}/v1/tasks/{task['id']}", headers=headers, timeout=15).json()
if not task.get("solution"):
sys.exit(f"{task['errorCode']}: {task['errorDescription']}")
# 3. Fetch the page through the same proxy, with the cookie and exactly its user agent.
with requests.Session() as session:
session.proxies = {"http": PROXY, "https": PROXY}
session.headers["User-Agent"] = task["solution"]["userAgent"]
session.cookies.set("cf_clearance", task["solution"]["cookie"]["value"], domain="shop.example.com")
page = session.get(PAGE, timeout=30)
print(page.status_code, page.headers.get("cf-mitigated", "not challenged"))

Reuse the session for every request until the site challenges you again: the clearance lasts the site’s Challenge Passage time, 30 minutes by default, and the API serves it for 30 minutes after it is issued. A task is charged only when it succeeds, at the price on the pricing page; there is no free tier or trial. If the page loads with a valid cookie and still challenges you, the client’s TLS handshake may not match the browser its user agent names: see the challenge loop.

The same request in curl, Node, Go and PHP is in the Cloudflare WAF and 5-second challenges docs, and the Cloudflare WAF and 5-second challenge solver page has a sample that runs as copied against our own test page. To see the current form of the challenge for yourself, open the Cloudflare 5-second JS challenge test page.

Sources

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.

Questions

What is the Cloudflare 5-second challenge?

The old name for Cloudflare's JavaScript challenge: an interstitial page that checked the browser for a few seconds, then let it through with a cf_clearance cookie. Today a WAF rule shows a Managed or Non-Interactive Challenge in its place, and Under Attack mode a Managed Challenge.

Does waiting five seconds get past the challenge?

No. The page is not a timer: it runs Cloudflare's checks in the browser and posts the result back. A client that runs no JavaScript gets the same page however long it waits.

How do I pass the Cloudflare 5-second challenge in Python?

Earn a cf_clearance cookie once, in a browser or with a challenge task through your own proxy, then send it with exactly the user agent it was issued for, through the same proxy, on every request until the site challenges you again.

Read next

This article is part of the Cloudflare WAF and 5-second challenge solver hub. Every task is charged only when a token is ready.

Get an API key