CAPTCHA API 8 min read

CAPTCHA Solver API Integration: Python, Node.js & cURL Examples

Ready-to-use code examples for integrating a CAPTCHA solver API in Python, Node.js, and cURL. Copy-paste snippets for createTask, getTaskResult, and error handling.

CAPTCHA Solver API Integration: Python, Node.js & cURL Examples

CAPTCHA Solver API Integration: Python, Node.js & cURL Examples

Integrating a CAPTCHA solver API into your project takes two HTTP calls: one to create a task, one to retrieve the result. This post provides copy-paste code examples in Python, Node.js, and cURL so you can start solving CAPTCHAs in minutes.

All examples use uCaptcha’s API at api.ucaptcha.net. The API follows the standard createTask / getTaskResult JSON format and is fully 2captcha-compatible, so these patterns work with minimal modification across providers.

Prerequisites

Before you begin, you need:

  • A uCaptcha API key (get one free from @uCaptcha_bot on Telegram)
  • The target site’s CAPTCHA site key (found in the page source)
  • The target page URL

Python Integration

Python is the most common language for CAPTCHA solver integrations. The requests library is all you need.

Basic Solve: reCAPTCHA v2

import requests
import time

API_KEY = "YOUR_UCAPTCHA_API_KEY"
BASE = "https://api.ucaptcha.net"

def solve_recaptcha_v2(site_url: str, site_key: str) -> str:
    """Solve a reCAPTCHA v2 and return the token."""
    # Create task
    resp = requests.post(f"{BASE}/createTask", json={
        "clientKey": API_KEY,
        "task": {
            "type": "RecaptchaV2TaskProxyless",
            "websiteURL": site_url,
            "websiteKey": site_key,
        }
    })
    data = resp.json()

    if data.get("errorId", 0) != 0:
        raise Exception(f"Task creation failed: {data['errorCode']}")

    task_id = data["taskId"]

    # Poll for result
    for _ in range(60):  # max 5 minutes at 5s intervals
        time.sleep(5)
        result = requests.post(f"{BASE}/getTaskResult", json={
            "clientKey": API_KEY,
            "taskId": task_id,
        }).json()

        if result["status"] == "ready":
            return result["solution"]["gRecaptchaResponse"]
        if result["status"] != "processing":
            raise Exception(f"Solve failed: {result.get('errorCode')}")

    raise TimeoutError("CAPTCHA solve timed out after 5 minutes")


# Usage
token = solve_recaptcha_v2(
    "https://example.com/login",
    "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-"
)
print(f"Token: {token[:60]}...")

Solving hCaptcha

The same pattern works for hCaptcha. Only the task type and solution key change:

def solve_hcaptcha(site_url: str, site_key: str) -> str:
    resp = requests.post(f"{BASE}/createTask", json={
        "clientKey": API_KEY,
        "task": {
            "type": "HardCaptchaTaskProxyless",
            "websiteURL": site_url,
            "websiteKey": site_key,
        }
    })
    task_id = resp.json()["taskId"]

    for _ in range(60):
        time.sleep(5)
        result = requests.post(f"{BASE}/getTaskResult", json={
            "clientKey": API_KEY,
            "taskId": task_id,
        }).json()

        if result["status"] == "ready":
            return result["solution"]["gRecaptchaResponse"]
        if result["status"] != "processing":
            raise Exception(result.get("errorCode"))

    raise TimeoutError("Solve timed out")

Image CAPTCHA

For image-based CAPTCHAs, encode the image as base64:

import base64

def solve_image(image_path: str) -> str:
    with open(image_path, "rb") as f:
        body = base64.b64encode(f.read()).decode()

    resp = requests.post(f"{BASE}/createTask", json={
        "clientKey": API_KEY,
        "task": {
            "type": "ImageToTextTask",
            "body": body,
            "case": True,
        }
    })
    task_id = resp.json()["taskId"]

    for _ in range(30):
        time.sleep(3)
        result = requests.post(f"{BASE}/getTaskResult", json={
            "clientKey": API_KEY,
            "taskId": task_id,
        }).json()

        if result["status"] == "ready":
            return result["solution"]["text"]
        if result["status"] != "processing":
            raise Exception(result.get("errorCode"))

    raise TimeoutError("Solve timed out")

Node.js Integration

Modern Node.js (18+) includes a native fetch API. No external dependencies required.

Basic Solve: reCAPTCHA v2

const API_KEY = "YOUR_UCAPTCHA_API_KEY";
const BASE = "https://api.ucaptcha.net";

async function solveRecaptchaV2(siteUrl, siteKey) {
  // Create task
  const createRes = await fetch(`${BASE}/createTask`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      clientKey: API_KEY,
      task: {
        type: "RecaptchaV2TaskProxyless",
        websiteURL: siteUrl,
        websiteKey: siteKey,
      },
    }),
  });
  const { taskId, errorId, errorCode } = await createRes.json();

  if (errorId !== 0) {
    throw new Error(`Task creation failed: ${errorCode}`);
  }

  // Poll for result
  for (let i = 0; i < 60; i++) {
    await new Promise((r) => setTimeout(r, 5000));

    const resultRes = await fetch(`${BASE}/getTaskResult`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ clientKey: API_KEY, taskId }),
    });
    const result = await resultRes.json();

    if (result.status === "ready") {
      return result.solution.gRecaptchaResponse;
    }
    if (result.status !== "processing") {
      throw new Error(`Solve failed: ${result.errorCode}`);
    }
  }

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

// Usage
const token = await solveRecaptchaV2(
  "https://example.com/login",
  "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-"
);
console.log(`Token: ${token.slice(0, 60)}...`);

Cloudflare Turnstile

async function solveTurnstile(siteUrl, siteKey) {
  const { taskId } = await fetch(`${BASE}/createTask`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      clientKey: API_KEY,
      task: {
        type: "TurnstileTaskProxyless",
        websiteURL: siteUrl,
        websiteKey: siteKey,
      },
    }),
  }).then((r) => r.json());

  for (let i = 0; i < 60; i++) {
    await new Promise((r) => setTimeout(r, 5000));
    const result = await fetch(`${BASE}/getTaskResult`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ clientKey: API_KEY, taskId }),
    }).then((r) => r.json());

    if (result.status === "ready") return result.solution.token;
    if (result.status !== "processing") throw new Error(result.errorCode);
  }
  throw new Error("Solve timed out");
}

cURL Examples

cURL is useful for testing the API directly from your terminal or integrating with shell scripts.

Create a Task

curl -X POST https://api.ucaptcha.net/createTask \
  -H "Content-Type: application/json" \
  -d '{
    "clientKey": "YOUR_UCAPTCHA_API_KEY",
    "task": {
      "type": "RecaptchaV2TaskProxyless",
      "websiteURL": "https://example.com/login",
      "websiteKey": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-"
    }
  }'

Response:

{
  "errorId": 0,
  "taskId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

Get Task Result

curl -X POST https://api.ucaptcha.net/getTaskResult \
  -H "Content-Type: application/json" \
  -d '{
    "clientKey": "YOUR_UCAPTCHA_API_KEY",
    "taskId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }'

Response (when ready):

{
  "errorId": 0,
  "status": "ready",
  "solution": {
    "gRecaptchaResponse": "03AGdBq24PBCb..."
  }
}

Check Balance

curl -X POST https://api.ucaptcha.net/getBalance \
  -H "Content-Type: application/json" \
  -d '{"clientKey": "YOUR_UCAPTCHA_API_KEY"}'

Error Handling Patterns

Production code must handle errors. Here are the most important patterns:

Distinguish Retriable vs. Fatal Errors

RETRIABLE = {"ERROR_NO_SLOT_AVAILABLE", "ERROR_CAPTCHA_UNSOLVABLE"}
FATAL = {"ERROR_KEY_DOES_NOT_EXIST", "ERROR_ZERO_BALANCE", "ERROR_WRONG_CAPTCHA_ID"}

def solve_with_retry(site_url, site_key, max_retries=3):
    for attempt in range(max_retries):
        try:
            return solve_recaptcha_v2(site_url, site_key)
        except Exception as e:
            error = str(e)
            if any(f in error for f in FATAL):
                raise  # Don't retry fatal errors
            if attempt < max_retries - 1:
                time.sleep(2 ** attempt)  # Exponential backoff
                continue
            raise

Timeout Safety

Always set an upper bound on polling. Without one, a stuck task will block your program indefinitely:

async function solveWithTimeout(siteUrl, siteKey, timeoutMs = 120000) {
  const controller = new AbortController();
  const timer = setTimeout(() => controller.abort(), timeoutMs);

  try {
    return await solveRecaptchaV2(siteUrl, siteKey);
  } finally {
    clearTimeout(timer);
  }
}

Next Steps

These examples cover the most common integration patterns. For production-grade hardening — retry strategies, cost optimization, provider failover, and monitoring — see Automated CAPTCHA Solving: Best Practices for Production.

All examples use uCaptcha’s API at api.ucaptcha.net, which aggregates five providers (CapSolver, 2Captcha, AntiCaptcha, CapMonster, Multibot, and uCaptcha’s own infrastructure) and routes each task for optimal speed, cost, or reliability. Get your free API key from @uCaptcha_bot and start solving in minutes.

Related Articles