Developer Guides

CAPTCHA Solver API Integration Guide

CAPTCHA solving services expose APIs that follow one of two main formats. Once you understand either format, you can integrate any provider in the ecosystem. This guide covers both formats, error handling, and production integration patterns.

The Two Main API Formats

Format 1: 2Captcha-Style (GET Parameters)

Used by: 2Captcha, CaptchaAI (compatible mode)

Submit task:

POST https://2captcha.com/in.php
Body: key=API_KEY&method=userrecaptcha&googlekey=SITEKEY&pageurl=URL&json=1

Poll result:

GET https://2captcha.com/res.php?key=API_KEY&action=get&id=TASK_ID&json=1

Format 2: Anti-Captcha JSON POST

Used by: Anti-Captcha, CapMonster Cloud, NextCaptcha, CapSolver (similar)

Submit task:

POST https://api.anti-captcha.com/createTask
{
  "clientKey": "API_KEY",
  "task": {
    "type": "RecaptchaV2TaskProxyless",
    "websiteURL": "https://example.com",
    "websiteKey": "SITEKEY"
  }
}

Poll result:

POST https://api.anti-captcha.com/getTaskResult
{
  "clientKey": "API_KEY",
  "taskId": 12345
}

Python Client — Format 1 (2Captcha-Compatible)

# captcha_client_v1.py
import requests
import time
from typing import Optional

class CaptchaClientV1:
    """2Captcha-compatible API client."""

    def __init__(self, api_key: str, base_url: str = "https://2captcha.com"):
        self.api_key = api_key
        self.base_url = base_url.rstrip("/")

    def solve_recaptcha_v2(
        self,
        page_url: str,
        site_key: str,
        invisible: bool = False,
        timeout: int = 120,
    ) -> str:
        task_id = self._submit({
            "method": "userrecaptcha",
            "googlekey": site_key,
            "pageurl": page_url,
            "invisible": int(invisible),
        })
        return self._poll(task_id, timeout=timeout)

    def solve_recaptcha_v3(
        self,
        page_url: str,
        site_key: str,
        action: str = "verify",
        min_score: float = 0.7,
        timeout: int = 120,
    ) -> str:
        task_id = self._submit({
            "method": "userrecaptcha",
            "version": "v3",
            "googlekey": site_key,
            "pageurl": page_url,
            "action": action,
            "min_score": min_score,
        })
        return self._poll(task_id, timeout=timeout)

    def solve_turnstile(self, page_url: str, site_key: str, timeout: int = 60) -> str:
        task_id = self._submit({
            "method": "turnstile",
            "sitekey": site_key,
            "pageurl": page_url,
        })
        return self._poll(task_id, timeout=timeout)

    def solve_hcaptcha(self, page_url: str, site_key: str, timeout: int = 120) -> str:
        task_id = self._submit({
            "method": "hcaptcha",
            "sitekey": site_key,
            "pageurl": page_url,
        })
        return self._poll(task_id, timeout=timeout)

    def _submit(self, params: dict) -> str:
        payload = {"key": self.api_key, "json": 1, **params}
        resp = requests.post(f"{self.base_url}/in.php", data=payload, timeout=15)
        resp.raise_for_status()
        data = resp.json()
        if data["status"] != 1:
            raise ValueError(f"Task submission failed: {data['request']}")
        return data["request"]

    def _poll(self, task_id: str, timeout: int = 120, poll_interval: int = 5) -> str:
        deadline = time.time() + timeout
        time.sleep(poll_interval)
        while time.time() < deadline:
            resp = requests.get(f"{self.base_url}/res.php", params={
                "key": self.api_key,
                "action": "get",
                "id": task_id,
                "json": 1,
            }, timeout=15)
            resp.raise_for_status()
            data = resp.json()
            if data["status"] == 1:
                return data["request"]
            if data["request"] not in ("CAPCHA_NOT_READY", "ERROR_CAPTCHA_NOT_READY"):
                raise ValueError(f"Solve error: {data['request']}")
            time.sleep(poll_interval)
        raise TimeoutError(f"Solve timed out after {timeout}s")

Python Client — Format 2 (Anti-Captcha JSON)

# captcha_client_v2.py
import requests
import time

class CaptchaClientV2:
    """Anti-Captcha JSON POST API client."""

    def __init__(self, api_key: str, base_url: str = "https://api.anti-captcha.com"):
        self.api_key = api_key
        self.base_url = base_url.rstrip("/")

    def solve_recaptcha_v2(self, page_url: str, site_key: str, timeout: int = 120) -> str:
        task_id = self._create_task({
            "type": "RecaptchaV2TaskProxyless",
            "websiteURL": page_url,
            "websiteKey": site_key,
        })
        return self._get_result(task_id, "gRecaptchaResponse", timeout=timeout)

    def solve_hcaptcha(self, page_url: str, site_key: str, timeout: int = 120) -> str:
        task_id = self._create_task({
            "type": "HCaptchaTaskProxyless",
            "websiteURL": page_url,
            "websiteKey": site_key,
        })
        return self._get_result(task_id, "gRecaptchaResponse", timeout=timeout)

    def solve_turnstile(self, page_url: str, site_key: str, timeout: int = 60) -> str:
        task_id = self._create_task({
            "type": "TurnstileTaskProxyless",
            "websiteURL": page_url,
            "websiteKey": site_key,
        })
        return self._get_result(task_id, "token", timeout=timeout)

    def _create_task(self, task: dict) -> int:
        resp = requests.post(f"{self.base_url}/createTask", json={
            "clientKey": self.api_key,
            "task": task,
        }, timeout=15)
        resp.raise_for_status()
        data = resp.json()
        if data.get("errorId", 0) != 0:
            raise ValueError(f"Task creation error: {data.get('errorDescription')}")
        return data["taskId"]

    def _get_result(self, task_id: int, result_key: str, timeout: int = 120, poll_interval: int = 5) -> str:
        deadline = time.time() + timeout
        time.sleep(poll_interval)
        while time.time() < deadline:
            resp = requests.post(f"{self.base_url}/getTaskResult", json={
                "clientKey": self.api_key,
                "taskId": task_id,
            }, timeout=15)
            resp.raise_for_status()
            data = resp.json()
            if data.get("errorId", 0) != 0:
                raise ValueError(f"Task error: {data.get('errorDescription')}")
            if data["status"] == "ready":
                return data["solution"][result_key]
            time.sleep(poll_interval)
        raise TimeoutError(f"Solve timed out after {timeout}s")

Node.js Integration (Format 1)

// captchaClient.js
const axios = require('axios');

class CaptchaClient {
  constructor(apiKey, baseUrl = 'https://2captcha.com') {
    this.apiKey = apiKey;
    this.baseUrl = baseUrl;
  }

  async solveRecaptchaV2(pageUrl, siteKey, options = {}) {
    const taskId = await this._submit({
      method: 'userrecaptcha',
      googlekey: siteKey,
      pageurl: pageUrl,
      invisible: options.invisible ? 1 : 0,
    });
    return this._poll(taskId);
  }

  async _submit(params) {
    const { data } = await axios.post(`${this.baseUrl}/in.php`, null, {
      params: { key: this.apiKey, json: 1, ...params },
    });
    if (data.status !== 1) throw new Error(`Submission failed: ${data.request}`);
    return data.request;
  }

  async _poll(taskId, timeout = 120000, interval = 5000) {
    const deadline = Date.now() + timeout;
    await new Promise(r => setTimeout(r, interval));

    while (Date.now() < deadline) {
      const { data } = await axios.get(`${this.baseUrl}/res.php`, {
        params: { key: this.apiKey, action: 'get', id: taskId, json: 1 },
      });
      if (data.status === 1) return data.request;
      if (!['CAPCHA_NOT_READY', 'ERROR_CAPTCHA_NOT_READY'].includes(data.request)) {
        throw new Error(`Solve error: ${data.request}`);
      }
      await new Promise(r => setTimeout(r, interval));
    }
    throw new Error('Solve timed out');
  }
}

module.exports = CaptchaClient;

Error Handling Reference

Error Code Meaning Action
ERROR_WRONG_USER_KEY Invalid API key Check key in dashboard
ERROR_KEY_DOES_NOT_EXIST Key not found Verify key
ERROR_ZERO_BALANCE Insufficient balance Top up account
ERROR_CAPTCHA_UNSOLVABLE Solver could not solve Retry; may be high-difficulty challenge
ERROR_NO_SLOT_AVAILABLE Queue full Retry with backoff; consider provider switch
CAPCHA_NOT_READY Still processing Continue polling

Production Checklist

  • [ ] API key stored in environment variable, not hardcoded
  • [ ] Retry logic with exponential backoff on solver errors
  • [ ] Timeout handling on poll loop
  • [ ] Token injection within 2 minutes of solve
  • [ ] Balance monitoring to detect empty account before large runs
  • [ ] Logging of task IDs for debugging failed solves
  • [ ] Failover provider configured for critical pipelines

See API quality comparisons at captcharank.com/solvers.

Production Readiness Notes

Use CAPTCHA Solver API Integration Guide as a decision and implementation aid, not just as a one-time reference. The practical test for captcha solver api integration guide is whether the same approach behaves reliably when traffic is messy: rotating sessions, expired tokens, changing widget parameters, intermittent solver delays, and target pages that refresh without warning. For Automation developer, the safest rollout is to start with a narrow fixture, record every submitted task, and compare the solver response with the browser state that finally submits the form. That makes failures explainable instead of mysterious, especially when a target alternates between visible challenges, invisible checks, and server-side verification.

Evaluation Criteria

A developer guide should become a reusable integration module with typed configuration, bounded polling, structured errors, and a single place for API credentials. For developer integration work, the most useful scorecard combines technical acceptance with operational cost. A low nominal price is not enough if retries double the real cost per accepted token, and a fast median solve time is not enough if p95 latency stalls the queue. Track these criteria before you standardize the workflow:

  • The challenge subtype, sitekey, action, rqdata, blob, captchaId, or page URL used for each task.
  • Median and p95 solve time, separated by provider and target domain.
  • Accepted-token rate on the target page, not just successful API responses.
  • Retry count, timeout count, zero-balance incidents, and invalid-parameter errors.
  • The exact browser, proxy region, and user-agent that submitted the solved token.

Rollout Checklist

Before this guidance moves into a production job, build a small acceptance suite around the pages that matter most. Run it with a fixed browser profile, then repeat with the proxy and concurrency settings you expect in production. Keep the first release conservative: bounded polling, clear timeout handling, and a fallback path when the solver cannot return a usable answer. For developer integration, treat the code as a production pattern: timeouts, retries, logging, secret storage, and test fixtures matter as much as the solve request itself. That checklist keeps the article useful after the first copy-paste, because the integration is judged by end-to-end completion rather than by whether a code sample returned a string.

Monitoring Signals

Healthy CAPTCHA automation is observable. Log the task id, provider, challenge type, target host, queue time, solve time, final submit status, and normalized error code for every attempt. Review those logs in daily batches at first, then move to alerts once the baseline is stable. Sudden drops usually come from target-side changes: a new sitekey, a changed action name, a stricter hostname check, an added managed challenge, or a proxy pool that no longer matches the expected geography. When you can see those shifts quickly, provider switching becomes a controlled decision instead of a late-night rewrite.

Maintenance Cadence

Revisit the setup whenever the target UI changes, when the solver provider changes task names or pricing, or when benchmark data shows a sustained latency or solve-rate shift. Keep one known-good fixture for each CAPTCHA subtype and rerun it after dependency upgrades, browser updates, and proxy changes. If the article is used for vendor selection, repeat the same fixture across at least two providers before renewing a balance or migrating the whole pipeline. That habit keeps captcha solver api integration guide work aligned with the real target behavior rather than with stale assumptions.

Comments are disabled for this article.