Một số trang web triển khai cả reCAPTCHA v2 và v3 trên cùng một trang. Mẫu điển hình là: v3 chạy ẩn ở chế độ nền và nếu điểm quá thấp, v2 sẽ xuất hiện dưới dạng thử thách dự phòng rõ ràng. Việc triển khai kép này tạo ra sự nhầm lẫn cho quá trình tự động hóa vì bạn cần xử lý hai loại CAPTCHA khác nhau bằng các phương pháp giải khác nhau. Hướng dẫn này bao gồm các chiến lược phát hiện, giải quyết và các trường hợp khó khăn phổ biến.
Tại sao các trang web sử dụng cả v2 và v3 cùng nhau
User visits page
↓
reCAPTCHA v3 runs invisibly in background
↓
Score returned to server (e.g., 0.4)
↓
Score below threshold (e.g., < 0.7)?
├─ YES → Show reCAPTCHA v2 checkbox/image challenge
└─ NO → Allow action without visible CAPTCHA
Mẫu này cung cấp tốt nhất của cả hai thế giới:
- Hầu hết người dùng (điểm v3 cao) không thấy CAPTCHA → ít ma sát
- Người dùng đáng ngờ (điểm v3 thấp) xem thử thách v2 Dự phòng bảo mật →
- Nhà điều hành trang web kiểm soát ngưỡng giữa ẩn và hiển thị
Các mẫu triển khai kép
Mẫu 1: Đánh giá trước v3 + dự phòng v2
Mẫu phổ biến nhất. v3 chạy trước và v2 chỉ xuất hiện nếu cần.
<!-- Both scripts loaded -->
<script src="https://www.google.com/recaptcha/api.js?render=V3_SITE_KEY"></script>
<script src="https://www.google.com/recaptcha/api.js?render=explicit" async defer></script>
<form id="loginForm">
<!-- v2 widget (hidden initially) -->
<div id="recaptcha-v2-container" style="display:none;">
<div class="g-recaptcha" data-sitekey="V2_SITE_KEY"></div>
</div>
<button type="submit">Login</button>
</form>
<script>
// First attempt: v3 invisible
grecaptcha.ready(function() {
grecaptcha.execute('V3_SITE_KEY', {action: 'login'}).then(function(v3Token) {
fetch('/api/verify-v3', {
method: 'POST',
body: JSON.stringify({token: v3Token})
})
.then(r => r.json())
.then(data => {
if (data.score < 0.7) {
// Score too low → show v2 fallback
document.getElementById('recaptcha-v2-container').style.display = 'block';
grecaptcha.render('recaptcha-v2-container', {sitekey: 'V2_SITE_KEY'});
} else {
// Score OK → submit form directly
document.getElementById('loginForm').submit();
}
});
});
});
</script>
Mẫu 2: Các khóa trang web khác nhau cho các hành động khác nhau
Một số trang web sử dụng v3 để giám sát thụ động và v2 cho các hành động có rủi ro cao cụ thể:
Homepage → v3 only (passive score)
Login page → v3 assessment, v2 fallback
Checkout → v2 always (high security)
Contact form → v3 only
Mẫu 3: Chữ đơn, chế độ kép
Google hỗ trợ tải một tập lệnh reCAPTCHA duy nhất xử lý cả v2 và v3:
<script src="https://www.google.com/recaptcha/api.js?render=V3_SITE_KEY"></script>
<script>
// v3 execute
grecaptcha.execute('V3_SITE_KEY', {action: 'login'});
// v2 render (uses a different site key)
grecaptcha.render('v2-container', {sitekey: 'V2_SITE_KEY'});
</script>
Phát hiện triển khai kép
Phát hiện Python
import requests
import re
def detect_dual_recaptcha(url):
"""Detect if a page uses both reCAPTCHA v2 and v3."""
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/120.0.0.0 Safari/537.36",
}
html = requests.get(url, headers=headers, timeout=15).text
result = {
"has_v3": False,
"has_v2": False,
"v3_site_key": None,
"v2_site_key": None,
"dual": False,
"pattern": None,
}
# Detect v3 (render parameter or enterprise.execute)
v3_match = re.search(r"api\.js\?render=([A-Za-z0-9_-]+)", html)
if v3_match and v3_match.group(1) != "explicit":
result["has_v3"] = True
result["v3_site_key"] = v3_match.group(1)
# Detect v3 in execute calls
v3_execute = re.search(
r"grecaptcha\.(?:enterprise\.)?execute\s*\(\s*['\"]([^'\"]+)['\"]",
html,
)
if v3_execute:
result["has_v3"] = True
if not result["v3_site_key"]:
result["v3_site_key"] = v3_execute.group(1)
# Detect v2 (g-recaptcha class or explicit render)
v2_match = re.search(r'data-sitekey="([^"]+)"', html)
if v2_match:
key = v2_match.group(1)
if key != result.get("v3_site_key"):
result["has_v2"] = True
result["v2_site_key"] = key
# Check for explicit v2 render
v2_render = re.search(
r"grecaptcha\.render\s*\([^,]+,\s*\{[^}]*sitekey:\s*['\"]([^'\"]+)",
html,
)
if v2_render:
result["has_v2"] = True
if not result["v2_site_key"]:
result["v2_site_key"] = v2_render.group(1)
result["dual"] = result["has_v3"] and result["has_v2"]
if result["dual"]:
# Determine pattern
if "display:none" in html or "display: none" in html:
result["pattern"] = "v3_pre_assessment_v2_fallback"
else:
result["pattern"] = "v2_v3_simultaneous"
return result
detection = detect_dual_recaptcha("https://staging.example.com/qa-login")
print(detection)
Phát hiện Node.js
const axios = require("axios");
async function detectDualRecaptcha(url) {
const { data: html } = await axios.get(url, { timeout: 15000 });
const result = {
hasV3: false,
hasV2: false,
v3SiteKey: null,
v2SiteKey: null,
dual: false,
};
// v3 detection
const v3Match = html.match(/api\.js\?render=([A-Za-z0-9_-]+)/);
if (v3Match && v3Match[1] !== "explicit") {
result.hasV3 = true;
result.v3SiteKey = v3Match[1];
}
// v2 detection
const v2Match = html.match(/data-sitekey="([^"]+)"/);
if (v2Match && v2Match[1] !== result.v3SiteKey) {
result.hasV2 = true;
result.v2SiteKey = v2Match[1];
}
result.dual = result.hasV3 && result.hasV2;
return result;
}
detectDualRecaptcha("https://staging.example.com/qa-login").then(console.log);
Giải quyết các chiến lược cho reCAPTCHA kép
Chiến lược 1: Giải v3 trước, sau đó đến v2 nếu cần
Chiến lược tối ưu phản ánh dòng chảy riêng của trang web:
import requests
import time
API_KEY = "YOUR_API_KEY"
def solve_v3(site_key, page_url, action="login"):
"""Solve reCAPTCHA v3 and return token."""
submit = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": site_key,
"pageurl": page_url,
"version": "v3",
"action": action,
"json": 1,
}).json()
task_id = submit["request"]
for _ in range(60):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "get", "id": task_id, "json": 1,
}).json()
if result.get("status") == 1:
return result["request"]
raise TimeoutError("v3 solve timeout")
def solve_v2(site_key, page_url):
"""Solve reCAPTCHA v2 and return token."""
submit = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": site_key,
"pageurl": page_url,
"json": 1,
}).json()
task_id = submit["request"]
for _ in range(60):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "get", "id": task_id, "json": 1,
}).json()
if result.get("status") == 1:
return result["request"]
raise TimeoutError("v2 solve timeout")
def solve_dual_recaptcha(v3_key, v2_key, page_url, action="login"):
"""Handle dual reCAPTCHA: try v3, fall back to v2."""
# Step 1: Try v3
v3_token = solve_v3(v3_key, page_url, action)
# Step 2: Submit v3 token to target
response = requests.post(f"{page_url}/verify", data={
"g-recaptcha-response": v3_token,
})
# Step 3: Check if v2 fallback is needed
if "recaptcha" in response.text.lower() and v2_key:
print("v3 score too low — v2 fallback triggered")
v2_token = solve_v2(v2_key, page_url)
return {"version": "v2", "token": v2_token}
return {"version": "v3", "token": v3_token}
result = solve_dual_recaptcha(
v3_key="6LcExample_v3_key",
v2_key="6LcExample_v2_key",
page_url="https://staging.example.com/qa-login",
)
print(f"Solved with {result['version']}")
Cách 2: Bỏ v3, giải trực tiếp v2
Nếu bạn biết trang web luôn hiển thị v2 cho lưu lượng truy cập tự động (điểm v3 sẽ thấp), hãy bỏ qua v3 và giải quyết v2 ngay lập tức:
# If you consistently fail v3 assessment, just solve v2 directly
token = solve_v2(v2_site_key, page_url)
submit_form(token)
Điều này giúp tiết kiệm thời gian và chi phí cho việc giải quyết v3 có thể không vượt qua ngưỡng.
Chiến lược 3: Xử lý dựa trên trình duyệt
Đối với các hoạt động triển khai phức tạp, hãy sử dụng trình duyệt để xử lý luồng dự phòng:
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
driver = webdriver.Chrome()
driver.get("https://staging.example.com/qa-login")
time.sleep(3)
# Check if v2 widget is visible
v2_visible = driver.execute_script("""
const container = document.querySelector('.g-recaptcha');
if (!container) return false;
const style = window.getComputedStyle(container.parentElement);
return style.display !== 'none' && style.visibility !== 'hidden';
""")
if v2_visible:
# v2 is showing — solve v2
sitekey = driver.find_element(
By.CSS_SELECTOR, "[data-sitekey]"
).get_attribute("data-sitekey")
token = solve_v2(sitekey, driver.current_url)
driver.execute_script(
f'document.getElementById("g-recaptcha-response").value = "{token}";'
)
else:
# v3 only — solve v3
# Extract v3 key from page source
v3_key = driver.execute_script(
"return document.querySelector('script[src*=\"render=\"]')"
".src.match(/render=([^&]+)/)[1];"
)
token = solve_v3(v3_key, driver.current_url)
# Inject v3 token into the form
driver.execute_script(f"""
const input = document.createElement('input');
input.type = 'hidden';
input.name = 'g-recaptcha-response';
input.value = '{token}';
document.querySelector('form').appendChild(input);
""")
driver.find_element(By.CSS_SELECTOR, "form").submit()
Vỏ cạnh
Hai khóa trang web khác nhau trên cùng một trang
Các trang web sử dụng reCAPTCHA kép sẽ có HAI khóa trang web khác nhau - một cho v3 và một cho v2. Khóa v3 xuất hiện trong URL tập lệnh ?render=KEY và trong grecaptcha.execute('KEY', ...). Khóa v2 xuất hiện trong data-sitekey="KEY" trên div tiện ích. Sử dụng sai key cho phiên bản sai sẽ tạo ra token không hợp lệ.
reCAPTCHA Enterprise với dự phòng v2
Một số triển khai Enterprise sử dụng v3 Enterprise để tính điểm và v2 cho các thử thách:
# Detect and handle Enterprise + v2 combo
if "recaptcha/enterprise.js" in html:
# Use enterprise parameter for v3
v3_params = {"enterprise": 1, "version": "v3"}
else:
v3_params = {"version": "v3"}
Nhiều biểu mẫu trên một trang
Nếu một trang có nhiều biểu mẫu (đăng nhập + đăng ký), mỗi biểu mẫu có thể có phiên bản reCAPTCHA riêng. Trích xuất khóa trang web từ biểu mẫu cụ thể mà bạn đang nhắm mục tiêu:
# Target the login form specifically
login_form = soup.find("form", id="login-form")
widget = login_form.find(attrs={"data-sitekey": True})
sitekey = widget["data-sitekey"]
Câu hỏi thường gặp
Tôi có cần giải cả v2 và v3 trên cùng một trang không?
Không. Thông thường, bạn giải v3 trước (nó chạy tự động). Nếu điểm v3 vượt qua ngưỡng của trang web, không có thử thách v2 nào xuất hiện và bạn đã hoàn thành. Bạn chỉ cần giải v2 nếu điểm v3 kích hoạt dự phòng.
Tôi có thể sử dụng một lệnh gọi API CaptchaAI cho reCAPTCHA kép không?
Số v2 và v3 là các loại CAPTCHA riêng biệt với các khóa trang web và phương pháp giải khác nhau. Mỗi yêu cầu lệnh gọi API riêng tới CaptchaAI. Tuy nhiên, bạn chỉ cần thực hiện một cuộc gọi nếu v3 vượt qua mà không kích hoạt v2.
Làm cách nào để biết liệu dự phòng v2 có được kích hoạt hay không?
Kiểm tra phản hồi của máy chủ sau khi gửi mã thông báo v3. Nếu phản hồi chứa HTML tiện ích v2 hoặc kích hoạt thử thách v2 (chuyển hướng hoặc phản hồi AJAX bằng HTML CAPTCHA), thì dự phòng đã được kích hoạt. Trong trình duyệt, hãy kiểm tra xem vùng chứa v2 có hiển thị sau khi gửi v3 hay không.
Tôi sử dụng khóa trang web nào cho mỗi phiên bản?
Khóa trang v3 nằm trong URL tập lệnh: api.js?render=V3_KEY. Khóa trang web v2 có trong tiện ích HTML: data-sitekey="V2_KEY". Chúng luôn là những chìa khóa khác nhau.
Tóm tắt
Việc triển khai reCAPTCHA kép sử dụng v3 để đánh giá trước vô hình và v2 làm dự phòng rõ ràng khi điểm v3 quá thấp. Phát hiện cả hai phiên bản bằng cách kiểm tra tham số kết xuất (v3) và widget data-sitekey (v2). Chiến lược tự động hóa tối ưu là: giải v3 trước bằngCaptchaAI, gửi mã thông báo và chỉ giải quyết v2 nếu kích hoạt dự phòng. Mỗi phiên bản yêu cầu một lệnh gọi API riêng với khóa trang web riêng.
bài viết liên quan
- Ứng dụng trang đơn Recaptcha động
- Cách giải quyết cuộc gọi lại Recaptcha V2 bằng Api
- Xử lý cửa quay Recaptcha V2 trên cùng một trang web