Errors and Retries
Every error code the API returns, what it means, and whether to retry
Every answer of /createTask and /getTaskResult carries an errorId. 0 means success; any other value comes with an errorCode and an errorDescription:
{
"errorId": 1,
"errorCode": "ERROR_INVALID_TASK_DATA",
"errorDescription": "websiteKey is required for TurnstileTaskProxyLess"
}Catch on errorCode, never on the description: the description is for your logs and can gain context (a bad field name, a proxy status).
Codes
| Code | errorId | What it means | Retry? |
|---|---|---|---|
ERROR_KEY_DOES_NOT_EXIST | 1 | The clientKey is unknown or revoked | No |
ERROR_ZERO_BALANCE | 1 | Not enough balance for this task. Nothing was reserved | After a top-up |
ERROR_INVALID_DEVELOPER_KEY | 1 | The developerKey is invalid or disabled | No, drop it |
ERROR_INVALID_TASK_DATA | 1 | A field is missing or malformed, or the sitekey does not match the page | No, fix the request |
ERROR_PROXY_NOT_DEFINED | 1 | A non-ProxyLess task without task.proxy | No, add a proxy or use the ProxyLess type |
ERROR_PROXY_FORMAT | 1 | The proxy is not one clean token (whitespace, socks, a whole line from a list) | No, fix the string |
ERROR_PROXY_CONNECTION_FAILED | 1 | Your proxy refused or could not reach the target | Not on the same proxy line |
ERROR_PROXY_BANNED | 1 | The target refuses your proxy address (403, or a 429/451/5xx with no challenge) | Not on the same proxy line |
ERROR_BLOCKED_TARGET | 1 | websiteURL or the proxy host is, or resolves to, a private or reserved address | No |
ERROR_TASK_TYPE_INACTIVE | 1 | The task type is not enabled on your key | No, ask us to grant it |
ERROR_TASK_TYPE_COMING_SOON | 1 | The task type is announced but not open | No |
ERROR_WRONG_TASK_TYPE | 1 | Right site, wrong type: a standard sitekey sent to an Enterprise type (or the reverse) | No, fix the type |
ERROR_CAPTCHA_UNSOLVABLE | 12 | Every attempt was rejected by the site, or an interactive step could not be completed | Yes |
ERROR_TIMEOUT | 12 | The solve did not finish inside its budget | Yes |
ERROR_TASK_QUEUE_FULL | 2 | The queue is too long: the task would wait too long, so it was refused at submission | Yes, after a delay |
ERROR_TASK_NOT_FOUND | 16 | The taskId is unknown or its result expired (10 minutes) | No, the result is gone |
ERROR_INTERNAL | 1 | Our side failed | Yes |
Payload API errors use a different shape ({ "success": false, "error": { "code", "retryable" } }) and are documented on that page.
Retry Policy
- Retry
ERROR_CAPTCHA_UNSOLVABLE,ERROR_TIMEOUT,ERROR_TASK_QUEUE_FULLandERROR_INTERNAL, with the same request and the sametaskIdwhere one exists. A second attempt succeeds often enough to be worth it; three attempts in a row failing on the same site means something else is wrong. - Back off on
ERROR_TASK_QUEUE_FULL: a few seconds at first, then double. It is a capacity signal, not a transient hiccup. - Never retry on the same proxy line after
ERROR_PROXY_CONNECTION_FAILEDorERROR_PROXY_BANNED: a customer proxy is not rotated for you, so the second attempt fails the same way. Use another line, or a residential one. - Fix, do not retry the codes marked No: they come from the request or the account.
Billing
A task refused at submission (balance, task data, proxy format, queue full) never reserves anything. A task accepted and then failed is refunded automatically, whatever the code: you pay for solved tasks only.
The refund is written when the task fails, so a balance read immediately after an error may still show the reservation. It is released by the same process that failed the task; the reconciler sweeps anything left behind.