Task báo lỗi ERROR_WRONG_GOOGLEKEY hoặc trả về sitekey rỗng? Nguyên nhân phổ biến nhất không phải do API, mà do lấy sai vị trí trong trang — reCAPTCHA v2 để sitekey thẳng trong data-sitekey, nhưng v3 và Enterprise thường nhúng nó trong URL của thẻ script, trong src của iframe, hoặc chỉ xuất hiện sau khi JavaScript render xong. Ngoài googlekey và pageurl, một số loại còn cần thêm action (v3), data-s (trang thuộc hệ sinh thái Google) hoặc cờ enterprise. Bài này gom đủ 6 cách trích xuất theo từng tình huống, kèm một hàm Python gộp 4 nguồn sitekey chính để dùng ngay trong pipeline test.
Ví dụ thực tế: một đội QA tại công ty outsourcing ở TP.HCM cần kiểm thử form đăng nhập trên cả ba môi trường dev, staging và production — mỗi môi trường lại có sitekey riêng. Thay vì hard-code sitekey theo từng môi trường, script trích xuất tự động chạy trong CI sẽ lấy đúng giá trị mỗi lần deploy, tránh việc quên cập nhật và làm sai lệch kết quả test.
Chọn đúng cách trích xuất theo triệu chứng bạn gặp
Trước khi đọc chi tiết từng cách, đối chiếu nhanh triệu chứng của bạn với danh sách dưới đây để đi thẳng vào phần cần dùng:
data-sitekeykhông xuất hiện trong HTML tĩnh → trang render widget bằng JavaScript, dùng Cách 2 (Puppeteer) thay vì fetch HTML thô.- Trang dùng reCAPTCHA v3 hoặc Enterprise, không thấy widget nào → sitekey nằm trong URL thẻ
<script>, dùng Cách 3. - Cần thêm tham số
actioncho v3 →actionchỉ tồn tại trong lệnh gọigrecaptcha.execute(), dùng Cách 4. - Widget chỉ lộ ra bên trong iframe → đọc
srccủa iframe theo Cách 5. - Trang tự gọi
grecaptcha.render()bằng tay → cấu hình sitekey nằm trong object truyền vào, dùng Cách 6. - Không chắc trang dùng cách nào → chạy hàm gộp 4 nguồn sitekey (Cách 1, 3, 5, 6) ở phần "Hàm trích xuất tự động toàn bộ tham số" bên dưới, nó tự thử lần lượt.
Tham số nào bắt buộc theo từng phiên bản reCAPTCHA?
| Tham số | v2 Tiêu chuẩn | v2 Vô hình | v3 | Enterprise |
|---|---|---|---|---|
googlekey (sitekey) |
Bắt buộc | Bắt buộc | Bắt buộc | Bắt buộc |
pageurl |
Bắt buộc | Bắt buộc | Bắt buộc | Bắt buộc |
invisible |
— | 1 |
— | — |
action |
— | — | Bắt buộc | Đôi khi |
data-s |
Đôi khi | Đôi khi | — | — |
enterprise |
— | — | — | 1 |
Cách 1: Đọc thuộc tính data-sitekey trong HTML tĩnh
Cách nhanh nhất: fetch HTML tĩnh rồi regex thẳng vào widget .g-recaptcha. Áp dụng được cho phần lớn trang reCAPTCHA v2 vì sitekey nằm ngay trong thuộc tính, không cần render JavaScript.
import re
import requests
url = "https://staging.example.com/qa-login"
html = requests.get(url).text
# Find data-sitekey
match = re.search(r'data-sitekey=["\']([A-Za-z0-9_-]+)["\']', html)
if match:
sitekey = match.group(1)
print(f"Sitekey: {sitekey}")
# Check if invisible
invisible_match = re.search(r'data-size=["\']invisible["\']', html)
is_invisible = bool(invisible_match)
print(f"Invisible: {is_invisible}")
# Find callback
callback_match = re.search(r'data-callback=["\'](\w+)["\']', html)
callback = callback_match.group(1) if callback_match else None
print(f"Callback: {callback}")
# Check for data-s (Google-owned sites)
data_s_match = re.search(r'data-s=["\']([^"\']+)["\']', html)
data_s = data_s_match.group(1) if data_s_match else None
print(f"data-s: {data_s}")
Cách 2: Đọc qua Puppeteer khi trang render bằng JavaScript
Nếu trang chặn request không có JavaScript hoặc widget được chèn động, đọc thuộc tính sau khi trang đã render trong Puppeteer sẽ đáng tin cậy hơn regex trên HTML thô.
const puppeteer = require('puppeteer');
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://staging.example.com/qa-login', { waitUntil: 'networkidle2' });
const params = await page.evaluate(() => {
const widget = document.querySelector('.g-recaptcha');
if (!widget) return null;
return {
sitekey: widget.getAttribute('data-sitekey'),
size: widget.getAttribute('data-size'),
callback: widget.getAttribute('data-callback'),
dataS: widget.getAttribute('data-s'),
invisible: widget.getAttribute('data-size') === 'invisible',
};
});
console.log(params);
Cách 3: Lấy sitekey reCAPTCHA v3 và Enterprise từ thẻ script
Với v3 và Enterprise, không có data-sitekey — Google nhúng sitekey trực tiếp vào query string của URL script (render=), nên phải regex vào thẻ <script> thay vì widget:
# Find sitekey from script src
v3_match = re.search(
r'recaptcha/(?:api|enterprise)\.js\?.*?render=([A-Za-z0-9_-]+)',
html
)
if v3_match:
sitekey = v3_match.group(1)
print(f"v3 Sitekey: {sitekey}")
# Check enterprise
is_enterprise = 'enterprise.js' in html
print(f"Enterprise: {is_enterprise}")
Cách 4: Tìm tham số action trong JavaScript
action chỉ tồn tại trong lệnh gọi grecaptcha.execute(), không nằm ở bất kỳ thuộc tính HTML nào — phải regex vào JavaScript inline hoặc file JS bên ngoài:
# Search for grecaptcha.execute calls
action_match = re.search(
r'grecaptcha\.execute\s*\([^,]+,\s*\{[^}]*action\s*:\s*["\']([^"\']+)',
html
)
if action_match:
action = action_match.group(1)
print(f"Action: {action}")
Cách 5: Đọc src của iframe
Một số trang chỉ nhúng widget qua iframe mà không lộ data-sitekey ra ngoài — sitekey lúc này nằm trong query string k= của src trên chính iframe đó:
# Find reCAPTCHA iframe
iframe_match = re.search(
r'<iframe[^>]+src=["\']([^"\']*recaptcha/api2/anchor[^"\']*)["\']',
html
)
if iframe_match:
iframe_src = iframe_match.group(1)
sitekey_match = re.search(r'k=([A-Za-z0-9_-]+)', iframe_src)
if sitekey_match:
sitekey = sitekey_match.group(1)
print(f"Iframe sitekey: {sitekey}")
Cách 6: Bắt tham số khi reCAPTCHA render động
Trang gọi grecaptcha.render() bằng tay (thay vì dùng widget .g-recaptcha mặc định) thường truyền config dạng object — sitekey, callback và size nằm ngay trong tham số thứ hai của lệnh gọi đó:
# Find grecaptcha.render calls
render_match = re.search(
r'grecaptcha\.render\s*\([^,]*,\s*\{([^}]+)\}',
html
)
if render_match:
config = render_match.group(1)
sk = re.search(r'sitekey\s*:\s*["\']([A-Za-z0-9_-]+)', config)
cb = re.search(r'callback\s*:\s*["\']?(\w+)', config)
sz = re.search(r'size\s*:\s*["\'](\w+)', config)
print(f"Sitekey: {sk.group(1) if sk else 'not found'}")
print(f"Callback: {cb.group(1) if cb else 'not found'}")
print(f"Size: {sz.group(1) if sz else 'not found'}")
Hàm trích xuất tự động toàn bộ tham số
Gộp 4 nguồn sitekey ở Cách 1, 3, 5 và 6 vào một hàm duy nhất, thử lần lượt từng nguồn cho tới khi tìm được sitekey — dùng được ngay trong script test hoặc pipeline CI:
import re
import requests
def extract_recaptcha_params(url):
html = requests.get(url, timeout=15).text
params = {"pageurl": url}
# Sitekey from data-sitekey
sk = re.search(r'data-sitekey=["\']([A-Za-z0-9_-]+)', html)
if sk:
params["sitekey"] = sk.group(1)
# Sitekey from script render parameter (v3)
if "sitekey" not in params:
v3 = re.search(r'render=([A-Za-z0-9_-]{20,})', html)
if v3:
params["sitekey"] = v3.group(1)
# Sitekey from iframe
if "sitekey" not in params:
iframe = re.search(r'recaptcha.*?k=([A-Za-z0-9_-]+)', html)
if iframe:
params["sitekey"] = iframe.group(1)
# Sitekey from grecaptcha.render
if "sitekey" not in params:
render = re.search(r'sitekey\s*:\s*["\']([A-Za-z0-9_-]+)', html)
if render:
params["sitekey"] = render.group(1)
# Version detection
if re.search(r'data-size=["\']invisible', html):
params["invisible"] = True
if 'enterprise.js' in html:
params["enterprise"] = True
# Action (v3)
action = re.search(
r'action\s*:\s*["\']([^"\']+)',
html[html.find('grecaptcha.execute'):] if 'grecaptcha.execute' in html else ''
)
if action:
params["action"] = action.group(1)
# data-s
ds = re.search(r'data-s=["\']([^"\']+)', html)
if ds:
params["data_s"] = ds.group(1)
# Callback
cb = re.search(r'data-callback=["\'](\w+)', html)
if cb:
params["callback"] = cb.group(1)
return params
# Usage
params = extract_recaptcha_params("https://staging.example.com/qa-login")
for k, v in params.items():
print(f" {k}: {v}")
Kết quả in ra:
pageurl: https://staging.example.com/qa-login
sitekey: 6Le-SITEKEY-abc123
invisible: True
callback: onCaptchaComplete
Gửi tham số vừa trích xuất tới CaptchaAI
Sau khi có đủ params, map thẳng sang payload in.php — chỉ thêm invisible, enterprise, action hay data-s khi giá trị tương ứng thực sự tồn tại:
data = {
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": params["sitekey"],
"pageurl": params["pageurl"],
"json": "1",
}
if params.get("invisible"):
data["invisible"] = "1"
if params.get("enterprise"):
data["enterprise"] = "1"
if params.get("action"):
data["action"] = params["action"]
if params.get("data_s"):
data["data-s"] = params["data_s"]
resp = requests.post("https://ocr.captchaai.com/in.php", data=data).json()
Các lỗi thường gặp khi trích xuất tham số
| Vấn đề | Nguyên nhân | Cách xử lý |
|---|---|---|
| Không tìm thấy sitekey | Trang render động bằng JavaScript | Dùng Puppeteer/Selenium thay vì fetch HTML tĩnh |
| Sitekey sai, task báo lỗi | Trang có nhiều widget reCAPTCHA | Kiểm tra đúng widget nào ánh xạ tới form bạn đang submit |
Không tìm thấy action |
Được định nghĩa trong file JS bên ngoài | Tải và regex vào các file JavaScript liên kết |
data-s đổi mỗi lần tải trang |
Google tạo lại giá trị này theo phiên | Trích xuất data-s mới cho từng lần gửi task, không cache |
Câu hỏi thường gặp
Không mở trình duyệt thì có lấy được sitekey không?
Có, với phần lớn trang — sitekey nằm sẵn trong HTML tĩnh (data-sitekey, URL script hoặc iframe). Nhưng nếu widget được grecaptcha.render() chèn vào sau khi trang tải xong, bạn cần Puppeteer, Playwright hoặc Selenium để đọc đúng DOM đã render.
CaptchaAI có hỗ trợ reCAPTCHA Enterprise không?
Có. CaptchaAI giải cả reCAPTCHA v2 Enterprise và v3 Enterprise qua cùng method userrecaptcha — chỉ cần thêm enterprise=1 khi sitekey lấy được từ enterprise.js.
Vì sao sitekey trích xuất đúng mà task vẫn báo lỗi?
Thường gặp nhất là trang có nhiều widget reCAPTCHA cùng lúc và script lấy nhầm cái không liên kết với form đang test. Kiểm tra lại data-sitekey gắn với đúng form trước khi đưa vào googlekey.
action của reCAPTCHA v3 có bắt buộc khớp chính xác không?
Có. action phải trùng với giá trị trang gốc dùng khi gọi grecaptcha.execute(), vì Google chấm điểm rủi ro dựa trên action đó. Sai action không làm request lỗi ngay, nhưng có thể trả về token với điểm rủi ro không phản ánh đúng hành vi thật.
Dùng tham số vừa lấy được để gửi task ổn định
Lấy API key của bạn tại captchaai.com và test ngay với sitekey vừa trích xuất ở trên.
Hướng dẫn liên quan
- Phát hiện CAPTCHA qua console trình duyệt
- Cơ chế callback của reCAPTCHA v2
- reCAPTCHA v2 Invisible: phát hiện thời điểm kích hoạt