Casos de Uso

Automatización de comparación de cotizaciones de seguros con manejo de CAPTCHA

¿Comparas tarifas de varias aseguradoras de forma automática, pero cada formulario se detiene en un reCAPTCHA? Es la barrera que encuentra cualquier equipo de QA que prueba un comparador de seguros. La solución: envías el sitekey a la API de CaptchaAI, recuperas el token g-recaptcha-response y lo adjuntas al envío del formulario. El mismo patrón sirve para auto, hogar, salud y vida. En esta guía montamos un recopilador que consulta varias aseguradoras en paralelo y ordena las cotizaciones por precio.


Dónde aparece el CAPTCHA en un comparador de seguros

Los agregadores y las páginas de cada aseguradora protegen sus motores de tarifas con CAPTCHA para frenar la recopilación automática de precios. En un comparador tipo Rastreator o Acierto (España) o los agregadores de México y Argentina, el desafío salta justo al pedir el precio final.

Ramo CAPTCHA Punto de activación Complejidad de la cotización
Seguro de auto reCAPTCHA v2 Envío del formulario de cotización Multipaso (vehículo + conductor)
Seguro de salud reCAPTCHA v2 Comparación de planes Multipaso (datos demográficos)
Seguro de hogar Image CAPTCHA Búsqueda de dirección Moderada
Seguro de vida reCAPTCHA v2 Calculadora de tarifas Formulario sencillo
Seguro de viaje reCAPTCHA v2 Invisible Solicitud de cotización Formulario sencillo
Seguro comercial reCAPTCHA v3 Formulario de contacto/cotización Formulario largo

CaptchaAI resuelve las variantes de reCAPTCHA v2/v3 y los CAPTCHA de imagen (OCR), justo los tipos que verás aquí; esta guía asume pruebas sobre flujos autorizados.


Por qué cada cotización debe conservar la misma IP

Una restricción define todo el diseño: la cotización nunca es una sola petición, sino una secuencia de pasos que el servidor ata a tu sesión y a tu IP. Si la IP cambia a mitad del flujo, lo interpreta como una sesión nueva y descarta el progreso.

Paso Datos enviados Requisito de IP
1. Datos personales Nombre, fecha de nacimiento, código postal Misma IP
2. Vehículo/inmueble Año, marca, modelo Misma IP
3. Selección de cobertura Límites, deducible Misma IP
4. Resolución del CAPTCHA token Misma IP
5. Visualización de la cotización N/A Misma IP

Para estos flujos, mantén sesiones de salida persistentes con la misma IP autorizada y un TTL de 10 a 15 minutos, suficiente para completar los pasos sin invalidar la sesión.


Recopilador de cotizaciones multiaseguradora

El colector carga la página, envía los datos del vehículo y del conductor, resuelve el reCAPTCHA y devuelve el precio parseado. compare_carriers repite el proceso por aseguradora y ordena el resultado por prima mensual.

import requests
import time
import re
import base64

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


def solve_recaptcha(sitekey, pageurl):
    resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data={
        "key": CAPTCHAAI_KEY, "method": "userrecaptcha",
        "googlekey": sitekey, "pageurl": pageurl, "json": 1,
    })
    task_id = resp.json()["request"]
    for _ in range(60):
        time.sleep(5)
        result = requests.get(f"{CAPTCHAAI_URL}/res.php", params={
            "key": CAPTCHAAI_KEY, "action": "get",
            "id": task_id, "json": 1,
        })
        data = result.json()
        if data["request"] != "CAPCHA_NOT_READY":
            return data["request"]
    raise TimeoutError("Timeout")


def solve_image_captcha(image_bytes):
    img_b64 = base64.b64encode(image_bytes).decode()
    resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data={
        "key": CAPTCHAAI_KEY, "method": "base64",
        "body": img_b64, "json": 1,
    })
    task_id = resp.json()["request"]
    for _ in range(20):
        time.sleep(3)
        result = requests.get(f"{CAPTCHAAI_URL}/res.php", params={
            "key": CAPTCHAAI_KEY, "action": "get",
            "id": task_id, "json": 1,
        })
        data = result.json()
        if data["request"] != "CAPCHA_NOT_READY":
            return data["request"]
    raise TimeoutError("Timeout")


class InsuranceQuoteCollector:
    def __init__(self, proxy=None):
        self.session = requests.Session()
        if proxy:
            self.session.proxies = {"http": proxy, "https": proxy}
        self.session.headers.update({
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
            "AppleWebKit/537.36 Chrome/126.0.0.0 Safari/537.36",
        })

    def get_auto_quote(self, carrier_url, vehicle_data, driver_data, sitekey):
        """Get auto insurance quote from a single carrier."""
        # Step 1: Load quote page
        self.session.get(carrier_url)

        # Step 2: Submit vehicle info
        resp = self.session.post(f"{carrier_url}/vehicle", data=vehicle_data)

        # Step 3: Submit driver info
        resp = self.session.post(f"{carrier_url}/driver", data=driver_data)

        # Step 4: Solve CAPTCHA on quote page
        token = solve_recaptcha(sitekey, f"{carrier_url}/quote")

        # Step 5: Get quote
        resp = self.session.post(f"{carrier_url}/quote", data={
            "g-recaptcha-response": token,
        })

        if resp.status_code == 200:
            return self._parse_quote(resp.text)
        return None

    def compare_carriers(self, carriers, vehicle_data, driver_data):
        """Compare quotes across multiple carriers."""
        quotes = []

        for carrier in carriers:
            try:
                quote = self.get_auto_quote(
                    carrier_url=carrier["url"],
                    vehicle_data=vehicle_data,
                    driver_data=driver_data,
                    sitekey=carrier["sitekey"],
                )
                quotes.append({
                    "carrier": carrier["name"],
                    "status": "success",
                    "quote": quote,
                })
            except Exception as e:
                quotes.append({
                    "carrier": carrier["name"],
                    "status": "failed",
                    "error": str(e),
                })
            time.sleep(5)  # Delay between carriers

        # Sort by price
        successful = [q for q in quotes if q["status"] == "success" and q["quote"]]
        successful.sort(key=lambda x: x["quote"].get("monthly_premium", float("inf")))

        return {
            "quotes": quotes,
            "best_rate": successful[0] if successful else None,
            "total_compared": len(carriers),
            "successful": len(successful),
        }

    def _parse_quote(self, html):
        from bs4 import BeautifulSoup
        soup = BeautifulSoup(html, "html.parser")

        premium_el = soup.select_one(".premium, .monthly-rate, .quote-amount")
        coverage_el = soup.select_one(".coverage-summary, .plan-details")

        return {
            "monthly_premium": premium_el.get_text(strip=True) if premium_el else "",
            "coverage": coverage_el.get_text(strip=True) if coverage_el else "",
        }


# Usage
collector = InsuranceQuoteCollector(
    proxy="http://user-session-abc:pass@residential.proxy.com:5000"
)

vehicle = {
    "year": "2022",
    "make": "Toyota",
    "model": "Camry",
    "vin": "",
    "mileage": "15000",
}

driver = {
    "age": "35",
    "gender": "M",
    "zip": "90210",
    "driving_record": "clean",
}

carriers = [
    {"name": "Carrier A", "url": "https://carrier-a.example.com/auto", "sitekey": "6Lc_xxx1"},
    {"name": "Carrier B", "url": "https://carrier-b.example.com/auto", "sitekey": "6Lc_xxx2"},
    {"name": "Carrier C", "url": "https://carrier-c.example.com/auto", "sitekey": "6Lc_xxx3"},
]

comparison = collector.compare_carriers(carriers, vehicle, driver)
print(f"Best rate: {comparison['best_rate']}")

El time.sleep(5) entre aseguradoras no es opcional: el ritmo pausado evita que salte el límite de solicitudes. Como CaptchaAI cobra por thread concurrente y no por resolución, el volumen no encarece la cuenta: BASIC ($15/mes, 5 threads) resuelve 5 desafíos en paralelo y ADVANCE ($90/mes, 50 threads) da margen para comparar decenas a la vez.


Comparación de planes de seguro médico

El seguro de salud sigue el mismo esquema: envías datos demográficos en lugar de vehículo/conductor y parseas las tarjetas de plan del marketplace.

def compare_health_plans(marketplace_url, demographics, sitekey):
    """Compare health insurance plans on marketplace sites."""
    collector = InsuranceQuoteCollector(
        proxy="http://user-session-xyz:pass@residential.proxy.com:5000"
    )

    # Load marketplace
    collector.session.get(marketplace_url)

    # Submit demographics
    collector.session.post(f"{marketplace_url}/demographics", data=demographics)

    # Solve CAPTCHA for plan results
    token = solve_recaptcha(sitekey, f"{marketplace_url}/plans")

    resp = collector.session.post(f"{marketplace_url}/plans", data={
        "g-recaptcha-response": token,
    })

    if resp.status_code == 200:
        from bs4 import BeautifulSoup
        soup = BeautifulSoup(resp.text, "html.parser")
        plans = []
        for card in soup.select(".plan-card, .insurance-plan"):
            plans.append({
                "name": card.select_one(".plan-name").get_text(strip=True) if card.select_one(".plan-name") else "",
                "premium": card.select_one(".premium").get_text(strip=True) if card.select_one(".premium") else "",
                "deductible": card.select_one(".deductible").get_text(strip=True) if card.select_one(".deductible") else "",
            })
        return plans

    return []

Diagnóstico de errores frecuentes

Problema Causa Solución
El formulario de cotización se reinicia a mitad del flujo La IP cambió entre pasos Mantén la misma IP de salida durante todo el flujo
"No se puede generar la cotización" Falló la validación de datos Revisa los campos obligatorios
El CAPTCHA aparece dos veces El primer token expiró Vuelve a resolverlo de inmediato
Tarifas distintas a las del proceso manual Diferencias de cookies/sesión Empieza con una sesión limpia
El límite de solicitudes bloquea las peticiones Demasiadas cotizaciones desde la misma IP Reduce el ritmo y alterna la IP entre aseguradoras

Preguntas frecuentes

¿CaptchaAI resuelve el reCAPTCHA de los comparadores de seguros?

Sí. Estos formularios usan sobre todo reCAPTCHA v2, v2 Invisible, v3 y CAPTCHA de imagen (OCR), y todos son tipos compatibles. Envías el sitekey a la API y recibes el token para el formulario.

¿Qué plan necesito para comparar muchas aseguradoras a la vez?

Depende de cuántas cotizaciones resuelvas en paralelo. Cada thread es un CAPTCHA en curso: BASIC ($15/mes) trae 5 threads y ADVANCE ($90/mes) trae 50, con resoluciones ilimitadas en todos los planes.

Es tu responsabilidad. Automatiza solo flujos que tengas autorización para probar y respeta los términos del portal y la normativa de datos aplicable (GDPR/LOPDGDD, LFPDPPP). Esta guía es para QA de flujos propios o autorizados.

¿Puedo reutilizar el mismo código para auto, hogar y vida?

Sí. El manejo de CAPTCHA es idéntico en todos los ramos; solo cambian los campos del formulario y el punto donde aparece el desafío.


Guías relacionadas


Compara cotizaciones de seguros a escala: obtén tu API key de CaptchaAI y automatiza el proceso de cotización.

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