Reference
Error codes
Every failure carries a numeric errorId, a stable errorCode string and a description. The last column says whether retrying is worth attempting — that is the part most integrations get wrong.
A failed solve is never charged
errorId, nothing leaves your balance, and any provisional hold is released immediately.The shape of a failure#
{
"errorId": 301,
"status": "failed",
"errorCode": "ERROR_IP_BLOCKED",
"errorDescription": "The target rejected the proxy IP.",
"cost": "$0.0000"
}Branch on errorCode rather than the numeric id or the HTTP status — the string is the stable contract. New codes may be added over time; treat an unrecognised one as non-retryable.
Note the 200. Everything in the Solve group below answers 200, because the call itself succeeded — your request was well formed, your key was good, the type was accepted and nothing was charged. What failed was the challenge, and errorId is where that is reported. Auth, request, billing and platform errors do carry a real status, because for those the call genuinely did not go through.
Authentication 100–119#
| Id | Code | HTTP | What happened / what to do | Retry |
|---|---|---|---|---|
| 100 | ERROR_KEY_MISSING | 401 | No clientKey was supplied.Send clientKey in the JSON body, or an Authorization: Bearer header. | Do not retry |
| 101 | ERROR_KEY_INVALID | 401 | The key does not exist or has been revoked.Check for a stale key after a rotation. Keys are revoked the moment you rotate. | Do not retry |
| 102 | ERROR_KEY_SUSPENDED | 403 | The account attached to this key is suspended.Contact support. Solves will not run until the account is restored. | Do not retry |
| 103 | ERROR_TYPE_NOT_ENABLED | 403 | This account is not enabled for the requested task type.Check your coverage page. Ask support to enable the type on your account. | Do not retry |
Request 200–219#
| Id | Code | HTTP | What happened / what to do | Retry |
|---|---|---|---|---|
| 200 | ERROR_BAD_REQUEST | 400 | The body was not valid JSON, or task was missing.Send a JSON object containing a task object. Check your Content-Type header. | Do not retry |
| 201 | ERROR_TYPE_UNSUPPORTED | 400 | task.type is not a recognised value.Compare against the task.type column on the pricing page. Matching is case-insensitive. | Do not retry |
| 202 | ERROR_REQUIRED_FIELD | 400 | A field this task type requires was absent.The response names the missing field. Each type page lists its required fields. | Do not retry |
| 203 | ERROR_URL_INVALID | 400 | task.url was not an absolute http or https URL.Send the full page URL including the scheme. | Do not retry |
| 204 | ERROR_SITEKEY_INVALID | 400 | The site key was malformed, or does not belong to that URL.Re-read the key from the live page — site keys are per-domain and rotate. | Do not retry |
| 205 | ERROR_PROXY_FORMAT | 400 | The proxy string could not be parsed.Use host:port, host:port:user:pass, or user:pass@host:port. | Do not retry |
| 206 | ERROR_TASK_NOT_FOUND | 404 | No task with that taskId, or it belongs to a different key.Task results are held for ten minutes. Collect a result in the session that created it; treat a lost id as a solve to repeat. | Do not retry |
Solve 300–319#
| Id | Code | HTTP | What happened / what to do | Retry |
|---|---|---|---|---|
| 300 | ERROR_PROXY_CONNECT | 200 | Your proxy refused the connection or timed out.Verify the proxy is alive and permits the target host. Not billed. | Retry |
| 301 | ERROR_IP_BLOCKED | 200 | The target rejected the proxy IP outright.Rotate to a different exit IP — ideally residential for this target. Not billed. | Retry |
| 302 | ERROR_SITE_UNREACHABLE | 200 | The target host did not respond in time.Check the site is up from your own network before retrying. Not billed. | Retry with backoff |
| 303 | ERROR_CAPTCHA_UNSOLVABLE | 200 | The challenge was served but could not be completed.Usually transient. Retry once; if it persists the site may have changed. Not billed. | Retry |
| 304 | ERROR_SCORE_NOT_REACHED | 200 | A token was produced but the target scored it too low to accept.Use a cleaner proxy pool, or a variant tuned for harder sites. Not billed. | Retry |
| 305 | ERROR_TIMEOUT | 200 | The solve exceeded the maximum time for this type.Retry. If it recurs on one target, tell us which — that is a bug on our side. Not billed. | Retry with backoff |
| 306 | ERROR_BLOB_REQUIRED | 200 | This site gates the challenge behind a data-exchange blob, and none was sent.Send task.blob with a FRESH blob from the site’s own flow for every task (Roblox: rblx-challenge-metadata dataExchangeBlob; Airbnb: Airlock frictionData.encodedDataPayload). Not billed. | Retry |
| 307 | ERROR_BLOB_REJECTED | 200 | The site rejected the data-exchange blob: it was already used, expired, or altered.Blobs are single-use and short-lived. Fetch a NEW blob for every task and pass it untouched — no URL-encoding or trimming — with the site_key that was returned alongside it. Not billed. | Retry |
Billing 400–419#
| Id | Code | HTTP | What happened / what to do | Retry |
|---|---|---|---|---|
| 400 | ERROR_INSUFFICIENT_BALANCE | 402 | Your balance will not cover this solve.Top up from the dashboard. Nothing is queued while the balance is empty. | Do not retry |
| 401 | ERROR_THREAD_LIMIT | 429 | You have more solves in flight than your key permits.Wait for one to finish, or ask support to raise the limit. Retry with backoff. | Retry with backoff |
| 402 | ERROR_RATE_LIMITED | 429 | Too many requests in a short window.Back off using the Retry-After header. | Retry with backoff |
System 500–519#
| Id | Code | HTTP | What happened / what to do | Retry |
|---|---|---|---|---|
| 500 | ERROR_INTERNAL | 500 | Something failed on our side.Retry with backoff. Never billed. Persistent failures belong in a support email. | Retry with backoff |
| 501 | ERROR_TYPE_DEGRADED | 503 | This task type is temporarily degraded.Check the status page. Retry with backoff. Never billed. | Retry with backoff |
A sane retry policy#
Retry ERROR_IP_BLOCKED, ERROR_PROXY_CONNECT, ERROR_CAPTCHA_UNSOLVABLE and ERROR_SCORE_NOT_REACHED immediately, rotating the exit IP first — these usually reflect the reputation of the address rather than anything wrong with your request.
Back off on ERROR_THREAD_LIMIT, ERROR_RATE_LIMITED, ERROR_TIMEOUT and anything in the 500 range. Two or three attempts with exponential backoff is plenty; beyond that you are queueing work behind a problem that is not going to clear on its own.
Never retry the 100 and 200 ranges. Those mean the request itself is wrong — a revoked key, a bad site key, a missing field — and an identical second attempt fails identically while still costing you a round trip.
Last updated on 24 July 2026