Reference

Переход с NextCaptcha на CaptchaAI: полное руководство

Переход с NextCaptcha на CaptchaAI не требует переписывать логику решения CAPTCHA — меняются только эндпоинт, формат тела запроса (JSON → form-data) и поля ответа (status/request вместо errorId/taskId). Дальше — по шагам: что делать, как сопоставляются оба API и готовый код на Python и JavaScript, который можно взять за основу.

Чек-лист миграции: что нужно сделать

  1. Создать аккаунт CaptchaAI и пополнить баланс.
  2. Сопоставить все типы createTask с методами CaptchaAI (таблица ниже).
  3. Заменить clientKey на API-ключ CaptchaAI.
  4. Перевести отправку из JSON-тела POST в form-data POST.
  5. Перевести опрос с POST на GET с query-параметрами.
  6. Обновить разбор ответа под формат status/request.
  7. Запустить параллельный сравнительный тест на части трафика.
  8. Постепенно перевести оставшийся продакшн-трафик.

Сопоставление эндпоинтов NextCaptcha и CaptchaAI

Действие NextCaptcha CaptchaAI
Отправить задачу POST /createTask POST https://ocr.captchaai.com/in.php
Получить результат POST /getTaskResult GET https://ocr.captchaai.com/res.php
Проверить баланс POST /getBalance GET res.php?action=getbalance&key=KEY

JSON против form-data: как отличается тело запроса

Как выглядит запрос в NextCaptcha (тело JSON)

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

Тот же запрос в CaptchaAI (параметры формы)

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

Поля запроса и типы задач

Прямое соответствие полей между API:

  • clientKeykey — API-ключ.
  • task.typemethod — см. сопоставление типов ниже.
  • task.websiteURLpageurl — URL целевой страницы.
  • task.websiteKeygooglekey или sitekey — ключ сайта для токена CAPTCHA.
  • task.recaptchaDataSValuedata-s — параметр reCAPTCHA.
  • task.isInvisibleinvisible=1 — невидимая reCAPTCHA.
  • task.pageActionaction — действие reCAPTCHA v3.
  • taskIdid — ID задачи для опроса.

Сопоставление типов задач

Тип задачи NextCaptcha Метод + параметры CaptchaAI
RecaptchaV2TaskProxyless method=userrecaptcha
RecaptchaV2Task method=userrecaptcha + proxy, proxytype
ImageToTextTask method=base64 + body
TurnstileTaskProxyless method=turnstile

HCaptchaTaskProxyless/HCaptchaTask аналога не имеют: hCaptcha CaptchaAI пока не поддерживает, такие задачи придётся временно оставить на другом провайдере.

Миграция кода: Python и JavaScript

Python — было (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 — стало (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 — было (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 — стало (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" };
}

Формат ответа: что меняется в парсинге

Ответ на отправку задачи:

  • Проверка успеха: errorId === 0 (NextCaptcha) → status === 1 (CaptchaAI).
  • Идентификатор задачи: taskId, целое число → request, строка.
  • Сообщение об ошибке: errorDescriptionrequest (строка с кодом ошибки).

Ответ при опросе:

  • Проверка готовности: status === "ready"status === 1.
  • Ещё не готово: status === "processing"request === "CAPCHA_NOT_READY".
  • Решение: solution.gRecaptchaResponserequest.
  • Ошибка: errorDescriptionrequest (код ошибки).

Совет: заведите общую функцию-адаптер для разбора ответа CaptchaAI (status/request), а не проверяйте условия россыпью по коду — так меньше шансов пропустить место, где ещё ждут старый формат NextCaptcha.

Типичные ошибки при переходе

  • ERROR_KEY_DOES_NOT_EXIST — в запросе всё ещё передаётся clientKey от NextCaptcha; замените его на API-ключ CaptchaAI.
  • Разбор ответа падает с ошибкой — код рассчитан на JSON-структуру NextCaptcha; проверяйте поля status (число) и request, структура CaptchaAI другая.
  • ERROR_WRONG_USER_KEY — API-ключ передан в неверном формате; сверьте его с панелью управления CaptchaAI.
  • Тип задачи не распознаётся — в коде остались названия типов NextCaptcha (RecaptchaV2TaskProxyless и подобные); сопоставьте их со значениями method из таблицы выше.

Пример: параллельный запуск для парсинг-команды

Команда, которая парсит витрины или проверяет доступность товаров под нагрузкой, обычно не отключает NextCaptcha резко: часть трафика (например, 10–20% задач по хэшу) направляется в CaptchaAI параллельно, остальное — как раньше, а провайдеры сравниваются по доле успешных решений и времени ответа на одних и тех же типах CAPTCHA. Для такого теста хватает тарифа BASIC ($15/мес, 5 потоков) — он покрывает репрезентативный объём задач до полного переключения.

Совет: если инфраструктура парсера развёрнута в европейских регионах или в Казахстане, отдельно замерьте RTT до ocr.captchaai.com, а не полагайтесь на цифры из документации — реальная сетевая задержка зависит от маршрута конкретного провайдера.

FAQ

CaptchaAI принимает JSON-тело запроса, как в NextCaptcha, или только form-data?

Оба варианта. in.php штатно работает с form-data, но принимает и JSON — часть клиентского кода можно оставить без изменений, сменив только эндпоинт и имена полей.

Что делать с задачами, которые уже стоят в очереди NextCaptcha на момент переключения?

Не обрывайте их резко. Держите оба интеграционных пути активными до полного израсходования очереди NextCaptcha, направляя в CaptchaAI только новые задачи.

Нужно ли получать новый sitekey при переходе на CaptchaAI?

Нет. sitekey/googlekey — это идентификатор виджета CAPTCHA на стороне целевого сайта, а не значение, которое выдаёт провайдер-решатель. Он остаётся тем же, меняется только имя поля в запросе.

Поддерживает ли CaptchaAI callback/webhook, как NextCaptcha?

Да. Параметр pingback принимает URL, на который CaptchaAI отправит POST с результатом сразу после решения — аналог callback-механизма NextCaptcha, только без отдельного колбэк-эндпоинта.

Дальнейшие шаги

Комментарии для этой статьи отключены.