Use Cases

Envío de formularios automatizado con manejo de CAPTCHA

Automatice los envíos de formularios que incluyan desafíos CAPTCHA utilizando Selenium y CaptchaAI.


El desafío

Los formularios web protegidos por CAPTCHA bloquean la automatización. Ya sea que esté probando formularios de contacto, enviando solicitudes o ejecutando flujos de trabajo de control de calidad, debe resolver el CAPTCHA antes de que el formulario acepte su envío.


Arquitectura

┌────────────┐     ┌──────────────┐     ┌────────────┐     ┌──────────────┐
│ Load Form  │────▶│ Fill Fields  │────▶│ Detect &   │────▶│ Submit Form  │
│ (Selenium) │     │              │     │ Solve      │     │              │
│            │     │              │     │ CAPTCHA    │     │              │
└────────────┘     └──────────────┘     └────────────┘     └──────────────┘

Componentes principales

Solucionador de CAPTCHA

import time
import requests


class FormCaptchaSolver:
    BASE = "https://ocr.captchaai.com"

    def __init__(self, api_key):
        self.api_key = api_key

    def solve(self, params, initial_wait=10):
        params["key"] = self.api_key
        params["json"] = 1
        resp = requests.post(f"{self.BASE}/in.php", data=params).json()
        if resp["status"] != 1:
            raise Exception(f"Submit error: {resp['request']}")

        task_id = resp["request"]
        time.sleep(initial_wait)

        for _ in range(60):
            result = requests.get(
                f"{self.BASE}/res.php",
                params={"key": self.api_key, "action": "get", "id": task_id, "json": 1},
            ).json()
            if result["request"] == "CAPCHA_NOT_READY":
                time.sleep(5)
                continue
            if result["status"] == 1:
                return result["request"]
            raise Exception(f"Solve error: {result['request']}")
        raise TimeoutError("CAPTCHA solve timed out")

Detector de CAPTCHA

import re
from selenium.webdriver.common.by import By


class CaptchaDetector:
    def __init__(self, driver):
        self.driver = driver

    def detect(self):
        """Detect CAPTCHA type on current page."""
        html = self.driver.page_source

        # Turnstile
        turnstile = self.driver.find_elements(By.CSS_SELECTOR, ".cf-turnstile, [data-sitekey]")
        for el in turnstile:
            if "cf-turnstile" in (el.get_attribute("class") or ""):
                return "turnstile", el.get_attribute("data-sitekey")

        # reCAPTCHA
        recaptcha = self.driver.find_elements(By.CSS_SELECTOR, "[data-sitekey]")
        if recaptcha:
            sitekey = recaptcha[0].get_attribute("data-sitekey")
            if "recaptcha" in html.lower():
                return "recaptcha_v2", sitekey

        # Image CAPTCHA
        img = self.driver.find_elements(By.CSS_SELECTOR, "img[src*='captcha'], img.captcha")
        if img:
            return "image", img[0].get_attribute("src")

        return "none", None

Automatizador de formularios

import base64
import requests as req
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


class FormAutomator:
    def __init__(self, api_key):
        self.solver = FormCaptchaSolver(api_key)
        self.driver = webdriver.Chrome()
        self.detector = CaptchaDetector(self.driver)

    def fill_field(self, selector, value):
        field = WebDriverWait(self.driver, 10).until(
            EC.presence_of_element_located((By.CSS_SELECTOR, selector))
        )
        field.clear()
        field.send_keys(value)

    def select_option(self, selector, value):
        from selenium.webdriver.support.ui import Select
        select = Select(self.driver.find_element(By.CSS_SELECTOR, selector))
        select.select_by_value(value)

    def solve_captcha(self):
        captcha_type, data = self.detector.detect()
        page_url = self.driver.current_url

        if captcha_type == "recaptcha_v2":
            token = self.solver.solve({
                "method": "userrecaptcha",
                "googlekey": data,
                "pageurl": page_url,
            })
            self.driver.execute_script(
                f'document.querySelector("[name=g-recaptcha-response]").value = "{token}";'
            )
            return True

        if captcha_type == "turnstile":
            token = self.solver.solve({
                "method": "turnstile",
                "sitekey": data,
                "pageurl": page_url,
            })
            self.driver.execute_script(
                f'document.querySelector("[name=cf-turnstile-response]").value = "{token}";'
            )
            return True

        if captcha_type == "image":
            img_data = req.get(data).content
            img_b64 = base64.b64encode(img_data).decode()
            text = self.solver.solve({"method": "base64", "body": img_b64})
            captcha_input = self.driver.find_element(
                By.CSS_SELECTOR, "input[name*='captcha']"
            )
            captcha_input.clear()
            captcha_input.send_keys(text)
            return True

        return False  # No CAPTCHA detected

    def submit_form(self, url, fields, submit_selector="button[type='submit']"):
        """
        fields: list of (selector, value) tuples
        """
        self.driver.get(url)

        for selector, value in fields:
            self.fill_field(selector, value)

        self.solve_captcha()

        submit = self.driver.find_element(By.CSS_SELECTOR, submit_selector)
        submit.click()

        return self.driver.current_url

    def close(self):
        self.driver.quit()

Ejemplo completo: formulario de contacto

automator = FormAutomator("YOUR_API_KEY")

try:
    result_url = automator.submit_form(
        url="https://example.com/contact",
        fields=[
            ("#name", "John Doe"),
            ("#email", "john@example.com"),
            ("#subject", "Sales inquiry"),
            ("#message", "I'd like to learn more about your services."),
        ],
        submit_selector="#submit-btn",
    )
    print(f"Form submitted. Redirected to: {result_url}")
finally:
    automator.close()

Manejo de múltiples tipos de formularios

Formulario de inicio de sesión

result = automator.submit_form(
    url="https://staging.example.com/qa-login",
    fields=[
        ("#username", "testuser"),
        ("#password", "testpass123"),
    ],
    submit_selector="#login-btn",
)

Formulario de registro

result = automator.submit_form(
    url="https://example.com/register",
    fields=[
        ("#first-name", "Jane"),
        ("#last-name", "Smith"),
        ("#email", "jane@example.com"),
        ("#password", "SecurePass!123"),
        ("#confirm-password", "SecurePass!123"),
    ],
    submit_selector="#register-btn",
)

Formulario de búsqueda con CAPTCHA

result = automator.submit_form(
    url="https://example.com/search",
    fields=[
        ("#query", "python developer"),
        ("#location", "San Francisco"),
    ],
    submit_selector="#search-btn",
)

Solución de problemas

Problema causa Solución
Token rechazado El token expiró antes del envío Resuelva CAPTCHA al final, envíelo inmediatamente
Campo no encontrado Carga de página dinámica Agregar esperas explícitas
Se detectó un tipo de CAPTCHA incorrecto Múltiples elementos CAPTCHA Comprobar orden de detección
El formulario se recarga después de enviarlo La validación del lado del servidor falló Verifique todos los campos obligatorios
La devolución de llamada de reCAPTCHA no se activa Necesita llamar a la función de callback Utilice grecaptcha.execute() después de la inyección.

Preguntas frecuentes

¿Puedo enviar formularios sin un navegador?

Para reCAPTCHA y Turnstile, puede resolver CAPTCHA sin un navegador y enviarlos a través de HTTP POST. Pero si el formulario utiliza validación de JavaScript, se necesita un navegador.

¿Cómo manejo formularios con múltiples CAPTCHA?

Algunos formularios muestran un CAPTCHA solo después de que falla la validación. Ejecute solve_captcha() nuevamente después de cada intento de envío.

¿Qué pasa con los formularios AJAX?

Para envíos AJAX, intercepte la solicitud XHR e incluya el token CAPTCHA en la carga útil de la solicitud en lugar de completar un campo oculto.


Guías relacionadas

  • Inicio rápido de CaptchaAI
  • Referencia de formatos de respuesta de la API

Automatiza cualquier formulario. Resuelve CAPTCHA con CaptchaAI.

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

Publicaciones relacionadas

Use Cases Manejo de CAPTCHA en pruebas de integración continua
Cómo manejar CAPTCHA en pruebas de integración continua: ejecuta tests end-to-end en páginas protegidas con CAPTCHA en tu pipeline CI/CD sin intervención manual...

Cómo manejar CAPTCHA en pruebas de integración continua: ejecuta tests end-to-end en páginas protegidas con CA...

May 04, 2026
Explainers Salida de red móvil en pruebas QA propias (editorial)
Vista editorial sobre el uso de salidas de red móviles autorizadas en pruebas QA propias y su impacto en CAPTCHA.

Vista editorial sobre el uso de salidas de red móviles autorizadas en pruebas QA propias y su impacto en CAPTC...

Apr 19, 2026