Ir al contenido
EstadoPanel

Guías

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

Esta página se tradujo automáticamente de la versión en chino y puede contener errores. Prevalece la versión en chino.

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 (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, que hace lo mismo con la misma API.

pip install requests selenium pillow
export YESCAPTCHA_CLIENT_KEY=your_client_key

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

  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. 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.
recaptcha_click_selenium.py
"""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()
  • 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). Las tareas cuyo clic fue rechazado se pueden reportar 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.