Troubleshooting

CaptchaAI Error Codes: Complete Reference and Fixes

This page documents every error code the CaptchaAI API can return, organized by endpoint. Use it to diagnose failed requests, implement proper error handling, and avoid common mistakes.

The CaptchaAI API has two endpoints:

  • in.php — submit a CAPTCHA task (errors occur at submission time)
  • res.php — poll for the result (errors occur while retrieving results)

When you include json=1 in your request, errors return as JSON:

{"status": 0, "request": "ERROR_CODE_HERE"}

Without json=1, errors return as plain text: ERROR_CODE_HERE


Quick error handling rules

Before the full reference, here are the three rules that handle 90% of cases:

Error pattern Action
CAPCHA_NOT_READY Normal — poll again in 5 seconds
Any ERROR_ starting with parameter/format issues Fix your request — do not retry the same request
Server errors (ERROR_SERVER_ERROR, ERROR_INTERNAL_SERVER_ERROR) Retry after 10 seconds with exponential backoff

Submit errors (in.php)

These errors occur when you submit a new CAPTCHA task.

ERROR_WRONG_USER_KEY

Cause: The key parameter has an incorrect format. CaptchaAI API keys are 32 characters.

Fix:

  1. Check that your key is exactly 32 characters.
  2. Verify there are no extra spaces or line breaks.
  3. Copy the key directly from captchaai.com/api.php.
# Wrong — key has extra space
"key": "abc123... "

# Correct
"key": "abc12345678901234567890123456789a"

ERROR_KEY_DOES_NOT_EXIST

Cause: The API key does not match any account in the system.

Fix:

  1. Log into captchaai.com and copy the key from your dashboard.
  2. Make sure you are using the correct account's key.
  3. If you recently created the account, wait a few minutes for the key to activate.

ERROR_ZERO_BALANCE

Cause: Your account has no available threads to accept the task.

Fix:

  1. Wait for currently running tasks to complete (threads will free up).
  2. Upgrade your plan for more concurrent threads.
  3. Check your account balance at captchaai.com/api.php.

This is not always an out-of-funds error. It can also mean all your threads are currently occupied. If you have a single-thread plan and one task is running, new submissions will return this error until the first task completes.


ERROR_PAGEURL

Cause: The pageurl parameter is missing or empty. This parameter is required for token-based CAPTCHAs (reCAPTCHA, Cloudflare Turnstile, GeeTest, etc.).

Fix: Add the full URL of the page where the CAPTCHA loads, including the protocol:

# Wrong
"pageurl": ""

# Correct
"pageurl": "https://example.com/login"

ERROR_WRONG_GOOGLEKEY / ERROR_GOOGLEKEY

Cause: The googlekey (sitekey) parameter is blank, malformed, or missing.

Fix:

  1. Re-extract the sitekey from the target page's data-sitekey attribute or the reCAPTCHA anchor URL k parameter.
  2. Make sure the value is not empty or truncated.
# Wrong — empty sitekey
"googlekey": ""

# Correct
"googlekey": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-"

ERROR_BAD_TOKEN_OR_PAGEURL

Cause: The combination of googlekey (sitekey) and pageurl is invalid. The sitekey is not registered for the given page URL.

Common causes:

  • The reCAPTCHA widget loads inside an iframe on a different subdomain. You are using the parent page URL instead of the iframe URL.
  • The sitekey belongs to a different page or domain.
  • The sitekey was extracted from a development/staging environment.

Fix:

  1. If the reCAPTCHA is in an iframe, use the iframe's src URL as the pageurl.
  2. Verify the sitekey from the live production page.
  3. Test both values by loading the reCAPTCHA anchor URL manually: https://www.google.com/recaptcha/api2/anchor?k=YOUR_SITEKEY

ERROR_TOO_BIG_CAPTCHA_FILESIZE

Cause: The uploaded image exceeds the maximum allowed size.

Fix: Compress or resize the image before submitting. Use JPEG for photos, PNG for screenshots.


ERROR_ZERO_CAPTCHA_FILESIZE

Cause: The image file is too small (less than 100 bytes), indicating an empty or corrupted upload.

Fix: Verify you are sending actual image data, not an empty file or broken base64 string.


ERROR_WRONG_FILE_EXTENSION

Cause: The uploaded file has an unsupported extension. Supported: jpg, jpeg, png, gif.

Fix: Convert the image to a supported format before uploading.


ERROR_IMAGE_TYPE_NOT_SUPPORTED

Cause: The server cannot determine the image type from the file content.

Fix: Convert to a standard format (PNG or JPEG) and ensure the file is not corrupted.


ERROR_UPLOAD

Cause: The server could not read the uploaded file or base64 payload.

Fix:

  1. For file uploads: verify your multipart form data encoding.
  2. For base64: verify the base64 string is complete and properly encoded.
  3. Test with a known-good image to rule out file corruption.

ERROR_BAD_PROXY

Cause: The proxy you provided is unreachable or has been marked as bad by the system.

Fix:

  1. Test the proxy independently — can it connect to the target site?
  2. Try a different proxy.
  3. Verify the format: login:password@IP:PORT or IP:PORT for IP-authenticated proxies.

Proxy usage must be enabled on your account. Contact CaptchaAI support if you have not done this.


ERROR_BAD_PARAMETERS

Cause: Required parameters are missing or have wrong data types.

Fix: Check the API documentation for the specific CAPTCHA type you are solving and verify all required parameters are present:

CAPTCHA Type Required Parameters
reCAPTCHA v2/v3 key, method=userrecaptcha, googlekey, pageurl
Cloudflare Turnstile key, method=turnstile, sitekey, pageurl
Cloudflare Challenge key, method=cloudflare_challenge, pageurl, proxy, proxytype
GeeTest v3 key, method=geetest, gt, challenge, pageurl
BLS key, method=bls, body, textinstructions
Normal/image key, method=post, file or body

IP_BANNED

Cause: Your IP has been temporarily banned after repeated failed authentication attempts.

Fix: Wait approximately 5 minutes, then retry with correct credentials. Do not keep sending requests with wrong API keys.


ERROR_SERVER_ERROR / ERROR_INTERNAL_SERVER_ERROR

Cause: A transient server-side error occurred.

Fix: Wait 10 seconds and retry. Use exponential backoff for repeated failures:

import time

retry_delay = 10
for attempt in range(5):
    response = submit_captcha()
    if response.get("status") == 1:
        break
    time.sleep(retry_delay)
    retry_delay *= 2  # 10s, 20s, 40s, 80s, 160s

Polling errors (res.php)

These errors occur when you check the status of a submitted task.

CAPCHA_NOT_READY

This is not an error. It means the solve is still in progress.

Action: Wait 5 seconds and poll again.

if result.get("request") == "CAPCHA_NOT_READY":
    time.sleep(5)
    continue  # poll again

Timing guide: | CAPTCHA Type | First poll after | Poll interval | |---|---|---| | reCAPTCHA v2/v3/Enterprise | 15 seconds | 5 seconds | | Cloudflare Turnstile | 15 seconds | 5 seconds | | Cloudflare Challenge | 20 seconds | 5 seconds | | GeeTest v3 | 15 seconds | 5 seconds | | Normal/image CAPTCHA | 5 seconds | 5 seconds |


ERROR_CAPTCHA_UNSOLVABLE

Cause: CaptchaAI could not solve the CAPTCHA after multiple attempts.

Common reasons:

  1. The CAPTCHA type is not supported or parameters are wrong.
  2. The challenge is corrupted or expired.
  3. For proxy-based solves: the proxy is too slow or unreachable.
  4. The site has changed its CAPTCHA implementation.

Fix:

  1. Verify your parameters (sitekey, pageurl, method) are correct.
  2. Resubmit with a fresh request.
  3. If using a proxy, try a different one.
  4. If the error persists, the site may have changed — re-extract the sitekey and pageurl.

Do not retry the same task ID. Submit a new task with fresh parameters.


ERROR_WRONG_ID_FORMAT

Cause: The captcha ID must be numeric only.

Fix: Verify you are sending the exact ID returned by in.php (digits only, no extra characters).


ERROR_WRONG_CAPTCHA_ID

Cause: The task ID does not exist or has expired.

Fix:

  1. Verify you are polling with the ID returned by your submission.
  2. Task IDs may expire after extended periods — resubmit if the task is very old.

ERROR_EMPTY_ACTION

Cause: The action parameter is missing or empty in your polling request.

Fix: Add action=get to your res.php request:

params = {
    "key": api_key,
    "action": "get",  # Required
    "id": captcha_id,
    "json": 1,
}

ERROR_PROXY_CONNECTION_FAILED

Cause: The solver could not connect to the target site through your proxy.

Fix:

  1. The proxy may be temporarily down — try a different one.
  2. The target site may be blocking the proxy IP.
  3. Verify the proxy can actually reach the target site.

ERROR_WRONG_USER_KEY / ERROR_KEY_DOES_NOT_EXIST

These can also appear on res.php — same cause and fix as the submit errors above.


Error handling template

Copy this pattern for robust error handling in any language:

Python

import time
import requests

API_KEY = "YOUR_API_KEY"
SUBMIT_URL = "https://ocr.captchaai.com/in.php"
RESULT_URL = "https://ocr.captchaai.com/res.php"

# Errors that should not be retried (fix the request first)
NO_RETRY_ERRORS = {
    "ERROR_WRONG_USER_KEY",
    "ERROR_KEY_DOES_NOT_EXIST",
    "ERROR_PAGEURL",
    "ERROR_WRONG_GOOGLEKEY",
    "ERROR_GOOGLEKEY",
    "ERROR_BAD_TOKEN_OR_PAGEURL",
    "ERROR_BAD_PARAMETERS",
    "ERROR_WRONG_FILE_EXTENSION",
    "ERROR_IMAGE_TYPE_NOT_SUPPORTED",
    "IP_BANNED",
}

# Errors that can be retried
RETRY_ERRORS = {
    "ERROR_ZERO_BALANCE",
    "ERROR_SERVER_ERROR",
    "ERROR_INTERNAL_SERVER_ERROR",
    "ERROR_UPLOAD",
}


def solve_captcha(submit_data, max_retries=3, max_polls=60):
    """Submit and solve a CAPTCHA with full error handling."""

    # Submit with retry logic
    for attempt in range(max_retries):
        resp = requests.post(SUBMIT_URL, data={**submit_data, "json": 1}, timeout=30)
        resp.raise_for_status()
        data = resp.json()

        if data.get("status") == 1:
            captcha_id = data["request"]
            break

        error = data.get("request", "UNKNOWN")

        if error in NO_RETRY_ERRORS:
            raise ValueError(f"Fatal error (fix request): {error}")

        if error in RETRY_ERRORS and attempt < max_retries - 1:
            time.sleep(10 * (2 ** attempt))
            continue

        raise RuntimeError(f"Submit failed: {error}")
    else:
        raise RuntimeError("Submit failed after max retries")

    # Poll for result
    time.sleep(15)

    for _ in range(max_polls):
        resp = requests.get(
            RESULT_URL,
            params={"key": API_KEY, "action": "get", "id": captcha_id, "json": 1},
            timeout=30,
        )
        data = resp.json()

        if data.get("request") == "CAPCHA_NOT_READY":
            time.sleep(5)
            continue

        if data.get("status") == 1:
            return data["request"]

        error = data.get("request", "UNKNOWN")
        if error == "ERROR_CAPTCHA_UNSOLVABLE":
            raise RuntimeError("CAPTCHA unsolvable — resubmit with fresh parameters")

        raise RuntimeError(f"Poll error: {error}")

    raise TimeoutError("Solve timed out")

Node.js

const NO_RETRY_ERRORS = new Set([
  "ERROR_WRONG_USER_KEY",
  "ERROR_KEY_DOES_NOT_EXIST",
  "ERROR_PAGEURL",
  "ERROR_WRONG_GOOGLEKEY",
  "ERROR_BAD_TOKEN_OR_PAGEURL",
  "ERROR_BAD_PARAMETERS",
  "IP_BANNED",
]);

async function solveCaptcha(submitData, maxRetries = 3, maxPolls = 60) {
  const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

  // Submit with retry
  let captchaId;
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const resp = await fetch("https://ocr.captchaai.com/in.php", {
      method: "POST",
      headers: { "Content-Type": "application/x-www-form-urlencoded" },
      body: new URLSearchParams({ ...submitData, json: "1" }),
    });
    const data = await resp.json();

    if (data.status === 1) {
      captchaId = data.request;
      break;
    }

    if (NO_RETRY_ERRORS.has(data.request)) {
      throw new Error(`Fatal error: ${data.request}`);
    }

    if (attempt < maxRetries - 1) {
      await sleep(10_000 * 2 ** attempt);
      continue;
    }

    throw new Error(`Submit failed: ${data.request}`);
  }

  // Poll for result
  await sleep(15_000);

  for (let i = 0; i < maxPolls; i++) {
    const resp = await fetch(
      `https://ocr.captchaai.com/res.php?${new URLSearchParams({
        key: submitData.key,
        action: "get",
        id: captchaId,
        json: "1",
      })}`
    );
    const data = await resp.json();

    if (data.request === "CAPCHA_NOT_READY") {
      await sleep(5_000);
      continue;
    }

    if (data.status === 1) return data.request;

    throw new Error(`Poll error: ${data.request}`);
  }

  throw new Error("Solve timed out");
}

FAQ

Is CAPCHA_NOT_READY an error?

No. It means the solve is still in progress. Wait 5 seconds and poll again. This is normal for every CAPTCHA type.

What should I do when I get ERROR_CAPTCHA_UNSOLVABLE?

Submit a new task with fresh parameters. Do not retry the same task ID. If the error happens repeatedly, verify your sitekey and pageurl are correct and that the CAPTCHA type is supported.

How do I know if an error is retryable?

Parameter/format errors (ERROR_WRONG_USER_KEY, ERROR_BAD_TOKEN_OR_PAGEURL, ERROR_PAGEURL, etc.) are not retryable — fix the request first. Server errors (ERROR_SERVER_ERROR, ERROR_INTERNAL_SERVER_ERROR) are retryable with exponential backoff. ERROR_ZERO_BALANCE is retryable after waiting for threads to free up.

Why do I get ERROR_BAD_PROXY for Cloudflare Challenge?

Cloudflare Challenge requires a working proxy. The proxy must be able to reach the target site. Test it independently, then try a different proxy if it fails. Also ensure proxy usage is enabled on your CaptchaAI account.

Where do I find my API key?

Log in to captchaai.com and go to captchaai.com/api.php. Your 32-character API key is displayed on the dashboard.


Discussions (0)

No comments yet.