Skip to content

API

Captcha API Error Codes: What Each Means and What It Costs

ERROR_CAPTCHA_UNSOLVABLE, ERROR_ZERO_BALANCE, ERROR_KEY_DOES_NOT_EXIST and the rest: what each captcha API error means, whether to retry, and what it costs.

4 min readPublished Updated

Every error from a CAPTCHA-solving API answers three questions: what went wrong, whether trying again helps, and whether it cost you anything. This guide groups ZeroCaptcha’s error codes by those questions, so your code can handle each group the same way. The codes are the ones clients of the createTask format already know; the REST API uses lowercase equivalents with the same meaning.

How errors arrive

In the compatible format, every reply is HTTP 200, and an error looks like this:

{
"errorId": 1,
"errorCode": "ERROR_ZERO_BALANCE",
"errorDescription": "Your balance cannot cover this task. Add funds and try again."
}

Branch on errorCode, never on the description, which may be reworded. The REST API answers with an HTTP error status and an RFC 9457 problem document whose code field plays the same role. The 2Captcha format puts the code in place of the result, such as ERROR_ZERO_BALANCE.

Group 1: wait and retry

These say “not now”. Retry the same request after the time in the Retry-After header, or after a short pause that doubles each time. For createTask, keep the same Idempotency-Key so a retry never makes a second task.

Code Meaning
ERROR_RATE_LIMIT Too many getTaskResult or getBalance calls; poll less often
ERROR_NO_SLOT_AVAILABLE Your share of the queue is full for a moment
ERROR_SERVICE_UNAVAILABLE The API could not serve the request just now
ERROR_IDEMPOTENCY_KEY_IN_USE The first request with this key is still being served

HTTP 429 and any 5xx status belong here too. Rate limits and concurrency covers pacing in detail.

Group 2: fix the request or the account

Retrying these unchanged gets the same answer. Each costs nothing, because no task was created.

Code What to do
ERROR_KEY_DOES_NOT_EXIST The key is wrong or incomplete; copy it again from the dashboard
ERROR_KEY_REVOKED The key was revoked, or its rotation overlap ended; use the new key
ERROR_IP_NOT_ALLOWED Add this server’s address to the key’s allowlist
ERROR_ACCESS_DENIED The key lacks the tasks or balance scope
ERROR_ZERO_BALANCE Add funds, then send the task again
ERROR_SPEND_CAP_REACHED The key’s daily cap is reached; raise it or wait for 00:00 UTC
ERROR_TASK_ABSENT The body has no task or no type
ERROR_TASK_NOT_SUPPORTED The task type is not one ZeroCaptcha solves
ERROR_INVALID_TASK_DATA A field is missing or invalid; the description names it
ERROR_IDEMPOTENCY_KEY_REUSED This key was used for a different task; use a new key
ERROR_DOMAIN_BLOCKED The site is on the blocklist; do not send tasks for it
ERROR_ACCOUNT_SUSPENDED The account is suspended; appeal from the dashboard

In the 2Captcha format, ERROR_PAGEURL means pageurl is missing or not a public page, and ERROR_PROXY_FORMAT means the proxy is not in a supported form. Secure your captcha API keys explains allowlists, scopes and spend caps.

Group 3: the task ran and failed

These come from getTaskResult after the task has run. The price held for the task goes back to your balance at once: nothing is charged.

Code Meaning
ERROR_CAPTCHA_UNSOLVABLE Every attempt to solve the challenge failed
ERROR_TASK_TIMEOUT The task was not solved before its deadline
ERROR_PROXY_NOT_ALLOWED The proxy points at a private or reserved address, such as 10.0.0.0/8
ERROR_BAD_PROXY The same, in the 2Captcha format

A new task may succeed. If ERROR_CAPTCHA_UNSOLVABLE repeats on the same page, check the sitekey, the URL, and the action and cData first: see Find a Cloudflare Turnstile sitekey.

Group 4: solved, but too late

ERROR_TOKEN_EXPIRED means the task was solved and charged, but you read it after its token had expired. A Turnstile token works once, for 300 seconds. This is the one error that costs money, and the fix is in your pipeline: use each token as soon as it is ready.

A handler in a few lines

RETRY = {"ERROR_RATE_LIMIT", "ERROR_NO_SLOT_AVAILABLE",
"ERROR_SERVICE_UNAVAILABLE", "ERROR_IDEMPOTENCY_KEY_IN_USE"}
TASK_FAILED = {"ERROR_CAPTCHA_UNSOLVABLE", "ERROR_TASK_TIMEOUT"}
def classify(code: str) -> str:
if code in RETRY:
return "retry-same-request"
if code in TASK_FAILED:
return "new-task" # nothing was charged
if code == "ERROR_TOKEN_EXPIRED":
return "new-task-faster" # charged; use tokens sooner
return "stop-and-fix" # nothing was charged

The full list

Every code in all three formats, with its HTTP status, whether a retry helps, what to do and what it costs, is in the errors reference, and each code has its own anchor, such as ERROR_ZERO_BALANCE. The Cloudflare Turnstile solver page shows the calls these errors come from.

Questions

Am I charged for ERROR_CAPTCHA_UNSOLVABLE?

No. A task that fails or times out releases the price held for it, so it costs nothing. Only a task whose token is ready is charged.

What does ERROR_ZERO_BALANCE mean if I still have money?

Your available balance is what is left after prices held for tasks still running. If many tasks are in flight, the available balance can be lower than the total.

Which errors should my code retry automatically?

HTTP 429 and 5xx, ERROR_RATE_LIMIT, ERROR_SERVICE_UNAVAILABLE, ERROR_NO_SLOT_AVAILABLE and ERROR_IDEMPOTENCY_KEY_IN_USE, waiting as Retry-After asks. The others need a change first.

Read next

This guide is part of the Cloudflare Turnstile solver hub. Every task is charged only when a token is ready.

Get an API key