Referencia

Cómo migrar de NextCaptcha a CaptchaAI

Migrar de NextCaptcha a CaptchaAI no te obliga a reescribir la lógica de resolución. NextCaptcha usa una API REST en JSON con /createTask y /getTaskResult; CaptchaAI usa el formato in.php/res.php, el mismo de las integraciones estilo 2Captcha. Para una agencia que factura en moneda local volátil hay un incentivo extra: se cobra por thread concurrente, no por resolución, en USD desde BASIC ($15/mes, 5 threads).

Qué cambia al migrar de NextCaptcha a CaptchaAI

Toda la migración se reduce a tres ajustes:

  • El endpoint: /createTask pasa a in.php.
  • El formato de la solicitud: de cuerpo JSON a parámetros de formulario.
  • El análisis de la respuesta: de errorId/taskId a status/request.
Acción NextCaptcha CaptchaAI
Enviar tarea POST /createTask POST https://ocr.captchaai.com/in.php
Obtener resultado POST /getTaskResult GET https://ocr.captchaai.com/res.php
Consultar saldo POST /getBalance GET res.php?action=getbalance&key=KEY

Traducción de parámetros y tipos de tarea

Cada campo del objeto task de NextCaptcha tiene su equivalente como parámetro de CaptchaAI:

Campo en NextCaptcha Campo en CaptchaAI Notas
clientKey key clave API
task.type method ver mapeo de tipos abajo
task.websiteURL pageurl URL de destino
task.websiteKey googlekey o sitekey clave del sitio
task.recaptchaDataSValue data-s parámetro data-s
task.isInvisible invisible=1 reCAPTCHA invisible
task.pageAction action acción de reCAPTCHA v3
taskId id ID para el sondeo

El tipo de tarea se traduce a un valor de method; en las variantes con proxy solo añades proxy y proxytype:

Tipo en NextCaptcha Método + parámetros en CaptchaAI
RecaptchaV2TaskProxyless method=userrecaptcha
RecaptchaV2Task method=userrecaptcha + proxy, proxytype
HCaptchaTaskProxyless No compatible por ahora
HCaptchaTask No compatible por ahora
ImageToTextTask method=base64 + body
TurnstileTaskProxyless method=turnstile

Aviso importante: CaptchaAI no resuelve hCaptcha, así que las tareas HCaptchaTask no tienen equivalente.

Del cuerpo JSON a los parámetros de formulario

NextCaptcha anida la tarea en un objeto JSON; CaptchaAI recibe los mismos datos como parámetros de formulario en in.php.

{
  "clientKey": "next_captcha_key",
  "task": {
    "type": "RecaptchaV2TaskProxyless",
    "websiteURL": "https://example.com",
    "websiteKey": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-"
  }
}
POST https://ocr.captchaai.com/in.php
key=YOUR_API_KEY&method=userrecaptcha&googlekey=6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-&pageurl=https://example.com&json=1

Migración del código: Python y JavaScript

El patrón envío-sondeo es el mismo; cambian el endpoint, el cuerpo y los campos que compruebas. Compara ambas versiones y sustituye función por función.

Python: antes (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: después (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: antes (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: después (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" };
}

Cómo cambia el formato de respuesta

Lo que más suele romper el análisis es la respuesta: NextCaptcha marca el éxito con errorId === 0 y devuelve enteros; CaptchaAI usa status === 1 y devuelve cadenas en request.

Campo (envío) NextCaptcha CaptchaAI
Comprobación de éxito errorId === 0 status === 1
ID de tarea taskId (entero) request (cadena)
Mensaje de error errorDescription request (cadena con el código)
Campo (sondeo) NextCaptcha CaptchaAI
Comprobación de listo status === "ready" status === 1
Aún no listo status === "processing" request === "CAPCHA_NOT_READY"
Solución solution.gRecaptchaResponse request
Error errorDescription request (código de error)

Lista de verificación para migrar a CaptchaAI

  1. Crea una cuenta en CaptchaAI y añade saldo.
  2. Asigna cada tipo createTask a su method.
  3. Sustituye clientKey por tu clave API.
  4. Cambia el envío de JSON a formulario POST.
  5. Cambia el sondeo de POST a GET.
  6. Ajusta el análisis al formato status/request.
  7. Ejecuta una prueba en paralelo.
  8. Migra producción gradualmente.

Errores frecuentes durante la migración

Casi todos los fallos vienen de una clave heredada o de un análisis que espera el JSON antiguo:

  • ERROR_KEY_DOES_NOT_EXIST: sigues usando el clientKey; cámbialo por tu clave API de CaptchaAI.
  • El análisis se rompe: lee los campos status (entero) y request.
  • ERROR_WRONG_USER_KEY: clave mal formada; verifícala en el panel de control.
  • Tipos no reconocidos: asigna los nombres de NextCaptcha a valores method (ver tabla).

Preguntas frecuentes

¿Puedo ejecutar NextCaptcha y CaptchaAI en paralelo durante la migración?

Sí, y es lo recomendable. Envía la misma tarea a ambos servicios unos días y compara resultados antes de cortar producción, validando el nuevo análisis con carga real.

¿CaptchaAI resuelve los mismos tipos que NextCaptcha?

En su mayoría, con una excepción: no resuelve hCaptcha. Sí cubre reCAPTCHA v2/v3 y Enterprise, Cloudflare Turnstile y Challenge, GeeTest v3, imagen/OCR, grid-image y BLS; CaptchaFox, Friendly Captcha y Lemin están en beta.

¿Cómo paso mis tareas con proxy?

Conservas el mismo method y añades proxy=user:pass@host:port y proxytype=HTTP. No hay un tipo de tarea aparte: el proxy son solo dos parámetros extra.

¿Qué plan necesito para mi volumen actual?

Depende de tu concurrencia, no del total de resoluciones: se factura por thread con resoluciones ilimitadas. BASIC ($15/mes, 5 threads) cubre volúmenes moderados; ADVANCE ($90/mes, 50 threads) da más margen.

Empieza tu migración a CaptchaAI

Consigue tiempos de resolución competitivos con CaptchaAI: crea tu cuenta y cambia tu integración en minutos.

Guías relacionadas:

Los comentarios están deshabilitados para este artículo.