Reference

Migrate from NextCaptcha to CaptchaAI: Complete Guide

NextCaptcha uses a JSON-based REST API with /createTask and /getTaskResult endpoints. CaptchaAI uses the widely-adopted in.php/res.php format. This guide covers the exact mapping between the two APIs.

Endpoint Mapping

Action NextCaptcha CaptchaAI
Submit task POST /createTask POST https://ocr.captchaai.com/in.php
Get result POST /getTaskResult GET https://ocr.captchaai.com/res.php
Check balance POST /getBalance GET res.php?action=getbalance&key=KEY

Request Structure Differences

NextCaptcha Submit (JSON body)

{
  "clientKey": "next_captcha_key",
  "task": {
    "type": "RecaptchaV2TaskProxyless",
    "websiteURL": "https://example.com",
    "websiteKey": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-"
  }
}

CaptchaAI Submit (form parameters)

POST https://ocr.captchaai.com/in.php
key=YOUR_API_KEY&method=userrecaptcha&googlekey=6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-&pageurl=https://example.com&json=1

Parameter Translation

NextCaptcha Field CaptchaAI Field Notes
clientKey key API key
task.type method See type mapping below
task.websiteURL pageurl Target page URL
task.websiteKey googlekey or sitekey Site key for token CAPTCHAs
task.recaptchaDataSValue data-s reCAPTCHA data-s parameter
task.isInvisible invisible=1 Invisible reCAPTCHA flag
task.minScore min_score reCAPTCHA v3 minimum score
task.pageAction action reCAPTCHA v3 action
taskId id Task/captcha ID for polling

Task Type Mapping

NextCaptcha Type CaptchaAI Method + Params
RecaptchaV2TaskProxyless method=userrecaptcha
RecaptchaV2Task method=userrecaptcha + proxy, proxytype
RecaptchaV3TaskProxyless method=userrecaptcha + version=v3, action, min_score
HCaptchaTaskProxyless method=hcaptcha
HCaptchaTask method=hcaptcha + proxy, proxytype
ImageToTextTask method=base64 + body
TurnstileTaskProxyless method=turnstile

Code Migration

Python — Before (NextCaptcha)

import requests
import time

CLIENT_KEY = "your_nextcaptcha_key"
BASE_URL = "https://api.nextcaptcha.com"

def solve_recaptcha_v2(sitekey, pageurl):
    # Submit
    resp = requests.post(f"{BASE_URL}/createTask", json={
        "clientKey": CLIENT_KEY,
        "task": {
            "type": "RecaptchaV2TaskProxyless",
            "websiteURL": pageurl,
            "websiteKey": sitekey
        }
    })
    data = resp.json()
    if data.get("errorId") != 0:
        return {"error": data.get("errorDescription")}

    task_id = data["taskId"]

    # Poll
    for _ in range(60):
        time.sleep(5)
        result = requests.post(f"{BASE_URL}/getTaskResult", json={
            "clientKey": CLIENT_KEY,
            "taskId": task_id
        }).json()
        if result.get("status") == "ready":
            return {"solution": result["solution"]["gRecaptchaResponse"]}
        if result.get("errorId") != 0:
            return {"error": result.get("errorDescription")}

    return {"error": "TIMEOUT"}

Python — After (CaptchaAI)

import os
import time
import requests

API_KEY = os.environ["CAPTCHAAI_API_KEY"]

def solve_recaptcha_v2(sitekey, pageurl):
    # Submit — different endpoint and format
    resp = requests.post("https://ocr.captchaai.com/in.php", data={
        "key": API_KEY,
        "method": "userrecaptcha",
        "googlekey": sitekey,
        "pageurl": pageurl,
        "json": 1
    })
    data = resp.json()
    if data.get("status") != 1:
        return {"error": data.get("request")}

    captcha_id = data["request"]

    # Poll — GET instead of POST, different response format
    for _ in range(60):
        time.sleep(5)
        result = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": API_KEY,
            "action": "get",
            "id": captcha_id,
            "json": 1
        }).json()
        if result.get("status") == 1:
            return {"solution": result["request"]}
        if result.get("request") != "CAPCHA_NOT_READY":
            return {"error": result.get("request")}

    return {"error": "TIMEOUT"}

JavaScript — Before (NextCaptcha)

const axios = require("axios");
const CLIENT_KEY = "your_nextcaptcha_key";
const BASE_URL = "https://api.nextcaptcha.com";

async function solveRecaptchaV2(sitekey, pageurl) {
  const submit = await axios.post(`${BASE_URL}/createTask`, {
    clientKey: CLIENT_KEY,
    task: {
      type: "RecaptchaV2TaskProxyless",
      websiteURL: pageurl,
      websiteKey: sitekey,
    },
  });
  if (submit.data.errorId !== 0) return { error: submit.data.errorDescription };

  const taskId = submit.data.taskId;

  for (let i = 0; i < 60; i++) {
    await new Promise((r) => setTimeout(r, 5000));
    const poll = await axios.post(`${BASE_URL}/getTaskResult`, {
      clientKey: CLIENT_KEY,
      taskId,
    });
    if (poll.data.status === "ready") return { solution: poll.data.solution.gRecaptchaResponse };
    if (poll.data.errorId !== 0) return { error: poll.data.errorDescription };
  }
  return { error: "TIMEOUT" };
}

JavaScript — After (CaptchaAI)

const axios = require("axios");
const API_KEY = process.env.CAPTCHAAI_API_KEY;

async function solveRecaptchaV2(sitekey, pageurl) {
  const submit = await axios.post("https://ocr.captchaai.com/in.php", null, {
    params: { key: API_KEY, method: "userrecaptcha", googlekey: sitekey, pageurl, json: 1 },
  });
  if (submit.data.status !== 1) return { error: submit.data.request };

  const captchaId = submit.data.request;

  for (let i = 0; i < 60; i++) {
    await new Promise((r) => setTimeout(r, 5000));
    const poll = await axios.get("https://ocr.captchaai.com/res.php", {
      params: { key: API_KEY, action: "get", id: captchaId, json: 1 },
    });
    if (poll.data.status === 1) return { solution: poll.data.request };
    if (poll.data.request !== "CAPCHA_NOT_READY") return { error: poll.data.request };
  }
  return { error: "TIMEOUT" };
}

Response Format Differences

Submit Response

Field NextCaptcha CaptchaAI
Success check errorId === 0 status === 1
Task ID taskId (integer) request (string)
Error message errorDescription request (error code string)

Poll Response

Field NextCaptcha CaptchaAI
Ready check status === "ready" status === 1
Not ready status === "processing" request === "CAPCHA_NOT_READY"
Solution solution.gRecaptchaResponse request
Error errorDescription request (error code)

Migration Checklist

Step Status
Create CaptchaAI account and add funds
Map all createTask types to CaptchaAI methods
Replace clientKey with CaptchaAI API key
Update submit from JSON body POST to form POST
Update poll from POST to GET with query params
Update response parsing (status/request format)
Run parallel comparison test
Cut over production traffic

Troubleshooting

Issue Cause Fix
ERROR_KEY_DOES_NOT_EXIST Using NextCaptcha clientKey Replace with CaptchaAI API key
Response parsing breaks Different JSON structure Update to check status (integer) and request fields
ERROR_WRONG_USER_KEY Malformed API key Verify key format from CaptchaAI dashboard
Task types not recognized Using NextCaptcha type names Map to CaptchaAI method values (see table above)

FAQ

NextCaptcha uses JSON POST for everything. Does CaptchaAI require form-encoded data?

CaptchaAI accepts both form-encoded (application/x-www-form-urlencoded) and JSON requests. The in.php endpoint works with form data, and polling uses simple GET parameters.

How do I handle proxy tasks during migration?

In NextCaptcha, proxy tasks use type names like RecaptchaV2Task. In CaptchaAI, add proxy=user:pass@host:port and proxytype=HTTP parameters to the same method.

What about callback/webhook support?

CaptchaAI supports pingback parameter — provide a URL and CaptchaAI will POST the result when ready, similar to NextCaptcha's callback functionality.

Next Steps

Get faster solve times with CaptchaAI — create your account and switch your integration in minutes.

Related guides:

Discussions (0)

No comments yet.