
You already have Cloudflare Turnstile handled. But then you hit a different wall: instead of a widget inside the page, the entire page is replaced by a full-screen "Verifying you are human" interstitial that never resolves for your script. That is the Cloudflare challenge page (the "5-second challenge" in a browser), and it needs a completely different API call than Turnstile does.
This walkthrough shows how to solve it with Kaptra's captcha API using the AntiCloudflareTask type: what parameters it needs, what comes back, and how to replay the result so your requests actually get through.
Widget vs full-page: know which one you are facing
These two Cloudflare defenses get confused all the time, and the fix for one does not work on the other:
- Turnstile: an embedded widget in a form. You collect a sitekey from the page, send it with the URL, and receive a token to submit with the form.
- The challenge page: the page itself is swapped for an interstitial. There is no sitekey anywhere. The solver has to pass the interstitial and return the resulting cookies, and those cookies are bound to the IP that earned them. That binding is exactly why this task type requires you to pass your own proxy.
Quick diagnostic: if your response body is mostly a "Just a moment..." page, it is the second case. Read on.
What the solved task hands you
When polling completes, solution contains cookies: the clearance material for that protected page. The flow from there:
- Create an
AntiCloudflareTaskwith the protected URL and your HTTP proxy. - Poll
getTaskResultuntilstatusisready. - Attach
solution["cookies"]to your session and send your real requests through the same proxy from step 1. The clearance was issued for that IP, so keep using it.
Full Python example
import time
import requests
# ---
BASE_URL = "https://api.kaptra.ai"
API_KEY = "YOUR_KAPTRA_API_KEY"
# ---
def solve_cloudflare_challenge(website_url: str, proxy: str) -> dict:
# 1. create the task; proxy is required for this type (HTTP only)
resp = requests.post(
f"{BASE_URL}/createTask",
json={
"clientKey": API_KEY,
"task": {
"type": "AntiCloudflareTask",
"websiteURL": website_url,
"proxy": proxy,
},
},
).json()
if resp.get("errorId"):
raise RuntimeError(f"createTask failed: {resp.get('errorCode')}")
task_id = resp["taskId"]
# 2. poll every 1-2s, max 120 queries per task
for _ in range(120):
result = requests.post(
f"{BASE_URL}/getTaskResult",
json={"clientKey": API_KEY, "taskId": task_id},
).json()
status = result.get("status")
if status == "ready":
return result["solution"] # {"cookies": ...}
if status == "failure":
raise RuntimeError(f"task failed: {result.get('errorCode')}")
# processing (or CAPTCHA_NOT_READY): keep polling
time.sleep(1.5)
raise TimeoutError("gave up after 120 polls")
# ---
if __name__ == "__main__":
my_proxy = "http://USER:PASS@HOST:PORT"
solution = solve_cloudflare_challenge(
"https://www.example.com/protected", my_proxy
)
print(solution["cookies"])
# 3. attach these cookies to your session and keep
# sending requests through that same proxy
Same client skeleton as the Turnstile flow: createTask, then poll every 1 to 2 seconds with a ceiling of 120 queries. CAPTCHA_NOT_READY means the worker is still on it; status settles at ready or failure.
Gotchas worth knowing before you ship
HTTP proxies only. The docs state it plainly: a public HTTP proxy is required and SOCKS is rejected. If your stack is SOCKS-only, front it with HTTP or use a different provider for these tasks.
Failure handling. Average solve time is under 10 seconds, so 120 polls at 1.5 second intervals is a wide margin. A failure surfaces as ERROR_CAPTCHA_UNSOLVABLE; retrying once with the same parameters is the normal move, because billing is per solved task.
Cost. $1.20 per 1,000 successful solves, nothing for failures or timeouts, no monthly fee, no expiring balance. New Kaptra accounts start with $10 in test credit, enough to validate the whole flow before you commit.
HTTP codes carry no signal. Every response is HTTP 200. The verdict lives in errorId (0 or 1) and errorCode in the JSON. If your code already speaks that envelope, nothing to change.
Summary
Widget: sitekey in, token out, submit with the form. Challenge page: your HTTP proxy in, cookies out, replay through that proxy. Different inputs, different outputs, same create-then-poll loop underneath.
- Site: kaptra.ai
-
AntiCloudflareTaskdocs: kaptra.ai/docs
The companion piece on Turnstile (the widget) is worth reading alongside this one. Questions or a task type you want covered next? The team answers tickets in Discord.
Top comments (0)