Migration
Migrate From 2Captcha: Cloudflare Turnstile in.php and createTask
Move Cloudflare Turnstile solving from 2Captcha to ZeroCaptcha: keep in.php and res.php or createTask, change the host and key, and check what differs.
4 min readPublished Updated
If your code solves Cloudflare Turnstile through 2Captcha, you can move it to ZeroCaptcha without
rewriting it. ZeroCaptcha speaks both of the request formats 2Captcha documents for Turnstile:
the classic in.php and res.php, and the createTask JSON format. In most cases the change is
the base URL and the key. This guide shows both paths, the differences to check, and how to roll
the change out safely.
ZeroCaptcha is not affiliated with 2Captcha. Facts about 2Captcha below come from its public pages, checked 1 October 2026.
Path 1: in.php and res.php
2Captcha’s first API creates a task with in.php and reads it with res.php. ZeroCaptcha serves
both on its API host, for method=turnstile:
# Before: https://2captcha.com/in.php?key=OLD_KEY&method=turnstile&...# action and data are the widget's data-action and data-cdata (or turnstile.render()'s action and# cData options): keep sending them, and leave out any the widget does not set. The# Idempotency-Key makes a retried submit return the same task.curl -H "Idempotency-Key: $(uuidgen)" \ "$ZEROCAPTCHA_API/in.php?key=$ZEROCAPTCHA_KEY&method=turnstile&sitekey=0x4AAAAAAAB1cD2eF3gH4iJ5&pageurl=https%3A%2F%2Fshop.example.com%2Flogin&action=login&data=session-7f3a9c2e&json=1"{ "status": 1, "request": "10000004821" }Then poll res.php every second or two:
curl "$ZEROCAPTCHA_API/res.php?key=$ZEROCAPTCHA_KEY&action=get&id=10000004821&json=1"The replies are the ones 2Captcha clients already handle: CAPCHA_NOT_READY while the task runs,
OK|<token> (or {"status": 1, "request": "<token>"} with json=1) when it is solved, and an
error code such as ERROR_CAPTCHA_UNSOLVABLE when it is not. action=get2 adds the price, and
action=getbalance returns your balance. Every parameter is in
the 2Captcha format.
Path 2: createTask
2Captcha also documents a JSON format for Turnstile, with createTask at
https://api.2captcha.com/createTask and the task types TurnstileTaskProxyless and
TurnstileTask (2Captcha’s Cloudflare Turnstile docs).
ZeroCaptcha accepts the same types and the same fields, so a 2Captcha client’s body works
unchanged, with the widget’s action in action and its cData in data, as 2Captcha documents
them. Written fresh, send the two in the task’s metadata, as most createTask clients do:
{ "clientKey": "zc_live_…", "task": { "type": "TurnstileTaskProxyless", "websiteURL": "https://shop.example.com/login", "websiteKey": "0x4AAAAAAAB1cD2eF3gH4iJ5", "metadata": { "action": "login", "cdata": "session-7f3a9c2e" } }}Either way, copy them from the widget’s data-action and data-cdata (or the action and
cData options of turnstile.render()), and leave out any it does not set: many sites check both
when they verify the token. Post the body to /createTask on the ZeroCaptcha API host, with an
Idempotency-Key header so a retried create returns the same task, then poll /getTaskResult
with the taskId. userAgent and pagedata are
accepted and ignored. createTask and getTaskResult explained
walks through the replies.
What to check before you switch
- Task IDs.
in.phpanswers numbers, as 2Captcha does, such as10000004821, so a client that parses them as numbers works unchanged. The JSONcreateTaskformat answers UUIDs, such as0192f3a4-7b1c-7d2e-9f10-3c4d5e6f7a8b: code that uses it must keep the ID as text. - Cloudflare only.
method=turnstileinin.php, and the Cloudflare Turnstile and challenge page task types in the JSON format. Other methods are answered withERROR_BAD_PARAMETERS(orERROR_TASK_NOT_SUPPORTEDin the JSON format), at no charge. - Proxies are HTTP or HTTPS. SOCKS proxies are not supported yet and are refused with
ERROR_PROXY_FORMAT. See Solve Cloudflare Turnstile with a proxy. - Several tasks at once:
action=getwithidsreads up to 100, as 2Captcha documents it. - Reports are recorded, not refunded.
reportbadandreportgoodanswerOK_REPORT_RECORDEDand our staff read them, but every charge is final. - Cloudflare challenge pages (the
pagedatacase) are not served in the 2Captcha format, whose replies have no place for the user agent a clearance needs. Use the createTask format or REST for them. See the Cloudflare WAF and 5-second challenge solver page.
pingback works without registration
On ZeroCaptcha, any public http or https URL works as pingback, with nothing to register first,
and each call carries a ZeroCaptcha-Signature header you can check with
HMAC-SHA256. The call is a form post of id=<task id>&code=<token>, or the error code. See
Captcha solver callbacks.
Prices
2Captcha lists Cloudflare Turnstile at $1.45 per 1,000 on its pricing page (checked 1 October 2026). ZeroCaptcha’s current price per 1,000 solved tasks is on its pricing page. On ZeroCaptcha you are charged only when a token is ready; a task that fails or expires costs nothing.
Rolling it out
- Sign up with an email and a password, create a key and add funds.
- Make the base URL and key configuration, not code, if they are not already.
- Point a share of your traffic, such as one worker, at ZeroCaptcha.
- Compare solve times and success on your pages, and on the status page.
- Move the rest once you are satisfied.
For a side-by-side view of the two services, see the 2Captcha alternative comparison. The Cloudflare Turnstile solver page has complete samples in every supported language.