# 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.

- Source: https://zerocaptcha.io/guides/captcha-api-error-codes
- Published: 2026-09-30
- Updated: 2026-10-01
- Author: ZeroCaptcha Engineering

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:

```json
{
  "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](https://zerocaptcha.io/guides/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](https://zerocaptcha.io/docs/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](https://zerocaptcha.io/guides/secure-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](https://zerocaptcha.io/guides/find-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

```python
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](https://zerocaptcha.io/docs/reference/errors), and each code has its own anchor,
such as [ERROR_ZERO_BALANCE](https://zerocaptcha.io/docs/reference/errors#ERROR_ZERO_BALANCE). The
[Cloudflare Turnstile solver](https://zerocaptcha.io/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.
