Migration
Migrate From CapSolver: AntiTurnstileTaskProxyLess on ZeroCaptcha
Move Cloudflare Turnstile tasks from CapSolver to ZeroCaptcha: AntiTurnstileTaskProxyLess and its metadata fields work as they are. Change host and key.
4 min readPublished Updated
CapSolver’s Cloudflare Turnstile task, AntiTurnstileTaskProxyLess, is one of the task types ZeroCaptcha
accepts as it is. A client written for CapSolver’s createTask and getTaskResult sends the
same JSON to ZeroCaptcha, with the action and cData nested in metadata the way CapSolver
documents them. The work is changing the host and the key, then checking a few details. This guide
lists them.
ZeroCaptcha is not affiliated with CapSolver. Facts about CapSolver below come from its public pages, checked 1 October 2026.
What CapSolver’s request looks like
CapSolver documents Turnstile at
its Cloudflare Turnstile guide: a
createTask call to https://api.capsolver.com/createTask with the task type
AntiTurnstileTaskProxyLess, websiteURL, websiteKey, and an optional metadata object
holding action and cdata.
The same request on ZeroCaptcha
{ "clientKey": "zc_live_…", "task": { "type": "AntiTurnstileTaskProxyLess", "websiteURL": "https://shop.example.com/login", "websiteKey": "0x4AAAAAAAB1cD2eF3gH4iJ5", "metadata": { "action": "login", "cdata": "sess_91f2c0" } }}Post it to /createTask on your ZeroCaptcha API host instead of api.capsolver.com. The reply is
{"errorId": 0, "taskId": "…"}. Then poll /getTaskResult with clientKey and taskId, as
before, every second or two.
ZeroCaptcha treats AntiTurnstileTaskProxyLess exactly like its own TurnstileTaskProxyless:
same price, same checks, same result. AntiTurnstileTask maps to TurnstileTask, which solves
through your proxy. Fields the task does not use, such as userAgent, are accepted and ignored.
In code
With Python and requests, the whole change is two values:
import os, time, uuid, requests
API = os.environ["ZEROCAPTCHA_API"] # was https://api.capsolver.comKEY = os.environ["ZEROCAPTCHA_KEY"] # was your CapSolver key
# New: an Idempotency-Key, so a retried create returns the same task instead of a second one.created = requests.post(f"{API}/createTask", timeout=15, headers={"Idempotency-Key": str(uuid.uuid4())}, json={ "clientKey": KEY, "task": { "type": "AntiTurnstileTaskProxyLess", "websiteURL": "https://shop.example.com/login", "websiteKey": "0x4AAAAAAAB1cD2eF3gH4iJ5", # Unchanged from CapSolver: the widget's data-action and data-cdata (or turnstile.render()'s # action and cData) in metadata. Leave out any the widget does not set. "metadata": {"action": "login", "cdata": "session-7f3a9c2e"}, },}).json()if created["errorId"]: raise RuntimeError(created["errorCode"])
while True: time.sleep(2) result = requests.post(f"{API}/getTaskResult", timeout=15, json={"clientKey": KEY, "taskId": created["taskId"]}).json() if result["errorId"]: raise RuntimeError(result["errorCode"]) if result["status"] == "ready": print(result["solution"]["token"]) breakFor production code with a deadline, retries and idempotency, start from the quickstart or the Python page. The Cloudflare Turnstile solver page has the same flow in Node.js, Go, PHP, Java, C# and curl.
Keeping both providers configured
During the move, it helps to run both side by side. Keep the host, the key and the task type in
one small configuration object per provider, and choose the provider per worker or per job. Since
both accept AntiTurnstileTaskProxyLess in the same JSON shape, the only values that differ are
the host and the key:
PROVIDERS = { "capsolver": {"api": "https://api.capsolver.com", "key": os.environ["CAPSOLVER_KEY"]}, "zerocaptcha": {"api": os.environ["ZEROCAPTCHA_API"], "key": os.environ["ZEROCAPTCHA_KEY"]},}Log which provider solved each task along with the outcome, so you can compare success and solve time on your own pages before moving everything.
What a failed task costs
On ZeroCaptcha, a task’s price is held when you create it and released at once if the task fails
or times out, so a failed task costs nothing. getTaskResult then answers errorId 1 with a code
such as ERROR_CAPTCHA_UNSOLVABLE or ERROR_TASK_TIMEOUT. A task your balance cannot cover is
refused up front with ERROR_ZERO_BALANCE. Captcha API error codes
covers the full list.
Differences to check
- Task IDs are UUIDs, such as
0192f3a4-7b1c-7d2e-9f10-3c4d5e6f7a8b. Keep them as strings. - The solution holds the token and its type,
solution.tokenandsolution.type(turnstile). There is nouserAgentin it. The ready reply addscost,solveCount,createTime,endTimeandexpiresAt, which says when the token stops working. - Proxies are HTTP or HTTPS. SOCKS is not supported yet. See Solve Cloudflare Turnstile with a proxy.
- “Slow down” is
ERROR_RATE_LIMIT, with aRetry-Afterheader that says how long to wait.createTaskhas no call budget of its own: your balance and your share of the queue bound it. See Rate limits and concurrency. - Cloudflare challenge pages. CapSolver lists a Cloudflare Challenge task on its site. ZeroCaptcha accepts AntiCloudflareTask as CloudflareChallengeTask, through your proxy only. See the Cloudflare WAF and 5-second challenge solver page.
Prices
CapSolver lists Cloudflare Turnstile at $1.2 per 1k and Cloudflare Challenge at $1.2 per 1k on its home page (checked 1 October 2026). ZeroCaptcha’s price per 1,000 solved tasks is on its pricing page. ZeroCaptcha charges only when a token is ready, from a prepaid US dollar balance you top up in crypto.
Rolling it out
- Create a ZeroCaptcha account and key, and add funds: see the quickstart.
- Put the API host and key in configuration.
- Send one worker’s tasks to ZeroCaptcha and compare results on your own pages.
- Watch the status page for the platform’s success rate and median solve time.
- Move the rest.
The CapSolver alternative page compares the two services side by side.