Phân Tích Kỹ Thuật

Cách xử lý reCAPTCHA v2 trong quy trình quét web

Vượt qua reCAPTCHA v2 trong pipeline scraping chỉ cần bốn bước: trích xuất sitekey, gửi task tới in.php, polling res.php lấy token, rồi chèn token vào trang trước khi submit. Phần giải chạy qua CaptchaAI — script của bạn không tự bấm checkbox hay chọn lưới ảnh, chỉ định tuyến CAPTCHA sang API và nhận lại token hợp lệ.

Mỗi widget reCAPTCHA v2 có hai tham số cần đọc: googlekey (sitekey nhúng trong HTML) và pageurl (địa chỉ trang hiển thị CAPTCHA). Phần dưới có code chạy được cho Python (Selenium + requests), Node.js (Puppeteer), và cách chỉ dùng HTTP khi không bắt buộc mở trình duyệt.

Với biến thể Enterprise, quy trình gần như giữ nguyên — chỉ thêm enterprise=1 vào request. Chi tiết ở Cách giải reCAPTCHA v2 Enterprise bằng API.


Chọn cách xử lý: trình duyệt thật hay chỉ HTTP?

Trước khi viết code, xác định trang đích rơi vào tình huống nào:

Tình huống Cách xử lý
Trang chèn token bằng JavaScript hoặc gọi hàm callback Trình duyệt thật — Selenium hoặc Puppeteer
Trang chấp nhận g-recaptcha-response qua POST thông thường Chỉ HTTP request, không cần trình duyệt
Bị chặn trước khi CAPTCHA xuất hiện (phát hiện headless) headless: "new", User-Agent thật, cấu hình trình duyệt kiểm thử chuẩn

Python: giải reCAPTCHA v2 với Selenium và CaptchaAI

Đoạn code dưới đây mở trang bằng Selenium, lấy sitekey, gửi task sang CaptchaAI, polling kết quả rồi chèn token vào form trước khi submit.

import requests
import time
from selenium import webdriver
from selenium.webdriver.common.by import By

# Step 1: Open the page with Selenium
driver = webdriver.Chrome()
driver.get("https://example.com/protected-page")

# Step 2: Extract the sitekey
sitekey = driver.find_element(By.CSS_SELECTOR, ".g-recaptcha").get_attribute("data-sitekey")
page_url = driver.current_url

# Step 3: Submit to CaptchaAI
response = requests.get("https://ocr.captchaai.com/in.php", params={
    "key": "YOUR_API_KEY",
    "method": "userrecaptcha",
    "googlekey": sitekey,
    "pageurl": page_url,
    "json": 1
}).json()

task_id = response["request"]

# Step 4: Poll for result
token = None
for _ in range(40):
    time.sleep(5)
    result = requests.get("https://ocr.captchaai.com/res.php", params={
        "key": "YOUR_API_KEY",
        "action": "get",
        "id": task_id,
        "json": 1
    }).json()

    if result.get("status") == 1:
        token = result["request"]
        break
    if result.get("request") != "CAPCHA_NOT_READY":
        raise RuntimeError(f"Solve failed: {result['request']}")

# Step 5: Inject the token and submit
driver.execute_script(
    f'document.getElementById("g-recaptcha-response").innerHTML = "{token}";'
)

# Check for callback
callback = driver.execute_script(
    'var el = document.querySelector(".g-recaptcha"); '
    'return el ? el.getAttribute("data-callback") : null;'
)
if callback:
    driver.execute_script(f'{callback}("{token}");')
else:
    driver.find_element(By.CSS_SELECTOR, "form").submit()

# Step 6: Scrape the data
print(driver.page_source[:500])
driver.quit()

Node.js: giải reCAPTCHA v2 với Puppeteer và CaptchaAI

Puppeteer làm việc tương tự: mở trang, lấy sitekey bằng $eval, gửi task tới CaptchaAI qua fetch, polling res.php rồi chèn token trước khi chờ điều hướng trang.

const puppeteer = require("puppeteer");

async function scrapeWithCaptcha(url) {
  const browser = await puppeteer.launch({ headless: "new" });
  const page = await browser.newPage();
  await page.goto(url, { waitUntil: "networkidle2" });

  // Extract sitekey
  const sitekey = await page.$eval(".g-recaptcha", (el) => el.dataset.sitekey);

  // Submit to CaptchaAI
  const submitRes = await fetch(
    `https://ocr.captchaai.com/in.php?${new URLSearchParams({
      key: "YOUR_API_KEY",
      method: "userrecaptcha",
      googlekey: sitekey,
      pageurl: url,
      json: 1,
    })}`
  );
  const { request: taskId } = await submitRes.json();

  // Poll for result
  let token;
  for (let i = 0; i < 40; i++) {
    await new Promise((r) => setTimeout(r, 5000));
    const res = await fetch(
      `https://ocr.captchaai.com/res.php?${new URLSearchParams({
        key: "YOUR_API_KEY",
        action: "get",
        id: taskId,
        json: 1,
      })}`
    );
    const data = await res.json();
    if (data.status === 1) {
      token = data.request;
      break;
    }
    if (data.request !== "CAPCHA_NOT_READY")
      throw new Error(`Solve failed: ${data.request}`);
  }

  // Inject token
  await page.evaluate((t) => {
    document.getElementById("g-recaptcha-response").innerHTML = t;
    const cb = document.querySelector(".g-recaptcha")?.dataset.callback;
    if (cb && window[cb]) window[cb](t);
  }, token);

  // Wait for navigation after form submit
  await page.waitForNavigation({ waitUntil: "networkidle2" });
  const content = await page.content();
  await browser.close();
  return content;
}

scrapeWithCaptcha("https://example.com/protected-page").then(console.log);

Không cần trình duyệt nếu trang chấp nhận token qua POST

Nếu trang đích gửi CAPTCHA trong luồng submit form thông thường, bạn có thể bỏ qua trình duyệt hoàn toàn và gửi trực tiếp bằng requests:

import requests
import time

session = requests.Session()
session.headers["User-Agent"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0"

# Load the page to get cookies
session.get("https://example.com/protected-page")

# Solve the CAPTCHA
sitekey = "6Le-wvkSAAAAAN..."  # extracted from page HTML
solve_resp = requests.get("https://ocr.captchaai.com/in.php", params={
    "key": "YOUR_API_KEY", "method": "userrecaptcha",
    "googlekey": sitekey, "pageurl": "https://example.com/protected-page",
    "json": 1
}).json()

task_id = solve_resp["request"]
time.sleep(15)

# Poll
for _ in range(30):
    result = requests.get("https://ocr.captchaai.com/res.php", params={
        "key": "YOUR_API_KEY", "action": "get", "id": task_id, "json": 1
    }).json()
    if result.get("status") == 1:
        token = result["request"]
        break
    time.sleep(5)

# Submit with token
resp = session.post("https://example.com/protected-page", data={
    "g-recaptcha-response": token,
    "other_field": "value"
})
print(resp.text[:500])

Cách này hợp với trang render phía server, không cần JavaScript để gắn token. Nếu trang bắt buộc chạy script phía client, quay lại dùng Selenium hoặc Puppeteer ở trên.


Theo dõi giá thương mại điện tử khi gặp reCAPTCHA v2

Tình huống quen thuộc với đội QA và data team tại các công ty outsourcing ở TP.HCM hay Hà Nội: pipeline theo dõi giá hàng nghìn SKU mỗi ngày trên Shopee, Lazada, Tiki bắt đầu bị reCAPTCHA v2 chặn khi tần suất request tăng. Quy trình bốn bước ở trên xử lý việc đó mà không cần ai bấm checkbox thủ công.

Khối lượng lớn thì chạy song song nhiều task thay vì tuần tự. BASIC ($15/tháng, 5 thread) đủ cho crawler nhỏ đang test luồng gửi task → polling → chèn token; lên production thì STANDARD ($30/tháng, 15 thread) hoặc ADVANCE ($90/tháng, 50 thread) giúp tốc độ crawl tăng gần tuyến tính theo số thread thay vì nghẽn ở một luồng.


Câu hỏi thường gặp về xử lý reCAPTCHA v2 khi scraping

Giải ở quy mô 10.000 request/ngày cần bao nhiêu thread? Mỗi lần giải mất 15–60 giây, nên khối lượng lớn cần chạy song song — ADVANCE ($90/tháng, 50 thread) giải 50 CAPTCHA cùng lúc, đủ cho phần lớn pipeline tầm trung; lớn hơn thì CORPORATE ($240/tháng) hoặc ENTERPRISE ($300/tháng).

Có bắt buộc dùng Selenium hay Puppeteer không? Không phải lúc nào cũng cần. Trang chấp nhận g-recaptcha-response qua POST thường thì dùng cách chỉ HTTP ở trên; trang cần chèn token bằng JavaScript hoặc gọi callback phía client thì cần trình duyệt thật.

CaptchaAI có giải được hCaptcha nếu trang đổi loại CAPTCHA không? Không. CaptchaAI chưa hỗ trợ hCaptcha hay FunCaptcha — chỉ giải reCAPTCHA v2/v3, Turnstile, GeeTest v3, CAPTCHA ảnh/OCR, grid image và BLS. Script nên kiểm tra loại widget trước khi gửi task.

Token giải xong dùng lại được cho request sau không? Không. Mỗi token chỉ dùng một lần, hết hạn sau khoảng 2 phút — mỗi request tới trang được bảo vệ cần một lần giải mới.

Nên bắt đầu với gói nào? BASIC ($15/tháng, 5 thread) đủ để test luồng gửi task, polling và chèn token; khi cần nhiều luồng song song hơn, nâng lên STANDARD hoặc ADVANCE theo khối lượng thực tế thay vì mua dư từ đầu.


Bắt đầu xử lý reCAPTCHA v2 trong pipeline scraping

  • Lấy API key tại captchaai.com/api.php
  • Trích xuất sitekey từ trang đích
  • Áp dụng code Python hoặc Node.js ở trên để giải và chèn token
  • Scale bằng nhiều thread song song khi khối lượng request tăng

Hướng dẫn liên quan

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