Skip to content
ZeroCaptcha

Migrate a 2Captcha client

Code that solves Cloudflare Turnstile through 2Captcha moves to ZeroCaptcha without a rewrite: ZeroCaptcha serves both of the formats 2Captcha documents for Turnstile, in.php and res.php, and the JSON createTask format. In most cases the change is the host and the key.

ZeroCaptcha is not affiliated with 2Captcha. This guide names it only to show what to change.

  1. Sign up, create a key and add funds. Keep the key in your environment, as ZEROCAPTCHA_KEY, and the API’s address as ZEROCAPTCHA_API.
  2. Check how your code keeps task IDs. in.php answers numbers, as 2Captcha does, such as 10000004821. The createTask format answers UUIDs, such as 0192f3a4-7b1c-7d2e-9f10-3c4d5e6f7a8b, so code that uses it must keep the ID as text.
  3. Check what your code asks for: ZeroCaptcha serves method=turnstile only, and challenge pages through the createTask format or REST.

Your 2Captcha balance does not move: ZeroCaptcha is prepaid separately, in US dollars.

The host and the key change; the parameters and replies stay. Keep sending the widget’s action and cData as action and data, as 2Captcha documents them: many sites check both when they verify the token. See action and cData.

Terminal window
# action and data are the widget's data-action and data-cdata, or the action and cData options of
# turnstile.render(); leave out any the widget does not set.
# Before
curl "https://2captcha.com/in.php?key=$TWOCAPTCHA_KEY&method=turnstile&sitekey=0x4AAAAAAAB1cD2eF3gH4iJ5&pageurl=https://shop.example.com/login&action=login&data=session-7f3a9c2e&json=1"
# After, with an Idempotency-Key so a retried submit returns the same task:
curl -H "Idempotency-Key: $(uuidgen)" \
"$ZEROCAPTCHA_API/in.php?key=$ZEROCAPTCHA_KEY&method=turnstile&sitekey=0x4AAAAAAAB1cD2eF3gH4iJ5&pageurl=https://shop.example.com/login&action=login&data=session-7f3a9c2e&json=1"

Polling res.php?action=get&id=… is the same: CAPCHA_NOT_READY, then OK|<token> or an error code. 2Captcha format lists every parameter and code.

If you use a client library, point it at the API’s address if it lets you set the host; if you are not sure it does, call the API over HTTP as above.

2Captcha’s JSON API moves the same way: post the same body to /createTask and /getTaskResult on ZeroCaptcha’s host, with your ZeroCaptcha key as clientKey. The samples send the widget’s action and cData in the task’s metadata, as most createTask clients do; a 2Captcha client that sends them as action and data works unchanged.

Terminal window
# Before: https://api.2captcha.com/createTask with your 2Captcha key as clientKey.
# After, with the widget's data-action and data-cdata (or turnstile.render()'s action and cData) in
# metadata, and an Idempotency-Key so a retried create returns the same task:
curl "$ZEROCAPTCHA_API/createTask" -H "Content-Type: application/json" -H "Idempotency-Key: $(uuidgen)" \
-d "{\"clientKey\": \"$ZEROCAPTCHA_KEY\", \"task\": {\"type\": \"TurnstileTaskProxyless\",
\"websiteURL\": \"https://shop.example.com/login\", \"websiteKey\": \"0x4AAAAAAAB1cD2eF3gH4iJ5\",
\"metadata\": {\"action\": \"login\", \"cdata\": \"session-7f3a9c2e\"}}}"

The widget’s cData goes in data, cdata, cData, turnstileCData, metadata.cdata or metadata.cData, and its action in action, pageAction or metadata.action. A field under any other name is ignored, so check the names your code sends. See createTask format.

  • Task IDs are numbers in in.php and res.php, and UUIDs, kept as text, in the createTask format.
  • Pingbacks need no registration: any public URL works. Each call is signed; see Polling and callbacks to check it.
  • Reports: reportbad, reportgood and the createTask format’s reportIncorrect and reportCorrect are recorded for our staff and never refunded: every charge is final.
  • Not offered: CAPTCHA types other than Cloudflare Turnstile.
  • Money: balances and prices are in US dollars; getbalance answers the available balance, and a task is charged only when it is solved. See pricing.
  • Errors: most codes are 2Captcha’s own; a few are ZeroCaptcha’s, such as ERROR_SPEND_CAP_REACHED and ERROR_IDEMPOTENCY_KEY_REUSED. The 2Captcha format lists them all.
  1. Point one service, or a share of your traffic, at ZeroCaptcha with a key of its own and a daily spend cap.
  2. Watch its tasks in the dashboard’s task log and on the status page.
  3. Move the rest once it behaves, then retire the old keys.