# Errors

> Error codes of the Noptcha API: v1 problem details, task failure codes and compatibility API error codes.

Source: https://noptcha.com/docs/errors/

There are two kinds of errors. A **request error** means the request was rejected: no task was created and nothing was charged. A **task failure** means the task was created but could not be solved: it ends with `status: "failed"` and is not charged. Use the codes in programs; messages may change. New codes can be added at any time ([Versioning](https://noptcha.com/docs/versioning.md)).

## Request errors (v1)

The native API returns errors as RFC 9457 problem details (`application/problem+json`). `type` is`https://noptcha.com/docs/errors/<code>`; every response carries `request_id` (also in the`Noptcha-Request-Id` header).

```json
{
  "type": "https://noptcha.com/docs/errors/insufficient_balance",
  "title": "Insufficient balance",
  "status": 402,
  "code": "insufficient_balance",
  "detail": "Available $0.000300, task price $0.000900.",
  "request_id": "req_…"
}
```

| code | HTTP | When |
| --- | --- | --- |
| [`invalid_request`](https://noptcha.com/docs/errors/invalid_request.md) | 400 | malformed body, missing field, bad parameter, `callback_url` not a string |
| [`unsupported_type`](https://noptcha.com/docs/errors/unsupported_type.md) | 400 | unknown or unavailable task type |
| [`unauthorized`](https://noptcha.com/docs/errors/unauthorized.md) | 401 | invalid, revoked or expired key |
| [`insufficient_balance`](https://noptcha.com/docs/errors/insufficient_balance.md) | 402 | balance too low for the task's price |
| [`budget_exceeded`](https://noptcha.com/docs/errors/budget_exceeded.md) | 402 | the key's budget for the period is used up |
| [`forbidden`](https://noptcha.com/docs/errors/forbidden.md) | 403 | missing scope, IP not allowed, type not allowed, organization suspended |
| [`not_found`](https://noptcha.com/docs/errors/not_found.md) | 404 | unknown endpoint or method; unknown, expired or foreign task; expired idempotent task |
| [`idempotency_conflict`](https://noptcha.com/docs/errors/idempotency_conflict.md) | 409 | same `Idempotency-Key` with another body, or still in progress |
| [`task_not_solved`](https://noptcha.com/docs/errors/task_not_solved.md) | 409 | feedback for a task that is still processing or failed |
| [`request_too_large`](https://noptcha.com/docs/errors/request_too_large.md) | 413 | body over the limit |
| [`invalid_params`](https://noptcha.com/docs/errors/invalid_params.md) | 422 | `params` or `metadata` do not match the schema, or `callback_url` is not allowed |
| [`rate_limited`](https://noptcha.com/docs/errors/rate_limited.md) | 429 | over a rate limit, or IP blocked after invalid keys |
| [`concurrency_limited`](https://noptcha.com/docs/errors/concurrency_limited.md) | 429 | too many tasks in flight |
| [`internal`](https://noptcha.com/docs/errors/internal.md) | 500 | our error |
| [`service_unavailable`](https://noptcha.com/docs/errors/service_unavailable.md) | 503 | no capacity or a dependency is down |

`422 invalid_params` adds `errors[]` with one `{pointer, message}` per problem (at most 50, sorted by pointer; `detail` then ends with “and N more errors”); problems with an image also carry a `reason` (`image_too_large`, `image_format`, `image_base64`, `image_empty`; see [Images](https://noptcha.com/docs/limits.md#images)).

## Task failures

In the native API a failed task has `status: "failed"` and `error: {code, message}`, with a cost of zero:

| error.code | Meaning |
| --- | --- |
| `unsolvable` | the captcha could not be solved (also when no solver accepts these parameters) |
| `timeout` | not solved before the type's deadline |
| `proxy_error` | the proxy could not be used |
| `invalid_site` | the site key or domain is invalid |
| `invalid_image` | the image is empty, too big or unreadable |
| `cancelled` | the task was cancelled |

In the compatibility API a failed task is reported by `getTaskResult` with `errorId: 1` and an error code such as`ERROR_CAPTCHA_UNSOLVABLE` or one of the proxy codes below.

## Compatibility API

Every response is HTTP 200; `errorId` is 0 on success and 1 on error, with `errorCode` and`errorDescription`. The codes are the anti-captcha compatible ones:

| errorCode | When |
| --- | --- |
| `ERROR_KEY_DOES_NOT_EXIST` | key malformed, unknown, revoked or expired; or the key lacks the scope this endpoint needs |
| `ERROR_ZERO_BALANCE` | balance too low, or the key's budget is used up |
| `ERROR_IP_NOT_ALLOWED` | client IP not in the key's allowlist |
| `ERROR_IP_BLOCKED` | too many invalid keys from this IP |
| `ERROR_ACCOUNT_SUSPENDED` | the organization is suspended |
| `ERROR_NO_SLOT_AVAILABLE` | no capacity, concurrency limit, create rate limit (also sandbox limits), temporary or internal error; retry later |
| `ERROR_TASK_NOT_SUPPORTED` | unknown task type name, or type not allowed for the key |
| `ERROR_TASK_ABSENT` | `task` missing or not an object (or the body could not be read) |
| `ERROR_NO_SUCH_CAPCHA_ID` | `taskId` missing, unknown, expired or of another organization; report for an unsolved task |
| `ERROR_INCORRECT_SESSION_DATA` | a parameter does not match the schema (`errorDescription` names it), or `callbackUrl` is not allowed |
| `ERROR_RECAPTCHA_INVALID_SITEKEY` | the site key is invalid (parameter check or solver) |
| `ERROR_RECAPTCHA_INVALID_DOMAIN` | the website URL, API domain or subdomain is invalid or not allowed |
| `ERROR_ZERO_CAPTCHA_FILESIZE` | the image is missing or empty |
| `ERROR_TOO_BIG_CAPTCHA_FILESIZE` | the image (characters or pixels) or the request body is too large |
| `ERROR_IMAGE_TYPE_NOT_SUPPORTED` | the image is not valid base64, not a PNG, JPEG, GIF, WebP or BMP image, or malformed or truncated (checked when the task is created); or the solver could not read it (task failed) |
| `ERROR_CAPTCHA_UNSOLVABLE` | the task failed: unsolvable, timed out, or no solver accepts these parameters |
| `ERROR_PROXY_CONNECT_REFUSED` `ERROR_PROXY_CONNECT_TIMEOUT` `ERROR_PROXY_READ_TIMEOUT` `ERROR_PROXY_BANNED` `ERROR_PROXY_TRANSPARENT` `ERROR_PROXY_HAS_NO_IMAGE_SUPPORT` `ERROR_PROXY_INCOMPATIBLE_HTTP_VERSION` | the proxy could not be used (task failed) |
| `ERROR_TOKEN_EXPIRED` | the solver reported the token expired (task failed) |

Two responses come from the infrastructure rather than the protocol: HTTP 403 (problem details, `forbidden`) when a request does not pass through our edge network and HTTP 500 (`internal`). Treat both as transient. The 2captcha legacy API has its own codes, see [2captcha legacy API](https://noptcha.com/docs/2captcha-api.md#errors).

## What to retry

-   **Retry after a wait**: `rate_limited`, `concurrency_limited`, `service_unavailable`, `internal`; `ERROR_NO_SLOT_AVAILABLE`. Honour `Retry-After` when present.
-   **Fix first**: everything else. Retrying an invalid request unchanged gives the same error.
-   **Failed tasks** are not charged; you may create a new task for the same captcha.
-   For `POST /v1/tasks`, send an `Idempotency-Key` so that a retry after a network error cannot create a second task ([Idempotency](https://noptcha.com/docs/native-api/tasks.md#idempotency)).
