# Clics simulados en reCAPTCHA v2 con reconocimiento de imágenes (Selenium)

> Usa Python, Selenium 4 y ReCaptchaV2Classification para hacer clic automáticamente en los desafíos de imágenes de reCAPTCHA v2 en el navegador: activa el captcha, lee la pregunta y las imágenes, llama a la API de reconocimiento, haz clic en las casillas y envía; código de ejemplo completo.

Source: https://docs.yescaptcha.com/es/guides/recaptcha-click-selenium/ · Last verified: 2026-10-15

> This page was machine-translated from the Chinese version. If anything differs, the Chinese version prevails: https://docs.yescaptcha.com/zh/guides/recaptcha-click-selenium/

Este tutorial abre la página de demostración de reCAPTCHA de Google con Selenium 4 y resuelve el desafío de imágenes en un navegador real: lee la pregunta y la imagen, se las envía a [reconocimiento de imágenes de reCAPTCHA v2](https://docs.yescaptcha.com/es/tasks/recaptcha-classification.md) (`ReCaptchaV2Classification`) para saber en qué casillas hacer clic, y luego simula los clics. A diferencia del enfoque con token, la verificación se completa en el propio navegador, lo que es útil en sitios donde los tokens rara vez pasan.

Si no quieres escribir código, usa directamente la [extensión del navegador](https://docs.yescaptcha.com/es/extension.md), que hace lo mismo con la misma API.

## Preparación

```bash
pip install requests selenium pillow
export YESCAPTCHA_CLIENT_KEY=your_client_key
```

Necesitas tener Chrome instalado. Selenium 4 descarga automáticamente el chromedriver compatible.

## Flujo

1.  **Haz clic en la casilla.** La casilla está dentro del iframe con `title="reCAPTCHA"`: cambia a ese iframe y haz clic en `#recaptcha-anchor`.
2.  **Cambia al iframe del desafío.** El desafío está en otro iframe (cuyo title contiene “challenge”).
3.  **Lee la pregunta.** El texto en negrita de `.rc-imageselect-desc-wrapper strong` es el objetivo, por ejemplo “traffic lights”. La API necesita el ID de la pregunta, así que usa la tabla de equivalencias para convertir el nombre en un ID (`/m/015qff`); consulta [ID de pregunta](https://docs.yescaptcha.com/es/tasks/recaptcha-classification.md). Es más fácil comparar si la interfaz del navegador está en inglés.
4.  **Obtén la imagen.** Las casillas son en realidad fragmentos de una misma imagen grande: descarga el `src` de `td.rc-imageselect-tile img`. Con 9 casillas (3x3) escálala a 300×300 y con 16 casillas (4x4) a 450×450, y conviértela a Base64.
5.  **Reconoce.** Llama a `createTask` con el tipo `ReCaptchaV2Classification` y envía `image` y `question`. Si añades `"confidence": 0.5`, las imágenes 3x3 devuelven de una vez todas las casillas que coinciden, y no tienes que gestionar las imágenes pequeñas que aparecen tras hacer clic.
6.  **Haz clic.** `objects` contiene los índices de las casillas, empezando en 0, de izquierda a derecha y de arriba abajo; haz clic en los `td` correspondientes en ese orden.
7.  **Verifica.** Haz clic en `#recaptcha-verify-button`. Si aparece una nueva ronda, vuelve al paso 3; cuando la ventana del desafío se cierra, has pasado.
8.  **Envía el formulario.** Vuelve a la página principal y haz clic en el botón de envío.

## Código completo

recaptcha_click_selenium.py

```python
"""Click through a reCAPTCHA v2 image challenge with Selenium 4 and ReCaptchaV2Classification.

Flow: open the page -> click the checkbox -> read the target name and the grid image ->
ask YesCaptcha which tiles to click -> click them -> press Verify. Repeat if a new challenge appears.

Run:  pip install requests selenium pillow
      export YESCAPTCHA_CLIENT_KEY=your_client_key
      python recaptcha_click_selenium.py
Each recognized image is charged (see the price list). reCAPTCHA's page structure can change;
adjust the selectors below if a step stops working.
"""
import base64
import io
import os
import time

import requests
from PIL import Image
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait

CLIENT_KEY = os.environ["YESCAPTCHA_CLIENT_KEY"]
PAGE_URL = "https://www.google.com/recaptcha/api2/demo"

# Target names shown in the challenge (English UI) -> question IDs.
# Full list: https://docs.yescaptcha.com/en/tasks/recaptcha-classification/
QUESTION_IDS = {
    "taxis": "/m/0pg52", "bus": "/m/01bjv", "buses": "/m/01bjv", "motorcycles": "/m/04_sv",
    "tractors": "/m/013xlm", "chimneys": "/m/01jk_4", "crosswalks": "/m/014xcs",
    "traffic lights": "/m/015qff", "bicycles": "/m/0199g", "parking meters": "/m/015qbp",
    "cars": "/m/0k4j", "bridges": "/m/015kr", "boats": "/m/019jd", "palm trees": "/m/0cdl1",
    "mountains or hills": "/m/09d_r", "fire hydrants": "/m/01pns0", "a fire hydrant": "/m/01pns0",
    "stairs": "/m/01lynh",
}

def classify(image_b64, question):
    task = {"type": "ReCaptchaV2Classification", "image": image_b64, "question": question, "confidence": 0.5}
    data = requests.post(
        "https://api.yescaptcha.com/createTask",
        json={"clientKey": CLIENT_KEY, "task": task},
        timeout=30,
    ).json()
    if data.get("errorId"):
        raise RuntimeError(f"{data.get('errorCode')}: {data.get('errorDescription')}")
    return data["solution"]  # synchronous: the solution comes back right away

def grid_image_b64(url, size):
    """Download the challenge image and scale it to the standard size (300 for 3x3, 450 for 4x4)."""
    img = Image.open(io.BytesIO(requests.get(url, timeout=30).content)).convert("RGB")
    img = img.resize((size, size))
    buf = io.BytesIO()
    img.save(buf, format="JPEG")
    return base64.b64encode(buf.getvalue()).decode()

driver = webdriver.Chrome()
wait = WebDriverWait(driver, 15)
try:
    driver.get(PAGE_URL)

    # 1. Click the checkbox (inside the "reCAPTCHA" iframe)
    wait.until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR, 'iframe[title="reCAPTCHA"]')))
    wait.until(EC.element_to_be_clickable((By.ID, "recaptcha-anchor"))).click()
    driver.switch_to.default_content()

    # 2. Switch to the challenge iframe and solve rounds until it closes
    wait.until(EC.frame_to_be_available_and_switch_to_it(
        (By.XPATH, '//iframe[contains(@title, "challenge")]')))
    for _ in range(5):
        target = wait.until(EC.presence_of_element_located(
            (By.CSS_SELECTOR, ".rc-imageselect-desc-wrapper strong"))).text.strip().lower()
        question = QUESTION_IDS.get(target)
        if not question:
            print("unsupported target, reloading:", target)
            driver.find_element(By.ID, "recaptcha-reload-button").click()
            time.sleep(2)
            continue
        tiles = driver.find_elements(By.CSS_SELECTOR, "td.rc-imageselect-tile")
        size = 450 if len(tiles) == 16 else 300
        url = driver.find_element(By.CSS_SELECTOR, "td.rc-imageselect-tile img").get_attribute("src")
        solution = classify(grid_image_b64(url, size), question)
        for index in solution.get("objects", []):
            tiles[index].click()
            time.sleep(0.3)
        time.sleep(1)
        driver.find_element(By.ID, "recaptcha-verify-button").click()
        time.sleep(3)
        driver.switch_to.default_content()
        frame = driver.find_element(By.XPATH, '//iframe[contains(@title, "challenge")]')
        if not frame.is_displayed():  # challenge closed: passed
            break
        driver.switch_to.frame(frame)

    driver.switch_to.default_content()
    driver.find_element(By.ID, "recaptcha-demo-submit").click()
    time.sleep(2)
    print("passed" if "Verification Success" in driver.page_source else "not passed")
finally:
    driver.quit()
```

## Notas

-   La estructura de la página de reCAPTCHA cambia con el tiempo; si los selectores del código dejan de funcionar, ajústalos a la página real.
-   Cada imagen reconocida implica un cobro de puntos (precios en [reconocimiento de imágenes de reCAPTCHA v2](https://docs.yescaptcha.com/es/tasks/recaptcha-classification.md)). Las tareas cuyo clic fue rechazado se pueden [reportar](https://docs.yescaptcha.com/es/api/report.md) en un plazo de 1 hora para solicitar el reembolso tras reportar.
-   Si encuentras una pregunta que no está en la tabla de equivalencias, haz clic en el botón de recarga para obtener otra, o contacta con Soporte para que añadan compatibilidad.
