Integraciones

Oxylabs + CaptchaAI: integración de proxy del centro de datos

La decisión al montar un scraper protegido por CAPTCHA es corta: deja que Oxylabs se encargue de la salida de red y que CaptchaAI resuelva cada reCAPTCHA v2 o Cloudflare Turnstile. El centro de datos da velocidad y volumen; los residenciales generan menos desafíos. En ambos casos el CAPTCHA deja de ser un muro y pasa a ser una llamada a la API. Esta guía conecta los proxies de Oxylabs con CaptchaAI en Python, con ejemplos listos para copiar. Si ya vienes de 2Captcha o Anti-Captcha, la integración es familiar: CaptchaAI expone los mismos endpoints in.php / res.php, así que reutilizas casi toda tu lógica de envío y sondeo.

En este montaje cada pieza tiene un papel claro:

  • Oxylabs aporta la salida de red: IP, rotación y país de origen de la petición.
  • CaptchaAI resuelve el desafío y te devuelve el token que valida el formulario.
  • Tu código orquesta ambos: obtiene la página, detecta el sitekey y envía el token.

Qué proxy de Oxylabs elegir

Oxylabs tiene varias familias de proxies y no todas encajan igual con un flujo con CAPTCHA. Esta tabla resume cuándo tira cada una:

Producto IP Velocidad Caso de uso
Datacenter Proxies 2 M+ Muy rápida Alto volumen, prioridad a la velocidad
Residential Proxies 100 M+ Media Sitios sensibles a CAPTCHA
ISP Proxies Grado residencial Rápida E-commerce, redes sociales
Mobile Proxies 20 M+ Lenta Objetivos móviles
SERP Scraper API Gestionado Rápida Resultados de Google/Bing

El atajo mental: objetivo sensible, IP residencial; prioridad a la velocidad, centro de datos, porque CaptchaAI absorbe los CAPTCHA que se generen de todos modos.


Integración en Python con requests

Enruta la petición por el proxy de Oxylabs y delega el reCAPTCHA en CaptchaAI. El sufijo -cc-{country} fija el país de salida. La función solve_recaptcha envía la tarea a in.php, luego sondea res.php cada cinco segundos: mientras la respuesta sea CAPCHA_NOT_READY sigue esperando, y devuelve el token en cuanto está resuelto o lanza un TimeoutError tras el límite de intentos.

import requests
import time

OXYLABS_USER = "customer-USERNAME"
OXYLABS_PASS = "PASSWORD"
OXYLABS_ENDPOINT = "pr.oxylabs.io:7777"

CAPTCHAAI_KEY = "YOUR_API_KEY"
CAPTCHAAI_URL = "https://ocr.captchaai.com"

# Residential rotating proxy
proxies = {
    "http": f"http://{OXYLABS_USER}:{OXYLABS_PASS}@{OXYLABS_ENDPOINT}",
    "https": f"http://{OXYLABS_USER}:{OXYLABS_PASS}@{OXYLABS_ENDPOINT}",
}


def fetch_page(url, country=None):
    """Fetch page through Oxylabs proxy."""
    user = OXYLABS_USER
    if country:
        user += f"-cc-{country}"

    proxy = {
        "http": f"http://{user}:{OXYLABS_PASS}@{OXYLABS_ENDPOINT}",
        "https": f"http://{user}:{OXYLABS_PASS}@{OXYLABS_ENDPOINT}",
    }

    return requests.get(
        url,
        proxies=proxy,
        headers={
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
            "AppleWebKit/537.36 Chrome/126.0.0.0 Safari/537.36"
        },
        timeout=30,
    )


def solve_recaptcha(site_url, sitekey):
    """Solve via CaptchaAI."""
    resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data={
        "key": CAPTCHAAI_KEY,
        "method": "userrecaptcha",
        "googlekey": sitekey,
        "pageurl": site_url,
        "json": 1,
    })
    data = resp.json()
    if data["status"] != 1:
        raise Exception(f"Submit: {data['request']}")

    task_id = data["request"]

    for _ in range(60):
        time.sleep(5)
        resp = requests.get(f"{CAPTCHAAI_URL}/res.php", params={
            "key": CAPTCHAAI_KEY,
            "action": "get",
            "id": task_id,
            "json": 1,
        })
        data = resp.json()
        if data["request"] == "CAPCHA_NOT_READY":
            continue
        if data["status"] == 1:
            return data["request"]
        raise Exception(f"Solve: {data['request']}")

    raise TimeoutError("Timeout")

Mantener la misma IP con sesiones persistentes

Si el formulario carga el CAPTCHA en una petición y valida el token en otra, necesitas la misma IP en ambas: la sesión persistente de Oxylabs se activa con el sufijo -sessid-{session_id}.

def get_oxylabs_sticky_proxy(session_id, country=None):
    """Create Oxylabs sticky session (same IP)."""
    user = OXYLABS_USER + f"-sessid-{session_id}"
    if country:
        user += f"-cc-{country}"

    proxy_url = f"http://{user}:{OXYLABS_PASS}@{OXYLABS_ENDPOINT}"
    return {"http": proxy_url, "https": proxy_url}


# CAPTCHA workflow with sticky IP
import random, string
session = "".join(random.choices(string.ascii_lowercase, k=8))
proxy = get_oxylabs_sticky_proxy(session, country="us")

# All requests use the same IP
resp = requests.get("https://target.com/form", proxies=proxy)
# ... solve CAPTCHA ...
resp = requests.post("https://target.com/submit", proxies=proxy, data={
    "g-recaptcha-response": token,
})

Oxylabs Web Scraper API + CaptchaAI

Si el renderizado propio de Oxylabs no basta, la Web Scraper API te entrega el HTML renderizado y CaptchaAI resuelve en cuanto detectas un data-sitekey.

def scrape_with_oxylabs_api(url):
    """Use Oxylabs Web Scraper API for rendering, CaptchaAI for CAPTCHAs."""
    resp = requests.post(
        "https://realtime.oxylabs.io/v1/queries",
        auth=(OXYLABS_USER, OXYLABS_PASS),
        json={
            "source": "universal",
            "url": url,
            "render": "html",
            "browser_instructions": [
                {"type": "wait", "wait_time_s": 3},
            ],
        },
    )

    result = resp.json()
    html = result["results"][0]["content"]

    # Check for CAPTCHA in rendered HTML
    import re
    sitekey_match = re.search(r'data-sitekey="([^"]+)"', html)

    if sitekey_match:
        sitekey = sitekey_match.group(1)
        token = solve_recaptcha(url, sitekey)
        return {"html": html, "captcha_solved": True, "token": token}

    return {"html": html, "captcha_solved": False}

Centro de datos vs residencial ante los CAPTCHA

Decide por objetivo, no para todo el proyecto: residencial para los dominios que reaccionan al tráfico automatizado y centro de datos para el resto, donde manda la velocidad. smart_proxy_selection encapsula esa lógica en una sola función, de modo que el resto del pipeline no tiene que saber qué tipo de IP está usando.

# Datacenter: Fast but higher CAPTCHA rate
DC_PROXY = {
    "http": f"http://{OXYLABS_USER}:{OXYLABS_PASS}@dc.pr.oxylabs.io:10000",
    "https": f"http://{OXYLABS_USER}:{OXYLABS_PASS}@dc.pr.oxylabs.io:10000",
}

# Residential: Slower but lower CAPTCHA rate
RES_PROXY = {
    "http": f"http://{OXYLABS_USER}:{OXYLABS_PASS}@pr.oxylabs.io:7777",
    "https": f"http://{OXYLABS_USER}:{OXYLABS_PASS}@pr.oxylabs.io:7777",
}


def smart_proxy_selection(url, captcha_sensitive=True):
    """Pick proxy type based on target site sensitivity."""
    if captcha_sensitive:
        return RES_PROXY  # Less likely to trigger CAPTCHA
    return DC_PROXY  # Faster, CaptchaAI handles any CAPTCHAs

Pipeline concurrente

CaptchaAI factura por thread concurrente, sin coste por resolución. Este ThreadPoolExecutor procesa varias URL en paralelo, cada una con su sesión persistente. Ajusta max_workers a los threads de tu plan: con 5 threads del plan BASIC, cinco resoluciones simultáneas mantienen el pipeline saturado sin desperdiciar capacidad.

from concurrent.futures import ThreadPoolExecutor, as_completed

def process_url(url):
    session = "".join(random.choices(string.ascii_lowercase, k=8))
    proxy = get_oxylabs_sticky_proxy(session, country="us")

    try:
        resp = requests.get(url, proxies=proxy, timeout=30)

        import re
        match = re.search(r'data-sitekey="([^"]+)"', resp.text)

        if match:
            token = solve_recaptcha(url, match.group(1))
            return {"url": url, "status": "solved"}
        return {"url": url, "status": "no_captcha"}

    except Exception as e:
        return {"url": url, "status": "error", "error": str(e)}


urls = ["https://site1.com", "https://site2.com", "https://site3.com"]

with ThreadPoolExecutor(max_workers=5) as executor:
    futures = {executor.submit(process_url, u): u for u in urls}
    for future in as_completed(futures):
        print(future.result())

Escenario: monitoreo de precios en España y LATAM

Caso típico: una agencia que monitorea precios de la competencia en marketplaces del tipo MercadoLibre o en Amazon.es para un panel diario, donde el reCAPTCHA salta ante varios accesos seguidos desde la misma IP. Los proxies de centro de datos de Oxylabs procesan miles de solicitudes por hora y CaptchaAI resuelve los reCAPTCHA sin frenar el pipeline, con costo mensual predecible en USD. Respeta siempre los términos de servicio y la normativa de protección de datos aplicable (GDPR y LOPDGDD en España, LFPDPPP en México).


Errores comunes y cómo resolverlos

  • 403 desde el proxy: la IP está en una lista de bloqueo. Cambia a residencial o rota la IP.
  • Fallo de autenticación: endpoint incorrecto. Centro de datos: dc.pr.oxylabs.io:10000; residencial: pr.oxylabs.io:7777.
  • La sesión persistente caduca: dura unos 10 minutos por defecto. Genera un nuevo ID de sesión.
  • CAPTCHA en cada página: la IP de centro de datos está reconocida. Usa una salida de red residencial autorizada.
  • Respuesta lenta: latencia de la red residencial. Acéptala o cambia a los proxies de ISP.

Preguntas frecuentes

¿Cómo fijo el país de salida con Oxylabs?

Añade el sufijo -cc-{country} al usuario del proxy (por ejemplo, -cc-mx o -cc-es). Útil cuando el sitio cambia precios o contenido según la región.

¿Cuánto dura una sesión persistente y cómo la renuevo?

Por defecto ronda los 10 minutos. Cuando caduca, genera un nuevo session_id y reconstruye el proxy con -sessid- para obtener una IP fresca.

¿Qué tipos de CAPTCHA resuelve CaptchaAI en este flujo?

reCAPTCHA v2 y v3, Cloudflare Turnstile y Cloudflare Challenge, GeeTest v3, e imagen/OCR y grid. No resuelve hCaptcha ni FunCaptcha: planifica el objetivo según el tipo real de CAPTCHA.

¿Puedo resolver varios CAPTCHA en paralelo?

Sí. CaptchaAI factura por thread concurrente, no por resolución: el plan BASIC ($15/mes) incluye 5 threads y el STANDARD ($30/mes) sube a 15. Sube de plan cuando tu pipeline lance más resoluciones a la vez.

¿Es difícil migrar desde 2Captcha o Anti-Captcha?

No. CaptchaAI mantiene endpoints in.php / res.php compatibles con ese estilo de API, así que el cambio suele reducirse a apuntar la URL base a https://ocr.captchaai.com y usar tu nueva clave API; el flujo de envío y sondeo se queda casi igual.


Guías relacionadas


Combina la infraestructura de proxy de Oxylabs con la resolución de CaptchaAI: obtén tu clave API.

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