Trường Hợp Sử Dụng

Các vấn đề và giải pháp về CAPTCHA của trình duyệt headless

Nếu cụm Puppeteer hoặc Selenium headless của bạn liên tục dính reCAPTCHA hay Turnstile trong khi trình duyệt thường thì không, nguyên nhân là dấu vân tay trình duyệt, không phải trang đích khó tính hơn.

Chrome, Firefox, WebKit ở chế độ headless để lộ tín hiệu khiến điểm tin cậy giảm.

  • Vá tín hiệu chỉ hạ tần suất, không loại bỏ hoàn toàn CAPTCHA.
  • CaptchaAI là lớp bảo hiểm giải phía server, bất kể vá được bao nhiêu.

Vì sao trình duyệt headless bị soi CAPTCHA nhiều hơn

Dấu hiệu nhận diện Trang web kiểm tra gì
navigator.webdriver Đặt thành true ở chế độ headless
Kích thước cửa sổ Headless thường dùng mặc định 800x600
Trình kết xuất WebGL Trả về "SwiftShader" khi headless
Chrome DevTools Protocol Cổng CDP đang mở
Thiếu plugin Không có trình xem PDF, Flash, v.v.
Permissions API Phản hồi khác với trình duyệt có giao diện
Chuỗi User-Agent Chứa chuỗi con "HeadlessChrome"

Khi nhiều tín hiệu kết hợp, các hệ thống chống bot hạ điểm tin cậy và bật CAPTCHA:

  • reCAPTCHA — yêu cầu thử thách khi thấy nhiều tín hiệu automation.
  • Cloudflare — bật Turnstile khi traffic IP datacenter tăng vọt.
  • DataDome — chấm điểm theo phiên, không chỉ từng request.

Ví dụ: đội dev tại TP.HCM chạy cụm Puppeteer theo dõi giá trên Shopee, Lazada — nhiều instance song song cùng dải IP khiến tỷ lệ CAPTCHA tăng vọt.


Lỗi thường gặp theo từng công cụ trình duyệt

Chrome headless

Lộ navigator.webdriver. Áp dụng cấu hình QA chuẩn để giảm tín hiệu này.

Puppeteer

Thiếu plugin trình duyệt mặc định. Dùng gói cộng đồng bổ sung cấu hình QA.

Selenium

Công tắc enable-automation bật mặc định. Tắt bằng excludeSwitches: ["enable-automation"].

Playwright

Vân tay WebKit dễ bị soi hơn Chromium. Dùng kênh Chrome kèm cấu hình QA chuẩn.

Tất cả công cụ

Kích thước khung nhìn không đồng nhất là dấu hiệu dễ soi nhất. Đặt cố định 1920x1080 hoặc chọn ngẫu nhiên.


Cách 1: Giải CAPTCHA bằng API ngay khi nó xuất hiện

Loại bỏ hoàn toàn CAPTCHA gần như bất khả thi ở quy mô lớn — thực tế hơn là giải ngay khi nó xuất hiện. Luồng chỉ có 3 bước: gửi site key qua in.php, polling res.php, rồi tiêm token.

Selenium (Python)

Gửi site key và pageurl sang CaptchaAI qua in.php, rồi polling res.php để lấy token:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import requests
import time

API_KEY = "YOUR_API_KEY"

options = Options()
options.add_argument("--headless=new")
options.add_argument("")
driver = webdriver.Chrome(options=options)

driver.get("https://staging.example.com/qa-login")

# Check for CAPTCHA
recaptcha = driver.find_elements("class name", "g-recaptcha")
if recaptcha:
    site_key = recaptcha[0].get_attribute("data-sitekey")

    # Solve via CaptchaAI
    resp = requests.get("https://ocr.captchaai.com/in.php", params={
        "key": API_KEY, "method": "userrecaptcha",
        "googlekey": site_key, "pageurl": driver.current_url
    })
    task_id = resp.text.split("|")[1]

    while True:
        time.sleep(5)
        result = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": API_KEY, "action": "get", "id": task_id
        })
        if result.text == "CAPCHA_NOT_READY": continue
        token = result.text.split("|")[1]
        break

    # Inject token
    driver.execute_script(
        f"document.getElementById('g-recaptcha-response').innerHTML = '{token}';"
    )
    driver.find_element("css selector", "form").submit()

Puppeteer (Node.js)

Cùng luồng gửi task, polling, tiêm token — viết lại bằng Puppeteer và Axios:

const puppeteer = require("puppeteer");
const axios = require("axios");

const API_KEY = "YOUR_API_KEY";

const browser = await puppeteer.launch({ headless: "new" });
const page = await browser.newPage();
await page.goto("https://staging.example.com/qa-login");

// Check for CAPTCHA
const siteKey = await page
  .$eval(".g-recaptcha", (el) => el.getAttribute("data-sitekey"))
  .catch(() => null);

if (siteKey) {
  const submit = await axios.get("https://ocr.captchaai.com/in.php", {
    params: {
      key: API_KEY,
      method: "userrecaptcha",
      googlekey: siteKey,
      pageurl: page.url(),
    },
  });
  const taskId = submit.data.split("|")[1];

  let token;
  while (true) {
    await new Promise((r) => setTimeout(r, 5000));
    const result = await axios.get("https://ocr.captchaai.com/res.php", {
      params: { key: API_KEY, action: "get", id: taskId },
    });
    if (result.data === "CAPCHA_NOT_READY") continue;
    token = result.data.split("|")[1];
    break;
  }

  await page.evaluate((t) => {
    document.getElementById("g-recaptcha-response").innerHTML = t;
  }, token);
  await page.click('button[type="submit"]');
}

Cách 2: Giảm tần suất gặp CAPTCHA

Giải qua API là lớp bảo hiểm cuối, nhưng giảm tần suất CAPTCHA giúp tiết kiệm thời gian. Ba kỹ thuật hiệu quả nhất:

  • navigator.webdriver.
  • Đặt kích thước cửa sổ giống trình duyệt thật.
  • Áp dụng cấu hình QA chuẩn hoặc gói cộng đồng.

Vá navigator.webdriver

# Selenium
options.add_argument("")
options.add_experimental_option("excludeSwitches", ["enable-automation"])
// Puppeteer
await page.evaluateOnNewDocument(() => {
  Object.defineProperty(navigator, "webdriver", { get: () => false });
});

Đặt kích thước cửa sổ giống trình duyệt thật

# Selenium
driver.set_window_size(1920, 1080)
// Puppeteer
await page.setViewport({ width: 1920, height: 1080 });

Áp dụng cấu hình QA chuẩn cho trình duyệt

Các gói cộng đồng bổ sung bản vá runtime, giúp trình duyệt headless giống trình duyệt thật hơn ở tầng JavaScript và giảm bớt các tín hiệu dễ bị soi nhất:

# Puppeteer
npm install puppeteer-extra puppeteer-extra-plugin-stealth
const puppeteer = require("puppeteer-extra");
const StealthPlugin = require("puppeteer-extra-plugin-stealth");
puppeteer.use(StealthPlugin());
# Selenium
pip install undetected-chromedriver
import undetected_chromedriver as uc
driver = uc.Chrome(headless=True)

Cách 3: Xử lý Cloudflare Challenge

Trang thử thách Cloudflare cần nhiều hơn một token — bạn cần cookie phiên hợp lệ (qa_session_cookie trong môi trường QA):

# CaptchaAI handles full Cloudflare challenges
resp = requests.get("https://ocr.captchaai.com/in.php", params={
    "key": API_KEY,
    "method": "cloudflare_challenge",
    "pageurl": "https://example.com",
    "proxy": "http://user:pass@proxy:port",
    "proxytype": "HTTP"
})
task_id = resp.text.split("|")[1]

# Result includes qa_session_cookie cookie and user_agent
# Use both to make subsequent requests

Câu hỏi thường gặp

Chạy headless trong Docker hoặc trên cloud có bị CAPTCHA nhiều hơn không?

Có. IP datacenter và thiếu context render GPU khiến điểm tin cậy thấp hơn — xem CAPTCHA là chuyện bình thường trong CI/CD.

Chi phí xử lý CAPTCHA cho cụm headless chạy 24/7 tốn bao nhiêu?

Tuỳ khối lượng task đồng thời. CaptchaAI tính phí theo thread — BASIC ($15/tháng, 5 thread) đủ cho crawl nhỏ, nhiều instance song song thường cần STANDARD ($30/tháng, 15 thread) trở lên.

Có nên chuyển sang chế độ có giao diện (headed) thay vì headless không?

Không bắt buộc. Chế độ có giao diện giảm tín hiệu tự động hóa nhưng cần Xvfb trên Linux. CaptchaAI xử lý CAPTCHA phía server nên hoạt động như nhau dù headed hay headless.

Checklist trước khi deploy:

  • Đã vá navigator.webdriver và kích thước cửa sổ chưa?
  • Đã tích hợp CaptchaAI làm lớp dự phòng chưa?
  • Proxy/IP đã xoay vòng chưa?

Hướng dẫn liên quan

Os comentários estão desativados para este artigo.