Integraciones

cURL + CaptchaAI: Resolución CLI CAPTCHA

Resolver un CAPTCHA con CaptchaAI son dos llamadas cURL: in.php envía la tarea, res.php recoge el token. Los SDK son azúcar sobre esas dos peticiones, y en un runner de CI sin Python ni Node.js la terminal es todo lo que tienes.

Qué necesitas antes de empezar

Requisito Detalles
cURL Cualquier versión moderna
jq (opcional) Para analizar respuestas
Clave API CaptchaAI Consigue uno aquí

Guarda la clave en CAPTCHAAI_API_KEY: en el historial del shell es una fuga silenciosa.

Los tres comandos que resumen la API

Consultar el saldo

curl -s "https://ocr.captchaai.com/res.php?key=YOUR_API_KEY&action=getbalance"

Salida: 1.234. Un número significa clave válida y red hacia el endpoint.

Enviar un reCAPTCHA v2

curl -s "https://ocr.captchaai.com/in.php?key=YOUR_API_KEY&method=userrecaptcha&googlekey=6Le-wvkS...&pageurl=https://example.com"

Salida: OK|73548291. Ese número es el ID de la tarea, no el token: la API es asíncrona.

Sondear el resultado

curl -s "https://ocr.captchaai.com/res.php?key=YOUR_API_KEY&action=get&id=73548291"

Salida: OK|03AGdBq24PBCbw... o CAPCHA_NOT_READY. Esto último no es un error —se escribe así, sin la "T", por compatibilidad histórica— sino la respuesta normal mientras la tarea sigue en cola.

Un script de Bash que puedes reutilizar

Para automatizar, envuelve envío y sondeo en una función con tiempo de espera en solve_captcha.sh:

#!/bin/bash
set -euo pipefail

API_KEY="${CAPTCHAAI_API_KEY:?Set CAPTCHAAI_API_KEY environment variable}"
BASE_URL="https://ocr.captchaai.com"

solve_recaptcha() {
    local site_key="$1"
    local page_url="$2"
    local timeout="${3:-300}"

    # Submit
    local response
    response=$(curl -s "${BASE_URL}/in.php?key=${API_KEY}&method=userrecaptcha&googlekey=${site_key}&pageurl=${page_url}")

    if [[ ! "$response" == OK|* ]]; then
        echo "ERROR: Submit failed: $response" >&2
        return 1
    fi

    local task_id="${response#OK|}"
    echo "Submitted task: $task_id" >&2

    # Poll
    local deadline=$((SECONDS + timeout))
    while (( SECONDS < deadline )); do
        sleep 5
        local result
        result=$(curl -s "${BASE_URL}/res.php?key=${API_KEY}&action=get&id=${task_id}")

        if [[ "$result" == "CAPCHA_NOT_READY" ]]; then
            echo "Waiting..." >&2
            continue
        fi

        if [[ "$result" == OK|* ]]; then
            echo "${result#OK|}"
            return 0
        fi

        echo "ERROR: Solve failed: $result" >&2
        return 1
    done

    echo "ERROR: Timeout after ${timeout}s" >&2
    return 1
}

# Usage: ./solve_captcha.sh SITE_KEY PAGE_URL
if [[ $# -ge 2 ]]; then
    solve_recaptcha "$1" "$2"
fi

Hazlo ejecutable:

chmod +x solve_captcha.sh

Y ejecútalo:

export CAPTCHAAI_API_KEY="your_key_here"
./solve_captcha.sh "6Le-wvkS..." "https://example.com"

Dos detalles importan: el token sale por stdout y el progreso por stderr, así lo capturas limpio; y el bucle tiene fecha límite, así un fallo de red no cuelga el job.

Otros tipos de CAPTCHA desde la misma terminal

Cloudflare Turnstile

Cambia method y el nombre de la clave pública (sitekey, no googlekey):

curl -s "https://ocr.captchaai.com/in.php?key=${CAPTCHAAI_API_KEY}&method=turnstile&sitekey=0x4AAAAA...&pageurl=https://example.com"

CAPTCHA de imagen y OCR

Codifica el archivo en base64 y envíalo:

# Encode image to base64
IMAGE_B64=$(base64 -w 0 captcha.png)

# Submit
curl -s "https://ocr.captchaai.com/in.php?key=${CAPTCHAAI_API_KEY}&method=base64&body=${IMAGE_B64}"

Con imágenes grandes, usa POST multipart:

curl -s -X POST "https://ocr.captchaai.com/in.php" \
  -F "key=${CAPTCHAAI_API_KEY}" \
  -F "method=post" \
  -F "[email protected]"

Por esta vía CaptchaAI cubre reCAPTCHA v2 y v3, Turnstile y Cloudflare Challenge, GeeTest v3, imagen/OCR, grid y BLS, más CaptchaFox (beta), Friendly Captcha (beta) y Lemin (beta). hCaptcha y FunCaptcha (Arkose Labs) no son compatibles; GeeTest v4, próximamente.

Del token al formulario en una tubería

El token solo sirve si acaba en el campo correcto. Este script encadena los dos pasos contra staging:

#!/bin/bash
# Solve CAPTCHA and submit form in one pipeline

API_KEY="${CAPTCHAAI_API_KEY}"
SITE_KEY="6Le-wvkS..."
TARGET_URL="https://staging.example.com/qa-login"

# Solve
TOKEN=$(./solve_captcha.sh "$SITE_KEY" "$TARGET_URL")

if [[ -z "$TOKEN" ]]; then
    echo "Failed to solve CAPTCHA"
    exit 1
fi

# Submit form with token
curl -s -X POST "$TARGET_URL" \
  -d "username=user" \
  -d "password=pass" \
  -d "g-recaptcha-response=${TOKEN}"

El campo es g-recaptcha-response porque el ejemplo es reCAPTCHA; con Turnstile, cf-turnstile-response. Equivocarse aquí da el fallo más frustrante: la resolución funciona y el backend rechaza el envío.

Lotes desde un archivo

Caso habitual: validar el alta de un portal de cita previa en varios entornos, sin navegador. Metes las URL en urls.txt:

#!/bin/bash
# Input file: urls.txt (one URL per line)

while IFS= read -r url; do
    echo "Processing: $url"
    TOKEN=$(./solve_captcha.sh "6Le-wvkS..." "$url")
    if [[ -n "$TOKEN" ]]; then
        echo "$url,$TOKEN" >> results.csv
        echo "  Solved ✓"
    else
        echo "  Failed ✗"
    fi
done < urls.txt

El plan BASIC ($15/mes, 5 threads) resuelve cinco en paralelo; STANDARD ($30/mes, 15 threads) y ADVANCE ($90/mes, 50 threads) amplían la concurrencia sin tocar el script: se factura por thread, no por resolución. Un costo fijo en USD, fácil de presupuestar para agencias y freelancers que facturan en moneda local.

PowerShell para runners Windows

La misma secuencia con Invoke-RestMethod:

$ApiKey = $env:CAPTCHAAI_API_KEY
$BaseUrl = "https://ocr.captchaai.com"

# Submit
$response = Invoke-RestMethod "${BaseUrl}/in.php?key=${ApiKey}&method=userrecaptcha&googlekey=6Le-wvkS...&pageurl=https://example.com"

if ($response -match '^OK\|(.+)$') {
    $taskId = $Matches[1]
    Write-Host "Task: $taskId"
} else {
    Write-Error "Submit failed: $response"
    exit 1
}

# Poll
do {
    Start-Sleep -Seconds 5
    $result = Invoke-RestMethod "${BaseUrl}/res.php?key=${ApiKey}&action=get&id=${taskId}"
} while ($result -eq 'CAPCHA_NOT_READY')

if ($result -match '^OK\|(.+)$') {
    $token = $Matches[1]
    Write-Host "Token: $token"
} else {
    Write-Error "Solve failed: $result"
}

Errores frecuentes y cómo resolverlos

Error Causa Solución
curl: (6) Could not resolve host Problema de DNS Comprueba la red
ERROR_WRONG_USER_KEY Clave API incorrecta Comprueba si hay espacios o saltos de línea en la clave
La respuesta está vacía. Timeout de red Añade --connect-timeout 30
base64: invalid input Problema con archivos binarios Usa base64 -w 0 (sin ajuste de línea)

ERROR_WRONG_USER_KEY rara vez es una clave inválida: casi siempre es un salto de línea al copiarla.

Configuración recomendada para tu pipeline

Si el CAPTCHA aparece en un test de navegador, usa el mismo viewport, idioma y user-agent en local, staging y CI:

from selenium import webdriver

def make_driver(headless: bool = True) -> webdriver.Chrome:
    options = webdriver.ChromeOptions()
    if headless:
        options.add_argument('--headless=new')
    options.add_argument('--window-size=1280,800')
    options.add_argument('--lang=es-ES')
    return webdriver.Chrome(options=options)

Cómo encaja CaptchaAI en tu integración

El patrón no cambia según el lenguaje ni el framework:

  1. Tu test detecta el widget en tu propia aplicación.
  2. Envía a CaptchaAI los datos públicos (sitekey, URL, tipo).
  3. CaptchaAI devuelve un token válido para esa página.
  4. Tu test lo inyecta en el campo y envía el formulario.
  5. Tu backend lo verifica, igual que con una persona.

Aplica a integraciones que tú controlas: respeta los términos de servicio y la normativa de datos aplicable.

Qué medir cuando ya corre solo

  • Tiempo de resolución — de la solicitud a la entrega del token.
  • Tasa de éxito por endpoint propio — verificaciones que pasan sobre el total.
  • Distribución de errores — por código (ERROR_*, tiempos de espera, red).
  • Latencia extremo a extremo — render, resolución y respuesta del backend.

Usa además una API key separada para QA y backoff exponencial en los reintentos.

Preguntas frecuentes

Las dudas que se repiten al llevar estos comandos a un script real.

¿Necesito jq para leer las respuestas?

No. La API devuelve texto plano OK|valor; la expansión de parámetros de Bash basta.

¿Qué hago si CAPCHA_NOT_READY no termina nunca?

Revisa el script antes que la clave. Tres causas cubren casi todo:

  • El pageurl no es la URL exacta del widget.
  • El sitekey es de otro entorno (staging frente a producción).
  • El bucle no tiene fecha límite y sondea una tarea ya descartada.

¿Cuántas resoluciones puedo lanzar a la vez?

Hasta el número de threads de tu plan: con BASIC ($15/mes), 5 simultáneas. Por encima, las solicitudes esperan turno.

¿Es seguro poner la clave en un secreto de CI?

Sí. Expórtala como variable de entorno y nunca la escribas literal en el comando: la línea queda visible en los logs de muchos runners.

Guías relacionadas

Valida tus integraciones CAPTCHA en entornos propios con CaptchaAI.

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