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:
/createTaskpasa ain.php. - El formato de la solicitud: de cuerpo JSON a parámetros de formulario.
- El análisis de la respuesta: de
errorId/taskIdastatus/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
- Crea una cuenta en CaptchaAI y añade saldo.
- Asigna cada tipo
createTaska sumethod. - Sustituye
clientKeypor tu clave API. - Cambia el envío de JSON a formulario POST.
- Cambia el sondeo de POST a GET.
- Ajusta el análisis al formato
status/request. - Ejecuta una prueba en paralelo.
- 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 elclientKey; cámbialo por tu clave API de CaptchaAI.- El análisis se rompe: lee los campos
status(entero) yrequest. 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: