Comparisons

Migrate from Anti-Captcha to CaptchaAI Step by Step

Anti-Captcha uses a custom JSON task-based API. CaptchaAI uses the simpler, widely-adopted 2Captcha-compatible format. This guide provides exact code replacements for every CAPTCHA type.


API Format Differences

Anti-Captcha:
  Submit: POST /createTask (JSON body)
  Poll:   POST /getTaskResult (JSON body)
  Format: Task objects with "type" field

CaptchaAI:
  Submit: POST /in.php (form data or JSON)
  Poll:   GET /res.php (query parameters)
  Format: Flat key-value with "method" field

Step 1: Get CaptchaAI Credentials

  1. Register at captchaai.com
  2. Add funds
  3. Copy your API key

Step 2: Migrate reCAPTCHA v2

Anti-Captcha (Before)

import requests
import time

ANTICAPTCHA_KEY = "your_anticaptcha_key"

# Submit
resp = requests.post("https://api.anti-captcha.com/createTask", json={
    "clientKey": ANTICAPTCHA_KEY,
    "task": {
        "type": "RecaptchaV2TaskProxyless",
        "websiteURL": "https://example.com",
        "websiteKey": "SITE_KEY",
    }
})
task_id = resp.json()["taskId"]

# Poll
while True:
    time.sleep(5)
    result = requests.post("https://api.anti-captcha.com/getTaskResult", json={
        "clientKey": ANTICAPTCHA_KEY,
        "taskId": task_id,
    })
    data = result.json()
    if data["status"] == "ready":
        token = data["solution"]["gRecaptchaResponse"]
        break

CaptchaAI (After)

import requests
import time

CAPTCHAAI_KEY = "your_captchaai_key"

# Submit
resp = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": CAPTCHAAI_KEY,
    "method": "userrecaptcha",
    "googlekey": "SITE_KEY",
    "pageurl": "https://example.com",
    "json": 1,
})
task_id = resp.json()["request"]

# Poll
while True:
    time.sleep(5)
    result = requests.get("https://ocr.captchaai.com/res.php", params={
        "key": CAPTCHAAI_KEY,
        "action": "get",
        "id": task_id,
        "json": 1,
    })
    data = result.json()
    if data["request"] != "CAPCHA_NOT_READY":
        token = data["request"]
        break

Step 3: Migrate reCAPTCHA v3

Anti-Captcha (Before)

resp = requests.post("https://api.anti-captcha.com/createTask", json={
    "clientKey": ANTICAPTCHA_KEY,
    "task": {
        "type": "RecaptchaV3TaskProxyless",
        "websiteURL": "https://example.com",
        "websiteKey": "SITE_KEY",
        "minScore": 0.7,
        "pageAction": "login",
    }
})

CaptchaAI (After)

resp = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": CAPTCHAAI_KEY,
    "method": "userrecaptcha",
    "version": "v3",
    "googlekey": "SITE_KEY",
    "pageurl": "https://example.com",
    "action": "login",
    "min_score": "0.7",
    "json": 1,
})

Step 4: Migrate Cloudflare Turnstile

Anti-Captcha (Before)

resp = requests.post("https://api.anti-captcha.com/createTask", json={
    "clientKey": ANTICAPTCHA_KEY,
    "task": {
        "type": "TurnstileTaskProxyless",
        "websiteURL": "https://example.com",
        "websiteKey": "TURNSTILE_KEY",
    }
})

CaptchaAI (After)

resp = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": CAPTCHAAI_KEY,
    "method": "turnstile",
    "sitekey": "TURNSTILE_KEY",
    "pageurl": "https://example.com",
    "json": 1,
})

Step 5: Migrate Image CAPTCHA

Anti-Captcha (Before)

import base64

with open("captcha.png", "rb") as f:
    body = base64.b64encode(f.read()).decode()

resp = requests.post("https://api.anti-captcha.com/createTask", json={
    "clientKey": ANTICAPTCHA_KEY,
    "task": {
        "type": "ImageToTextTask",
        "body": body,
    }
})

CaptchaAI (After)

import base64

with open("captcha.png", "rb") as f:
    body = base64.b64encode(f.read()).decode()

resp = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": CAPTCHAAI_KEY,
    "method": "base64",
    "body": body,
    "json": 1,
})

Step 6: Migrate GeeTest

Anti-Captcha (Before)

resp = requests.post("https://api.anti-captcha.com/createTask", json={
    "clientKey": ANTICAPTCHA_KEY,
    "task": {
        "type": "GeeTestTaskProxyless",
        "websiteURL": "https://example.com",
        "gt": "GT_KEY",
        "challenge": "CHALLENGE_VALUE",
    }
})

CaptchaAI (After)

resp = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": CAPTCHAAI_KEY,
    "method": "geetest",
    "gt": "GT_KEY",
    "challenge": "CHALLENGE_VALUE",
    "pageurl": "https://example.com",
    "json": 1,
})

Step 7: New Features After Migration

After switching, you gain access to CAPTCHA types Anti-Captcha doesn't support:

Cloudflare Challenge

resp = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": CAPTCHAAI_KEY,
    "method": "cloudflare_challenge",
    "pageurl": "https://cloudflare-protected.example.com",
    "sitekey": "CHALLENGE_KEY",
    "json": 1,
})

BLS CAPTCHA

resp = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": CAPTCHAAI_KEY,
    "method": "bls",
    "pageurl": "https://bls-portal.example.com",
    "sitekey": "BLS_SITE_KEY",
    "json": 1,
})

Complete Migration Wrapper

Replace Anti-Captcha calls with this unified wrapper:

import requests
import time


class CaptchaAISolver:
    """Drop-in replacement for Anti-Captcha API calls."""

    def __init__(self, api_key):
        self.api_key = api_key
        self.base = "https://ocr.captchaai.com"

    def solve(self, method, **params):
        """Submit and poll for any CAPTCHA type."""
        data = {"key": self.api_key, "method": method, "json": 1}
        data.update(params)

        resp = requests.post(f"{self.base}/in.php", data=data, timeout=30)
        resp.raise_for_status()
        result = resp.json()

        if result.get("status") != 1:
            raise RuntimeError(f"Submit failed: {result.get('request')}")

        return self._poll(result["request"])

    def _poll(self, task_id, timeout=120):
        start = time.time()
        while time.time() - start < timeout:
            time.sleep(5)
            resp = requests.get(f"{self.base}/res.php", params={
                "key": self.api_key,
                "action": "get",
                "id": task_id,
                "json": 1,
            }, timeout=15)
            data = resp.json()
            if data["request"] != "CAPCHA_NOT_READY":
                if data.get("status") == 1:
                    return data["request"]
                raise RuntimeError(f"Solve error: {data['request']}")
        raise TimeoutError("Poll timeout")

    def recaptcha_v2(self, sitekey, url):
        return self.solve("userrecaptcha", googlekey=sitekey, pageurl=url)

    def recaptcha_v3(self, sitekey, url, action="verify", min_score=0.7):
        return self.solve(
            "userrecaptcha", version="v3", googlekey=sitekey,
            pageurl=url, action=action, min_score=str(min_score),
        )

    def turnstile(self, sitekey, url):
        return self.solve("turnstile", sitekey=sitekey, pageurl=url)

    def geetest(self, gt, challenge, url):
        return self.solve("geetest", gt=gt, challenge=challenge, pageurl=url)

    def image(self, base64_body):
        return self.solve("base64", body=base64_body)

    def bls(self, sitekey, url):
        return self.solve("bls", sitekey=sitekey, pageurl=url)

    def balance(self):
        resp = requests.get(f"{self.base}/res.php", params={
            "key": self.api_key, "action": "getbalance", "json": 1,
        })
        return float(resp.json()["request"])


# Usage — replaces all Anti-Captcha calls
solver = CaptchaAISolver("your_captchaai_key")

# reCAPTCHA v2
token = solver.recaptcha_v2("SITE_KEY", "https://example.com")

# Turnstile
token = solver.turnstile("SITE_KEY", "https://example.com")

# Balance
print(f"Balance: ${solver.balance():.2f}")

Parameter Mapping Reference

Anti-Captcha CaptchaAI Notes
clientKey key API key
task.type method CAPTCHA type identifier
task.websiteURL pageurl Target page URL
task.websiteKey googlekey or sitekey Site key
task.minScore min_score v3 minimum score
task.pageAction action v3 action string
task.body body Base64 image data
task.gt gt GeeTest key
task.challenge challenge GeeTest challenge
taskId id Task ID for polling

Troubleshooting

Issue Cause Fix
ERROR_WRONG_USER_KEY Using Anti-Captcha key Register at CaptchaAI for new key
JSON body rejected Sending JSON task objects Use form data with flat key-value pairs
Missing method field Using type from Anti-Captcha Replace with CaptchaAI method names
Wrong poll endpoint POST to /getTaskResult GET to /res.php with query params

FAQ

Is the migration harder than switching from 2Captcha?

Slightly, because the API formats differ. But the core logic is the same (submit → poll → get result). Use the wrapper class above for a clean migration.

Can I keep Anti-Captcha as a fallback?

Yes. Run both in parallel and route based on CAPTCHA type or priority. CaptchaAI handles Cloudflare Challenge and BLS that Anti-Captcha doesn't support.

Do I need to change my proxy configuration?

The proxy parameter format differs. In CaptchaAI, use proxy=user:pass@host:port and proxytype=HTTP as flat parameters instead of Anti-Captcha's nested proxy object.



Switch to better Cloudflare and BLS support — start with CaptchaAI.

Discussions (0)

No comments yet.