Skip to content
CaptchAPI
Reference

Error codes

Every error the API returns, what it means, and what to do about it.

HTTP is always 200, including for errors. That is the anti-captcha contract and we keep it, so a client written for CapSolver does not need its error handling rewritten. Branch on errorId: 0 means success, 1 means read errorCode.

Error response shape
{
  "errorId": 1,
  "errorCode": "ERROR_KEY_DOES_NOT_EXIST",
  "errorDescription": "No API key matches that clientKey."
}
CodeMeaningWhat to do
ERROR_KEY_DOES_NOT_EXISTNo API key matches the clientKey you sent.Check for a copy-paste error or a stale environment variable. Keys are shown in full only once, at creation.
ERROR_ZERO_BALANCEYour wallet cannot cover the price of the task.Top up. Tasks already in flight are unaffected and are still refunded if they fail.
ERROR_TASK_TYPE_NOT_SUPPORTEDThe task.type value is not one we handle.Compare it against the task types reference. The value is case-insensitive but the spelling must match.
ERROR_NO_SUCH_TASKThat taskId does not exist, or does not belong to your key.Results are retained for 5 minutes after completion. Poll sooner, and never share a taskId across accounts.
ERROR_RATE_LIMITToo many requests in the current window.Back off and retry. The task itself is unaffected — keep the same taskId and keep polling.
ERROR_KEY_DISABLEDThe key exists but has been disabled.Re-enable it in the dashboard, or generate a new one. Keys are disabled by you, or by us after an acceptable-use investigation.
ERROR_UPSTREAMThe solver refused or crashed on this task.You have been refunded. Retry once; if it repeats on the same target, send us the sitekey and page URL.
ERROR_TIMEOUTThe task did not resolve within its deadline.You have been refunded. Hardened targets sometimes need a proxy or an exact User-Agent — try the proxy variant of the task type.
ERROR_PROXY_REQUIREDA DataDome task arrived without a proxy, or asked for a ProxyLess variant.Supply your proxy. DataDome binds the cookie to the exit IP, so a solve from any other address is worthless — and replaying it hard-bans that IP. There is no proxyless DataDome.
ERROR_IP_BANNEDThe captchaUrl you sent carries t=bv: DataDome has already banned that proxy IP and serves no CAPTCHA.Nothing is served, so nothing is charged. Rotate to a fresh proxy IP and read a new captchaUrl before retrying.

Solve outcome codes

The codes above come from the gateway — your key, your balance, your rate limit. When a solve itself fails, the solver's own code passes straight through. You are always refunded for these; the action column says whether retrying is worth it and, when the cause is your proxy, that it is yours to fix.

CodeMeaningWhat to do
CAPTCHA_UNSOLVABLEWe ran the solve but could not produce a valid token or cookie for this target.Refunded. Retry once; if it repeats on the same sitekey, send it to us — some targets are genuinely hard and worth tuning for.
TASK_TIMEOUTThe solve did not finish within its deadline.Refunded. Usually a slow or overloaded target; retry, and on a hardened site supply a residential proxy.
CHALLENGE_NOT_PRESENTFor a Cloudflare cookie task, the page served directly — there was no challenge to clear on this IP.Refunded, and nothing to do: the page is already reachable from that IP. If you expected a challenge, it fires from datacenter IPs, not clean residential ones.
PROXY_BANNEDThe target kept looping its Cloudflare challenge and never issued a token — this exit IP is refused by that site.Refunded. Retry with a different, higher-trust proxy (residential or mobile). No amount of retrying helps the same refused IP.
PROXY_CONNECTION_FAILEDWe could not open a connection through the proxy you supplied.Refunded. Check the proxy host, port and that it is up. This is your proxy, not the target.
PROXY_AUTH_FAILEDThe proxy rejected the credentials you supplied.Refunded. Check proxyLogin and proxyPassword.
PROXY_INCOMPATIBLEThe proxy could not carry the request — usually SOCKS-only, transparent, or a broken TLS certificate.Refunded. Use an HTTP(S) proxy that supports CONNECT tunnelling.
INVALID_SITEKEYThe websiteKey was rejected by the target — wrong, expired, or for a different domain.Refunded. Copy the sitekey from the page source of the exact URL you are solving.
INVALID_USERAGENTThe userAgent you sent is not a current browser User-Agent.Refunded. Send a real, recent browser UA, or omit the field and we use our own.
INVALID_TASK_DATAA field the task type requires is missing or malformed (for example a websiteKey on a widget task).Refunded. Check the create-task field table for the type you are sending.

Handling them

Only two codes are worth retrying automatically. ERROR_RATE_LIMIT means back off and keep the same task. ERROR_UPSTREAM and ERROR_TIMEOUT mean the task is dead and refunded — retry by creating a new one, at most once, or you will spend your budget on a target that is not going to solve. Everything else needs a human.

const result = await post('/getTaskResult', { taskId });

if (result.errorId !== 0) {
  switch (result.errorCode) {
    case 'ERROR_RATE_LIMIT':
      // Back off and retry the same taskId — the task is still alive.
      await sleep(2000);
      continue;
    case 'ERROR_ZERO_BALANCE':
    case 'ERROR_KEY_DISABLED':
      // Nothing to retry. Alert an operator.
      throw new Error(result.errorDescription);
    default:
      // Refunded already; create a fresh task if it is worth retrying.
      throw new Error(`${result.errorCode}: ${result.errorDescription}`);
  }
}

An error response never leaves you charged. If you ever see a debit without a matching credit for a failed task, that is a bug — send us the task id and we will fix it and refund it.