# Mô phỏng click hình ảnh hCaptcha bằng Selenium

> Dùng Python, Selenium 4 và HCaptchaClassification để tự động hoàn thành câu đố hình ảnh lưới 3×3 của hCaptcha trong trình duyệt thật: nhấp vào hộp kiểm, đọc câu hỏi và 9 hình ảnh, gọi API nhận dạng, click và gửi; kèm mã ví dụ đầy đủ.

Source: https://docs.yescaptcha.com/vi/guides/hcaptcha-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/hcaptcha-click-selenium/

Hướng dẫn này dùng Selenium 4 mở trang demo của hCaptcha và hoàn thành câu đố hình ảnh lưới 3×3 trong trình duyệt thật: đọc câu hỏi và 9 hình ảnh, gửi cho [nhận dạng hình ảnh hCaptcha](https://docs.yescaptcha.com/vi/tasks/hcaptcha-classification.md) (`HCaptchaClassification`) để xác định ô nào là mục tiêu, rồi mô phỏng click.

hCaptcha còn có các dạng câu đố như “click vào vị trí chỉ định” và “kéo thả”. Chúng trả về tọa độ thay vì ô lưới; cách xử lý xem tại [nhận dạng hình ảnh hCaptcha](https://docs.yescaptcha.com/vi/tasks/hcaptcha-classification.md). Nếu không muốn viết mã, bạn có thể dùng thẳng [tiện ích trình duyệt](https://docs.yescaptcha.com/vi/extension.md); tiện ích hỗ trợ tất cả các dạng này.

## Chuẩn bị

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

## Quy trình

1.  **Nhấp vào hộp kiểm.** Hộp kiểm nằm trong iframe hCaptcha có địa chỉ chứa `frame=checkbox`; chuyển vào iframe đó rồi nhấp `#checkbox`.
2.  **Chuyển sang iframe của câu hỏi.** Câu hỏi nằm trong iframe có địa chỉ chứa `frame=challenge`.
3.  **Đọc câu hỏi.** Văn bản trong `.prompt-text` chính là câu hỏi, truyền nguyên văn cho API (nên chuyển ngôn ngữ giao diện của hCaptcha sang tiếng Trung giản thể hoặc tiếng Anh). Nếu cạnh câu hỏi có ảnh mẫu nhỏ, hãy đưa ảnh đó vào `anchors`.
4.  **Lấy hình ảnh.** Ảnh nền của `.task-image .image` ở mỗi ô là một hình nhỏ; tải lần lượt theo thứ tự, chuyển sang Base64 và tạo danh sách `queries`.
5.  **Nhận dạng.** Gọi `createTask` với loại `HCaptchaClassification`. `objects` trả về tương ứng một-một với các ô, giá trị `true` là mục tiêu.
6.  **Click và gửi.** Click các ô là mục tiêu rồi nhấn nút gửi. Có thể xuất hiện nhiều vòng liên tiếp, lặp lại các bước 3 đến 6.
7.  **Hoàn tất.** Sau khi vượt qua, trường `h-captcha-response` trên trang sẽ chứa token, gửi kèm cùng biểu mẫu.

## Mã đầy đủ

hcaptcha_click_selenium.py

```python
"""Click through an hCaptcha 3x3 image challenge with Selenium 4 and HCaptchaClassification.

Flow: open the page -> click the checkbox -> read the question and the 9 images ->
ask YesCaptcha which images match -> click them -> submit. Repeat while new rounds appear.

Run:  pip install requests selenium
      export YESCAPTCHA_CLIENT_KEY=your_client_key
      python hcaptcha_click_selenium.py
Each recognized round is charged (see the price list; rounds with no target found are free).
hCaptcha changes its page structure often; adjust the selectors below if a step stops working.
Click and drag questions return coordinates instead; see the HCaptchaClassification page.
"""
import base64
import os
import re
import time

import requests
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://accounts.hcaptcha.com/demo"

def classify(question, images_b64):
    task = {"type": "HCaptchaClassification", "question": question, "queries": images_b64}
    data = requests.post(
        "https://api.yescaptcha.com/createTask",
        json={"clientKey": CLIENT_KEY, "task": task},
        timeout=60,
    ).json()
    if data.get("errorId"):
        raise RuntimeError(f"{data.get('errorCode')}: {data.get('errorDescription')}")
    return data["solution"]  # synchronous

def background_image_b64(element):
    """The tiles are <div>s with a CSS background image; download it and Base64-encode it."""
    style = element.get_attribute("style") or ""
    match = re.search(r'url\("?(.*?)"?\)', style)
    if not match:
        return None
    return base64.b64encode(requests.get(match.group(1), timeout=30).content).decode()

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

    # 1. Click the checkbox (inside the first hCaptcha iframe)
    wait.until(EC.frame_to_be_available_and_switch_to_it(
        (By.CSS_SELECTOR, 'iframe[src*="hcaptcha"][src*="frame=checkbox"]')))
    wait.until(EC.element_to_be_clickable((By.ID, "checkbox"))).click()
    driver.switch_to.default_content()

    # 2. Solve rounds in the challenge iframe
    wait.until(EC.frame_to_be_available_and_switch_to_it(
        (By.CSS_SELECTOR, 'iframe[src*="hcaptcha"][src*="frame=challenge"]')))
    for _ in range(5):
        question = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, ".prompt-text"))).text.strip()
        tiles = driver.find_elements(By.CSS_SELECTOR, ".task-image")
        images = [background_image_b64(t.find_element(By.CSS_SELECTOR, ".image")) for t in tiles]
        if not tiles or None in images:
            print("not a 3x3 image challenge; see the docs for click/drag questions")
            break
        solution = classify(question, images)
        for tile, hit in zip(tiles, solution.get("objects", [])):
            if hit:
                tile.click()
                time.sleep(0.3)
        driver.find_element(By.CSS_SELECTOR, ".button-submit").click()
        time.sleep(3)
        if not driver.find_elements(By.CSS_SELECTOR, ".task-image"):
            break

    driver.switch_to.default_content()
    token = driver.find_element(By.NAME, "h-captcha-response").get_attribute("value")
    print("token received" if token else "not passed")
finally:
    driver.quit()
```

## Lưu ý

-   Cấu trúc trang của hCaptcha thường xuyên thay đổi; khi bộ chọn trong mã không còn hiệu lực, hãy điều chỉnh theo trang thực tế.
-   Mỗi vòng nhận dạng đều bị trừ điểm; vòng không nhận dạng ra mục tiêu thì không trừ điểm. Nếu xác minh thất bại sau khi click, bạn có thể [báo cáo](https://docs.yescaptcha.com/vi/api/report.md) trong vòng 1 giờ để yêu cầu hoàn điểm.
-   Khi gặp câu hỏi mới và nhận `ERROR_UNKNOWN_QUESTION`, hãy làm mới để đổi câu hỏi khác, hoặc liên hệ bộ phận hỗ trợ.
