Reference

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

Меняются всего два значения — базовый URL и API-ключ, весь остальной формат запроса остаётся прежним: AZCaptcha и CaptchaAI используют один и тот же 2Captcha-совместимый API. Поэтому реальная миграция обычно занимает 15–30 минут на одну кодовую базу, а не переписывание интеграции с нуля. Ниже — готовый код на Python и Node.js «до/после», независимая от поставщика обёртка для быстрого отката, параллельный тест, а следом справочные таблицы по эндпоинтам и параметрам на случай, если что-то не совпадёт.

Пошаговый перенос интеграции

Четыре шага, в этом порядке: сначала ключ, затем код, затем обёртка для отката, и только потом — переключение трафика.

Шаг 1. Получите API-ключ CaptchaAI

  1. Зарегистрируйтесь на captchaai.com
  2. Пополните баланс аккаунта
  3. Скопируйте API-ключ из панели управления

Ключ понадобится в следующем шаге — сохраните его в переменную окружения, а не прямо в коде.

Шаг 2. Обновите код

Дальше — построчное сравнение старого и нового кода на Python и JavaScript.

Python — до (AZCaptcha)

import requests

API_KEY = "your_azcaptcha_key"

def solve_recaptcha(sitekey, pageurl):
    # Submit
    resp = requests.post("https://azcaptcha.com/in.php", data={
        "key": API_KEY,
        "method": "userrecaptcha",
        "googlekey": sitekey,
        "pageurl": pageurl,
        "json": 1
    })
    data = resp.json()
    if data["status"] != 1:
        return {"error": data["request"]}

    captcha_id = data["request"]

    # Poll
    import time
    for _ in range(60):
        time.sleep(5)
        result = requests.get("https://azcaptcha.com/res.php", params={
            "key": API_KEY, "action": "get", "id": captcha_id, "json": 1
        }).json()
        if result["status"] == 1:
            return {"solution": result["request"]}
        if result["request"] != "CAPCHA_NOT_READY":
            return {"error": result["request"]}

    return {"error": "TIMEOUT"}

Python — после (CaptchaAI)

import os
import time
import requests

API_KEY = os.environ["CAPTCHAAI_API_KEY"]  # Changed: use env var

def solve_recaptcha(sitekey, pageurl):
    # Submit — only URL changed
    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 — only URL changed
    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 — тоже один URL меняется, остальное без правок:

JavaScript — до (AZCaptcha)

const axios = require("axios");
const API_KEY = "your_azcaptcha_key";

async function solveRecaptcha(sitekey, pageurl) {
  const submit = await axios.post("https://azcaptcha.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://azcaptcha.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" };
}

JavaScript — после (CaptchaAI)

const axios = require("axios");
const API_KEY = process.env.CAPTCHAAI_API_KEY;  // Changed: env var

async function solveRecaptcha(sitekey, pageurl) {
  // Only URLs changed
  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" };
}

Шаг 3. Абстрагируйте поставщика

Для безопасного отката оберните вызовы в независимый от поставщика класс — переключение сведётся к одной строке:

import os
import time
import requests


class CaptchaProvider:
    def __init__(self, base_url, api_key):
        self.submit_url = f"{base_url}/in.php"
        self.result_url = f"{base_url}/res.php"
        self.api_key = api_key
        self.session = requests.Session()

    def solve(self, sitekey, pageurl, method="userrecaptcha"):
        resp = self.session.post(self.submit_url, data={
            "key": self.api_key,
            "method": method,
            "googlekey": sitekey,
            "pageurl": pageurl,
            "json": 1
        })
        data = resp.json()
        if data.get("status") != 1:
            return {"error": data.get("request")}

        captcha_id = data["request"]
        for _ in range(60):
            time.sleep(5)
            result = self.session.get(self.result_url, params={
                "key": self.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"}


# Switch by changing one line:
# provider = CaptchaProvider("https://azcaptcha.com", "old_key")
provider = CaptchaProvider(
    "https://ocr.captchaai.com",
    os.environ["CAPTCHAAI_API_KEY"]
)

Теперь у вас есть единая точка переключения между поставщиками. Прежде чем менять продакшен, убедитесь на цифрах, что новый поставщик действительно быстрее и стабильнее — для этого нужен параллельный тест.

Шаг 4. Запустите оба поставщика параллельно

Перед переключением сравните оба поставщика на одинаковой нагрузке:

def parallel_test(sitekey, pageurl, runs=10):
    azcaptcha = CaptchaProvider("https://azcaptcha.com", "old_key")
    captchaai = CaptchaProvider(
        "https://ocr.captchaai.com",
        os.environ["CAPTCHAAI_API_KEY"]
    )

    results = {"azcaptcha": [], "captchaai": []}

    for i in range(runs):
        start = time.time()
        az_result = azcaptcha.solve(sitekey, pageurl)
        results["azcaptcha"].append({
            "success": "solution" in az_result,
            "time": time.time() - start
        })

        start = time.time()
        cai_result = captchaai.solve(sitekey, pageurl)
        results["captchaai"].append({
            "success": "solution" in cai_result,
            "time": time.time() - start
        })

    for provider, data in results.items():
        successes = sum(1 for r in data if r["success"])
        avg_time = sum(r["time"] for r in data) / len(data)
        print(f"{provider}: {successes}/{runs} success, {avg_time:.1f}s avg")

Логи параллельного теста храните обезличенными — без sitekey реальных клиентских сайтов и без чужих cookie, особенно если команда отчитывается по 152-ФЗ «О персональных данных» или соблюдает GDPR для клиентов из ЕС.

Чем отличаются эндпоинты AZCaptcha и CaptchaAI

Как видно из кода выше, хост меняется, а пути — нет: in.php для отправки задачи и res.php для получения результата остаются теми же самыми путями. Полная таблица — на случай, если переносите не только reCAPTCHA, но и другие типы:

Действие AZCaptcha CaptchaAI
Отправить задачу https://azcaptcha.com/in.php https://ocr.captchaai.com/in.php
Получить результат https://azcaptcha.com/res.php https://ocr.captchaai.com/res.php
Проверить баланс res.php?action=getbalance res.php?action=getbalance
Сообщить о неверном решении res.php?action=reportbad res.php?action=reportbad

Что меняется в параметрах запроса

Почти все параметры совпадают один в один, и их можно перенести без изменений. Разница только в значении самого ключа:

Параметр AZCaptcha CaptchaAI Примечание
key API-ключ API-ключ Другой ключ — получите свой на captchaai.com
method userrecaptcha userrecaptcha Без изменений
googlekey sitekey sitekey Без изменений
pageurl URL страницы URL страницы Без изменений
json 1 1 Без изменений
proxy user:pass@host:port user:pass@host:port Тот же формат
proxytype HTTP/SOCKS5 HTTP/SOCKS5 Без изменений

Сколько потоков брать вместо тарифа AZCaptcha

CaptchaAI тарифицирует не решения, а параллельные потоки, поэтому при переходе стоит ориентироваться на пиковую одновременную нагрузку, а не на суточный объём задач. Команда, которая держит около 10–15 одновременных задач reCAPTCHA v2, обычно укладывается в STANDARD ($30/мес, 15 потоков); при устойчивом пике в 40–50 задач разумнее сразу взять ADVANCE ($90/мес, 50 потоков). Для агентств и фрилансеров, которые выставляют счета клиентам в долларах, а не в местной валюте, это заодно и предсказуемая фиксированная строка в бюджете вместо плавающей цены за решение, которая зависит от курса.

Чек-лист миграции

Держите этот список рядом с тикетом на миграцию — он покрывает всё, от первого пополнения баланса до вывода старого ключа из эксплуатации:

Шаг Статус
Создать аккаунт CaptchaAI и пополнить баланс
Заменить базовый URL во всех файлах
Обновить API-ключ (через переменную окружения)
Запустить параллельный тест (от 10 решений)
Сравнить долю успешных решений
Сравнить время решения
Обновить мониторинг и алерты под новые эндпоинты
Переключить продакшен-трафик
Понаблюдать за метриками 24 часа
Вывести ключ AZCaptcha из эксплуатации

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

Если что-то из чек-листа выше не сходится, начните отсюда — это самые частые причины сбоя после переключения:

Проблема Причина Решение
ERROR_KEY_DOES_NOT_EXIST Неверный API-ключ Проверьте API-ключ CaptchaAI в панели управления
ERROR_ZERO_BALANCE На новом аккаунте нет средств Пополните баланс на captchaai.com
Коды ошибок не совпадают один в один У сервисов небольшие расхождения в кодах ошибок Сопоставьте коды заранее — большинство совпадают напрямую
Доля успешных решений заметно отличается У сервисов разные пулы солверов Запустите от 50 тестовых решений — на 10 запусках разброс не показателен статистически

Частые вопросы

Нужно ли переписывать логику опроса res.php?

Нет. Формат ответа, параметр action=get и код CAPCHA_NOT_READY идентичны AZCaptcha — меняется только базовый URL, сам цикл опроса переносится без изменений.

Сколько потоков CaptchaAI взять вместо текущего тарифа AZCaptcha?

Считайте по пиковой одновременной нагрузке, а не по суточному объёму задач: одна задача занимает один поток, а решений на поток — без ограничения. Ориентиры по планам приведены в разделе выше.

Заработает ли текущая настройка прокси после перехода?

Да, без изменений. CaptchaAI принимает те же параметры proxy и proxytype в том же формате user:pass@host:port — переписывать прокси-конфигурацию не нужно.

Сколько времени займёт вся миграция?

Для одной кодовой базы — обычно 15–30 минут: большая часть времени уходит на замену базового URL через поиск-и-замену и на запуск параллельного теста для проверки результата.

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

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