Skip to content
ZeroCaptcha

Migrate a createTask client

Clients written for CapSolver’s or Anti-Captcha’s JSON API call createTask, then getTaskResult until the task is ready. ZeroCaptcha answers the same calls, with the same shapes, for Cloudflare Turnstile and Cloudflare challenge pages. The change is the host and the key, plus a look at the field names your client sends.

ZeroCaptcha is not affiliated with CapSolver or Anti-Captcha. This guide names them 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 that your code keeps task IDs as text: ZeroCaptcha’s are UUIDs.
  3. Check the task types you send. ZeroCaptcha takes TurnstileTaskProxyless, TurnstileTask, CloudflareChallengeTask, and the same names with CapSolver’s Anti prefix (AntiTurnstileTaskProxyLess, AntiTurnstileTask and AntiCloudflareTask), in any case. Any other type is ERROR_TASK_NOT_SUPPORTED.

The task stays as your client sends it, with the widget’s action and cData in metadata: many sites check both when they verify the token, so keep sending them. See action and cData. An Idempotency-Key header, new to most of these clients, makes a retried create return the same task.

Terminal window
# Before: https://api.capsolver.com/createTask or https://api.anti-captcha.com/createTask
# After. metadata holds 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.
curl "$ZEROCAPTCHA_API/createTask" -H "Content-Type: application/json" -H "Idempotency-Key: $(uuidgen)" \
-d "{\"clientKey\": \"$ZEROCAPTCHA_KEY\", \"task\": {\"type\": \"AntiTurnstileTaskProxyLess\",
\"websiteURL\": \"https://shop.example.com/login\", \"websiteKey\": \"0x4AAAAAAAB1cD2eF3gH4iJ5\",
\"metadata\": {\"action\": \"login\", \"cdata\": \"session-7f3a9c2e\"}}}"

getTaskResult and getBalance move the same way: the same bodies, on ZeroCaptcha’s host. 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.

ZeroCaptcha reads the spellings these clients send, and ignores fields it does not use, so a field under a name it does not know is silently left out. Check yours against these:

What Names ZeroCaptcha reads
The page websiteURL, websiteUrl
The site key websiteKey
The action action, pageAction, metadata.action
The cData cdata, cData, data, turnstileCData, metadata.cdata (or metadata.cData)
A proxy proxy as a URL, or proxyType, proxyAddress, proxyPort, proxyLogin, proxyPassword
A callback callbackUrl, beside task

Each of these is read as the clients send it, Anti-Captcha’s cData included. A cData under any other name is left out, and the site may then refuse the token.

CapMonster Cloud’s clients send pageAction and data, both read. Its cloudflareTaskType may be token or left out; its cf_clearance mode is refused with ERROR_TASK_NOT_SUPPORTED, as the clearance would be tied to a user agent the client did not choose. Use CloudflareChallengeTask with your proxy instead: its reply gives the clearance and the user agent to send it with.

  • A created task: {"errorId": 0, "taskId": "…"}.
  • While it runs: {"errorId": 0, "status": "processing"}.
  • Solved: status: "ready", solution.token, and cost, createTime, endTime, solveCount and expiresAt. A challenge page’s solution also has userAgent and cookies.cf_clearance, as CapSolver’s AntiCloudflareTask answers.
  • Failed: errorId: 1 with errorCode, such as ERROR_CAPTCHA_UNSOLVABLE, and nothing charged.
  • Balance: {"errorId": 0, "balance": 12.3456}, in US dollars.
  • Reports: reportIncorrect, reportCorrect, Anti-Captcha’s reportIncorrectRecaptcha and reportCorrectRecaptcha, and CapSolver’s feedbackTask answer {"errorId": 0, "status": "success"}. Each is recorded for our staff and refunds nothing, as every charge is final.

Every reply is HTTP 200; a failure is errorId: 1. See createTask format for every field and the errors reference for every code.

  • Proxies: http and https only; SOCKS is not supported yet. A challenge page always needs your proxy: there is no proxyless challenge task.
  • Errors: ERROR_RATE_LIMIT asks you to slow your polling; ERROR_NO_SLOT_AVAILABLE means your account’s share of the queue is full for a moment. Both come with a wait: see Errors and retries.
  • Money: prepaid US dollars, charged only when a task is solved. See pricing.
  • Idempotency: send an Idempotency-Key header with each createTask, so a retry after a lost reply returns the first task instead of creating a second.

Roll it out one service at a time, with a key of its own and a daily spend cap, and watch its tasks in the dashboard.