API
createTask and getTaskResult: The Captcha API Format Explained
How the createTask, getTaskResult and getBalance format works: request bodies, replies, errorId, polling, and ZeroCaptcha's Cloudflare Turnstile tasks.
3 min readPublished Updated
createTask and getTaskResult are the most widely used request format among CAPTCHA-solving
services. You create a task with one JSON call, get a task ID back at once, then ask for the
result until it is ready. ZeroCaptcha implements this format for Cloudflare Turnstile and
Cloudflare challenge pages, so clients
written for it work after changing the host and the key. This guide explains each call, the
replies, and the conventions that trip people up.
The three calls
All three are POST requests with a JSON body to the API host, and all three carry your key in
the body as clientKey:
| Call | Body | Reply |
|---|---|---|
/createTask |
clientKey, task |
errorId, taskId |
/getTaskResult |
clientKey, taskId |
errorId, status, and solution once ready |
/getBalance |
clientKey |
errorId, balance |
Creating a task
# 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. The Idempotency-Key makes a retried# create return the same task.curl -s "$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"} } }'{ "errorId": 0, "taskId": "0192f3a4-7b1c-7d2e-9f10-3c4d5e6f7a8b" }The task object describes the challenge. For Turnstile:
type:TurnstileTaskProxyless, orTurnstileTaskto solve through your own proxy. The aliasesAntiTurnstileTaskProxyLessandAntiTurnstileTaskwork too.websiteURL(orwebsiteUrl) andwebsiteKey: the page and the widget’s sitekey.actionandcdata: when the widget sets them. See Cloudflare Turnstile action and cData.- Proxy fields, for
TurnstileTask: see Solve Cloudflare Turnstile with a proxy.
Fields the task does not use, such as userAgent, are accepted and ignored, so a client that
sends extras still works. The task’s price is held on your balance when it is created.
Polling for the result
curl -s "$ZEROCAPTCHA_API/getTaskResult" \ -H "Content-Type: application/json" \ -d '{"clientKey": "'"$ZEROCAPTCHA_KEY"'", "taskId": "0192f3a4-7b1c-7d2e-9f10-3c4d5e6f7a8b"}'While the task runs, the reply is:
{ "errorId": 0, "taskId": "0192f3a4-7b1c-7d2e-9f10-3c4d5e6f7a8b", "status": "processing" }When it is solved:
{ "errorId": 0, "taskId": "0192f3a4-7b1c-7d2e-9f10-3c4d5e6f7a8b", "status": "ready", "solution": { "token": "0.xT4…", "type": "turnstile" }, "cost": "0.000800", "createTime": 1790762400, "endTime": 1790762404, "solveCount": 1, "expiresAt": "2026-09-30T10:05:04Z"}cost is what the task cost in US dollars, as a string with six decimals. expiresAt says when the token stops working: Turnstile tokens are valid for 300
seconds and work once. If the task failed, the reply has errorId 1 and an errorCode such as
ERROR_CAPTCHA_UNSOLVABLE, and nothing is charged.
The conventions
- Every reply is HTTP 200. Success or failure is in
errorId: 0 for success, 1 for an error witherrorCodeanderrorDescription. Only failures outside the format, such as a body over the size limit, answer with an HTTP error. - Task IDs are strings. ZeroCaptcha’s task IDs are UUIDs. A client that keeps the ID as text passes it back unchanged; one that parses it as a number needs that changed.
- The body is JSON whatever the Content-Type. Some clients send JSON as
text/plain; that works. - Poll every one or two seconds.
getTaskResultandgetBalanceshare a budget; calling them far faster is answered withERROR_RATE_LIMITand aRetry-Afterheader.
Retrying createTask safely
A lost reply to createTask leaves you unsure whether the task exists. Send an Idempotency-Key
header with every createTask: the same key and body within 24 hours returns the first task
instead of making a second. Idempotency keys for captcha tasks
shows the pattern.
Callbacks instead of polling
Add callbackUrl beside task, and ZeroCaptcha posts the getTaskResult reply to that URL when
the task ends, signed so you can check it. Polling still works alongside it. See
Captcha solver callbacks.
The other two formats
The same tasks, prices and charges are available two other ways:
- 2Captcha’s
in.phpandres.php, for clients written for that API: see the 2Captcha format. - REST v1, with
POST /v1/tasks, a bearer key, anIdempotency-Keyheader and RFC 9457 problem details: see the Tasks API reference.
The compatible format reference documents every field, and the Cloudflare Turnstile solver page shows a complete program in each supported language.