Skip to content
ZeroCaptcha

createTask format

ZeroCaptcha speaks the createTask format that CapSolver, Anti-Captcha and 2Captcha’s JSON API use, so a client written for one of them solves Turnstile and Cloudflare challenge pages here after two changes: its base URL, to our API’s address, and its key, to your ZeroCaptcha key. A task made this way is priced, held and charged exactly as one made with REST.

ZeroCaptcha is not affiliated with CapSolver, Anti-Captcha or 2Captcha. Their names appear here only to say which format this is.

Call Body Reply
POST /createTask {"clientKey": "…", "task": {…}}, and optionally callbackUrl {"errorId": 0, "taskId": "…"}
POST /getTaskResult {"clientKey": "…", "taskId": "…"} processing, then ready with the solution
POST /getBalance {"clientKey": "…"} {"errorId": 0, "balance": 12.3456}
POST /reportIncorrect, POST /reportCorrect {"clientKey": "…", "taskId": "…"} {"errorId": 0, "status": "success"}
POST /reportIncorrectRecaptcha, POST /reportCorrectRecaptcha The same, as Anti-Captcha’s clients send it The same
POST /feedbackTask {"clientKey": "…", "taskId": "…", "result": {"invalid": true}}, as CapSolver’s clients send it The same
  • Every reply is HTTP 200. Success is errorId: 0; a failure is errorId: 1 with errorCode and errorDescription. Only a failure outside the format, such as a body over 64 KiB, a server timeout or the service shedding load, answers with an HTTP error and a problem document, so check the status too.
  • The body is read leniently, as these clients send it: JSON whatever the Content-Type (some send text/plain), a number wherever text is expected, null for an absent field, and fields it does not use are ignored.
  • Idempotency-Key works on createTask as on REST: send the same header again within 24 hours and you get the first task back instead of a second one.
  • clientKey is your API key, zc_live_…, 41 characters.
Field Required Other spellings What it is
type Yes TurnstileTaskProxyless, or TurnstileTask through your proxy; CapSolver’s AntiTurnstileTaskProxyLess too, and AntiTurnstileTask for the proxy variant. Case does not matter.
websiteURL Yes websiteUrl The page with the widget.
websiteKey Yes The widget’s site key.
action When the widget sets one pageAction (CapMonster Cloud’s), metadata.action The widget’s action: its data-action, or the action option of turnstile.render().
cdata When the widget sets one cData, data, turnstileCData, metadata.cdata, metadata.cData The widget’s cData: its data-cdata, or the cData option of turnstile.render().
proxy With TurnstileTask the proxyAddress fields Your proxy as a URL: http://user:pass@proxy.example.net:8080.
proxyType, proxyAddress, proxyPort, proxyLogin, proxyPassword Instead of proxy Your proxy in parts: proxyType http (the default) or https, a public host, a port (a number or a string of digits), and an optional login and password of at most 255 bytes each.
cloudflareTaskType No CapMonster Cloud’s mode: token, or absent, for the widget’s token. Its cf_clearance and wait_room modes are refused with ERROR_TASK_NOT_SUPPORTED, before anything is made or charged: for a challenge page’s clearance, use the challenge page task.

Most createTask clients send the action and cData nested in the task’s metadata, as "metadata": {"action": "login", "cdata": "session-7f3a9c2e"}, and the samples below do too. Many sites check both when they verify the token, so send them whenever the widget sets them: see Cloudflare Turnstile action and cData.

Where a field has more than one spelling, the first one sent wins, in the order listed. The limits are REST’s: see Solving Cloudflare Turnstile. SOCKS proxies are not supported yet.

Field Required What it is
type Yes CloudflareChallengeTask, or CapSolver’s AntiCloudflareTask.
websiteURL or websiteUrl Yes The page behind the challenge.
proxy, or the proxyAddress fields Yes Your proxy: the clearance works only from its address.

A websiteKey, action or cdata is ignored, as are fields other providers take for a challenge page, such as userAgent and html. A proxyless challenge task, such as CloudflareChallengeTaskProxyless or AntiCloudflareTaskProxyLess, is refused with ERROR_TASK_NOT_SUPPORTED. See Cloudflare WAF and 5-second challenges.

While the task runs:

{ "errorId": 0, "taskId": "0192f3a4-7b1c-7d2e-9f10-3c4d5e6f7a8b", "status": "processing" }

Solved, a Turnstile task:

{
"errorId": 0,
"taskId": "0192f3a4-7b1c-7d2e-9f10-3c4d5e6f7a8b",
"status": "ready",
"solution": { "token": "0.Zm9vYmFy…", "type": "turnstile" },
"cost": "0.000800",
"createTime": 1790776925,
"endTime": 1790776934,
"solveCount": 1,
"expiresAt": "2026-09-30T14:07:14Z"
}

Solved, a challenge page: solution has "type": "cloudflare", userAgent, and "cookies": {"cf_clearance": "…"} beside token, as CapSolver’s AntiCloudflareTask answers.

Failed, or not solved in time (nothing is charged):

{
"errorId": 1,
"errorCode": "ERROR_CAPTCHA_UNSOLVABLE",
"errorDescription": "Every attempt to solve the challenge failed. Nothing was charged.",
"taskId": "0192f3a4-7b1c-7d2e-9f10-3c4d5e6f7a8b",
"status": "failed",
"cost": "0.000000"
}

Solved, but read after its token expired: errorId: 1, ERROR_TOKEN_EXPIRED, "status": "ready" and the cost it was charged. Use tokens as soon as they are ready.

Field Meaning
status processing until the task ends, then ready; failed on an error reply for a task that did not succeed
solution.token The Turnstile token, or the cf_clearance cookie’s value
expiresAt When the token stops being accepted, in UTC
cost What the task cost, in US dollars with six decimals
createTime, endTime When it was created and solved, in Unix seconds
solveCount The solve attempts it took
Terminal window
# 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. For your own proxy, make the type
# TurnstileTask and add "proxy": "http://user:pass@proxy.example.net:8080" to the task; to be
# called when it ends, add "callbackUrl": "https://hooks.example.com/zerocaptcha" beside it.
reply=$(curl -sS "$ZEROCAPTCHA_API/createTask" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d "{\"clientKey\": \"$ZEROCAPTCHA_KEY\", \"task\": {\"type\": \"TurnstileTaskProxyless\",
\"websiteURL\": \"https://example.com/login\", \"websiteKey\": \"0x4AAAAAAAB1cD2eF3gH4iJ5\",
\"metadata\": {\"action\": \"login\", \"cdata\": \"session-7f3a9c2e\"}}}")
# errorId 1 is a refusal; its errorCode and errorDescription say why.
if [ "$(jq -r .errorId <<<"$reply")" != 0 ]; then echo "$reply" >&2; exit 1; fi
TASK_ID=$(jq -r .taskId <<<"$reply")
# Every 2 seconds, until "status" is ready, or errorId 1 says the task failed:
curl "$ZEROCAPTCHA_API/getTaskResult" -H "Content-Type: application/json" \
-d "{\"clientKey\": \"$ZEROCAPTCHA_KEY\", \"taskId\": \"$TASK_ID\"}"

A report says whether the site took a solved task’s token: reportIncorrect (or Anti-Captcha’s reportIncorrectRecaptcha, or CapSolver’s feedbackTask with "invalid": true) that it refused it, and reportCorrect (or reportCorrectRecaptcha, or "invalid": false) that it took it. Each is recorded against the task, where our staff read it to find sites and settings that fail.

Nothing is refunded: a task is charged only when it is solved, and every charge is final. A task takes one report: a second is ERROR_DUPLICATE_REPORT, and a report of a task that was not solved is ERROR_REPORT_NOT_RECORDED. A key needs tasks:write to report.

Every errorCode of this format, with whether a retry helps and what it costs, is in the errors reference, and a task’s own failures under task outcomes. The ones clients meet most:

Code What to do
ERROR_KEY_DOES_NOT_EXIST, ERROR_KEY_REVOKED Use a working key from the dashboard.
ERROR_ZERO_BALANCE Add funds, then create the task again.
ERROR_TASK_NOT_SUPPORTED, ERROR_INVALID_TASK_DATA Fix the task as errorDescription says.
ERROR_NO_SLOT_AVAILABLE, ERROR_RATE_LIMIT Wait a few seconds (or Retry-After), then retry.
ERROR_CAPTCHA_UNSOLVABLE, ERROR_TASK_TIMEOUT The task failed and cost nothing: create a new one.
ERROR_TOKEN_EXPIRED The task was solved and charged; create a new one and use its token at once.
ERROR_NO_SUCH_CAPCHA_ID Poll with the taskId createTask gave, with a key of the same account.
  • Task IDs are ZeroCaptcha’s own, UUIDs such as 0192f3a4-7b1c-7d2e-9f10-3c4d5e6f7a8b, not numbers. A client that keeps the ID as text passes it back unchanged.
  • Only Turnstile and Cloudflare challenge pages are offered; other task types are refused with ERROR_TASK_NOT_SUPPORTED.
  • callbackUrl beside task names a callback, signed so you can check it.
  • There is no free trial or test key: every task is real, and charged only when it is solved.