Cả hai đều là biến thể reCAPTCHA v2 sử dụng cùng một công nghệ cơ bản. Phiên bản hộp kiểm hiển thị "Tôi không phải là người máy" và có thể hiển thị các lưới hình ảnh. Phiên bản ẩn tự động kích hoạt các hành động của người dùng (nhấp vào nút, gửi biểu mẫu hoặc tải trang) mà không có tiện ích hiển thị. Để giải quyết CaptchaAI, điểm khác biệt duy nhất là thêm invisible=1 vào yêu cầu của bạn — nhưng quy trình đưa mã thông báo khác biệt đáng kể.
So sánh song song
| tính năng | Hộp kiểm v2 | v2 Vô hình |
|---|---|---|
| Tiện ích hiển thị | Có - hộp kiểm "Tôi không phải là robot" | Không — ẩn với người dùng |
| Cơ chế kích hoạt | Hộp kiểm nhấp chuột của người dùng | Nhấp vào nút, gửi biểu mẫu hoặc tải trang |
| Thử thách hình ảnh | Hiển thị khi Google nghi ngờ bot | Cửa sổ bật lên ở góc dưới bên phải khi nghi ngờ |
| Trải nghiệm người dùng | Ma sát vừa phải | Ma sát Low/zero |
| Thực hiện | Thêm div g-recaptcha vào trang |
Thêm data-callback vào nút hoặc grecaptcha.execute() |
| Định dạng khóa trang web | Tương tự như vô hình | Tương tự như hộp kiểm |
| Trường mã thông báo | g-recaptcha-response |
g-recaptcha-response |
| Chức năng gọi lại | Tùy chọn | Hầu như luôn luôn cần thiết |
| Phương pháp CaptchaAI | method=userrecaptcha |
method=userrecaptcha + invisible=1 |
| Tuổi thọ của mã thông báo | 120 giây | 120 giây |
| Giải quyết thời gian | 10-30 giây | 10-25 giây |
Cách mỗi thứ xuất hiện trong HTML
Hộp kiểm v2
<!-- Standard checkbox widget -->
<div class="g-recaptcha"
data-sitekey="6Le-wvkSAAAAAPBMRTvw..."
data-callback="onSubmit">
</div>
<!-- Widget renders as: -->
<!-- [✓] I'm not a robot reCAPTCHA logo -->
Người dùng nhìn thấy và tương tác với hộp kiểm. Nếu Google nghi ngờ thì thử thách lưới hình ảnh sẽ xuất hiện nội tuyến.
v2 Vô hình
<!-- Pattern 1: Invisible widget on a button -->
<button class="g-recaptcha"
data-sitekey="6Le-wvkSAAAAAPBMRTvw..."
data-callback="onSubmit"
data-size="invisible">
Submit
</button>
<!-- Pattern 2: Invisible div (programmatic trigger) -->
<div class="g-recaptcha"
data-sitekey="6Le-wvkSAAAAAPBMRTvw..."
data-size="invisible"
data-callback="onSubmit">
</div>
<!-- Pattern 3: Programmatic render -->
<script>
grecaptcha.render('submit-btn', {
sitekey: '6Le-wvkSAAAAAPBMRTvw...',
callback: onSubmit,
size: 'invisible'
});
</script>
Không có tiện ích hiển thị. reCAPTCHA kích hoạt khi người dùng kích hoạt phần tử được chỉ định hoặc khi grecaptcha.execute() được gọi.
Cách phát hiện biến thể nào trên một trang
Phát hiện Python:
import requests
from bs4 import BeautifulSoup
import re
def detect_recaptcha_variant(url):
resp = requests.get(url)
soup = BeautifulSoup(resp.text, "html.parser")
# Check for invisible indicators
invisible_widget = soup.find(attrs={"data-size": "invisible", "class": "g-recaptcha"})
if invisible_widget:
return {
"variant": "invisible",
"sitekey": invisible_widget.get("data-sitekey"),
"callback": invisible_widget.get("data-callback")
}
# Check for programmatic invisible in scripts
for script in soup.find_all("script"):
if script.string and "invisible" in str(script.string):
key_match = re.search(r"sitekey['\"]?\s*[:=]\s*['\"]([^'\"]+)", script.string)
if key_match:
return {
"variant": "invisible-programmatic",
"sitekey": key_match.group(1),
"callback": "check grecaptcha.render() call"
}
# Check for standard checkbox
checkbox_widget = soup.find(class_="g-recaptcha")
if checkbox_widget:
return {
"variant": "checkbox",
"sitekey": checkbox_widget.get("data-sitekey"),
"callback": checkbox_widget.get("data-callback")
}
return None
result = detect_recaptcha_variant("https://staging.example.com/qa-login")
print(result)
Phát hiện Node.js:
const axios = require("axios");
const cheerio = require("cheerio");
async function detectRecaptchaVariant(url) {
const { data } = await axios.get(url);
const $ = cheerio.load(data);
// Check for invisible
const invisible = $(".g-recaptcha[data-size='invisible']");
if (invisible.length) {
return {
variant: "invisible",
sitekey: invisible.attr("data-sitekey"),
callback: invisible.attr("data-callback"),
};
}
// Check scripts for programmatic invisible
const scripts = $("script")
.map((_, el) => $(el).html())
.get()
.join("\n");
if (scripts.includes("invisible")) {
const keyMatch = scripts.match(/sitekey['"]?\s*[:=]\s*['"]([^'"]+)/);
if (keyMatch) {
return {
variant: "invisible-programmatic",
sitekey: keyMatch[1],
callback: "check render call",
};
}
}
// Check for standard checkbox
const checkbox = $(".g-recaptcha");
if (checkbox.length) {
return {
variant: "checkbox",
sitekey: checkbox.attr("data-sitekey"),
callback: checkbox.attr("data-callback"),
};
}
return null;
}
Kiểm tra bảng điều khiển trình duyệt nhanh:
const el = document.querySelector('[data-size="invisible"]');
console.log(el ? "Invisible reCAPTCHA" : "Checkbox reCAPTCHA");
| Tín hiệu phát hiện | Hộp kiểm v2 | v2 Vô hình |
|---|---|---|
data-size="invisible" |
Không có mặt | hiện tại |
| Hộp kiểm hiển thị trên trang | Có | Không |
grecaptcha.execute() đã gọi |
Không (số nhấp chuột của người dùng) | Có (có lập trình) |
| Vị trí bật lên thách thức | Hộp kiểm nội tuyến, bên dưới | Góc dưới bên phải của trang |
Giải quyết bằng CaptchaAI
Hộp kiểm v2
import requests
import time
resp = requests.get("https://ocr.captchaai.com/in.php", params={
"key": "YOUR_API_KEY",
"method": "userrecaptcha",
"googlekey": "6Le-wvkSAAAA...",
"pageurl": "https://example.com/form"
})
task_id = resp.text.split("|")[1]
for _ in range(60):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": "YOUR_API_KEY", "action": "get", "id": task_id
})
if result.text.startswith("OK|"):
token = result.text.split("|")[1]
break
v2 Vô hình
import requests
import time
resp = requests.get("https://ocr.captchaai.com/in.php", params={
"key": "YOUR_API_KEY",
"method": "userrecaptcha",
"googlekey": "6Le-wvkSAAAA...",
"pageurl": "https://example.com/form",
"invisible": 1 # Only parameter difference
})
task_id = resp.text.split("|")[1]
for _ in range(60):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": "YOUR_API_KEY", "action": "get", "id": task_id
})
if result.text.startswith("OK|"):
token = result.text.split("|")[1]
break
Tiêm mã thông báo - sự khác biệt quan trọng
Hộp kiểm v2: Trường ẩn thường là đủ
# Selenium — inject into hidden field
driver.execute_script(
f'document.getElementById("g-recaptcha-response").value = "{token}";'
)
# If the page uses a callback, also call it
callback = driver.find_element("css selector", ".g-recaptcha").get_attribute("data-callback")
if callback:
driver.execute_script(f'{callback}("{token}");')
v2 Vô hình: Hầu như luôn cần phải gọi lại
# Selenium — inject AND call the callback
driver.execute_script(
f'document.getElementById("g-recaptcha-response").value = "{token}";'
)
# CRITICAL: Invisible reCAPTCHA almost always requires calling the callback
callback_name = driver.find_element(
"css selector", ".g-recaptcha[data-size='invisible']"
).get_attribute("data-callback")
driver.execute_script(f'{callback_name}("{token}");')
// Puppeteer — invisible callback injection
await page.evaluate((tok) => {
// Set the hidden field
document.getElementById("g-recaptcha-response").value = tok;
// Find and call the callback function
const widget = document.querySelector("[data-size='invisible']");
const cbName = widget?.getAttribute("data-callback");
if (cbName && typeof window[cbName] === "function") {
window[cbName](tok);
}
}, token);
Sự khác biệt chính: Biểu mẫu hộp kiểm v2 thường chỉ hoạt động với thao tác chèn trường ẩn vì nhấp chuột của người dùng vào hộp kiểm đã đăng ký lệnh gọi lại. ReCAPTCHA vô hình không bao giờ có lượt nhấp chuột đó — lệnh gọi lại phải được gọi một cách rõ ràng.
Bộ giải phổ quát cho cả hai biến thể
import requests
import time
from bs4 import BeautifulSoup
class RecaptchaV2UniversalSolver:
def __init__(self, api_key):
self.api_key = api_key
def detect_and_solve(self, page_url, page_html=None):
if not page_html:
page_html = requests.get(page_url).text
soup = BeautifulSoup(page_html, "html.parser")
# Detect variant
invisible = soup.find(attrs={"data-size": "invisible", "class": "g-recaptcha"})
widget = invisible or soup.find(class_="g-recaptcha")
if not widget:
raise Exception("No reCAPTCHA widget found")
sitekey = widget.get("data-sitekey")
is_invisible = invisible is not None
callback = widget.get("data-callback")
params = {
"key": self.api_key,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": page_url
}
if is_invisible:
params["invisible"] = 1
resp = requests.get("https://ocr.captchaai.com/in.php", params=params)
if not resp.text.startswith("OK|"):
raise Exception(f"Submit failed: {resp.text}")
task_id = resp.text.split("|")[1]
for _ in range(60):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": self.api_key, "action": "get", "id": task_id
})
if result.text.startswith("OK|"):
return {
"token": result.text.split("|")[1],
"variant": "invisible" if is_invisible else "checkbox",
"callback": callback,
"sitekey": sitekey
}
if result.text != "CAPCHA_NOT_READY":
raise Exception(f"Solve error: {result.text}")
raise Exception("Timed out")
# Usage
solver = RecaptchaV2UniversalSolver("YOUR_API_KEY")
result = solver.detect_and_solve("https://staging.example.com/qa-login")
print(f"Variant: {result['variant']}, Callback: {result['callback']}")
Khắc phục sự cố
| vấn đề | Sửa hộp kiểm | Sửa chữa vô hình |
|---|---|---|
| Mã thông báo không được chấp nhận | Đưa vào trường g-recaptcha-response |
Tiêm VÀ gọi hàm data-callback |
| Không tìm thấy tiện ích | Tìm lớp .g-recaptcha |
Kiểm tra các cuộc gọi kết xuất data-size="invisible" hoặc tập lệnh |
| Gửi biểu mẫu nhưng không thành công | Kiểm tra xem cuộc gọi lại có được mong đợi không | Gọi lại hầu như luôn được yêu cầu - tìm và gọi nó |
| Trang tải lại sau khi tiêm | Xác thực JavaScript không thành công | Gọi lại trước trình kích hoạt tự động gửi biểu mẫu |
Câu hỏi thường gặp
ReCAPTCHA vô hình có khó giải quyết hơn không?
Không. Quá trình giải quyết thông qua CaptchaAI gần như giống hệt nhau. Việc thêm invisible=1 vào yêu cầu của bạn là thay đổi duy nhất. Thử thách thêm nằm ở phía tiêm: bạn phải tìm và thực thi chức năng gọi lại.
Cả hai đều sử dụng cùng một định dạng khóa trang web phải không?
Vâng. Định dạng khóa trang web giống hệt nhau. Bạn không thể chỉ biết biến thể chỉ từ khóa trang web — hãy kiểm tra data-size="invisible" trong HTML.
ReCAPTCHA vô hình vẫn hiển thị các thách thức về hình ảnh phải không?
Vâng. Khi Google phát hiện hành vi đáng ngờ, reCAPTCHA vô hình sẽ hiển thị cửa sổ bật lên thử thách hình ảnh ở góc dưới cùng bên phải của trang. Đây là lý do tại sao bạn vẫn cần CaptchaAI - phiên bản vô hình vẫn có thể đưa ra những thách thức.
Một trang web có thể chuyển đổi giữa hộp kiểm và ẩn không?
Vâng. Đây là sự thay đổi cấu hình ở phía cuối trang web — cùng một khóa trang web, cách triển khai khác nhau. Một số trang web sử dụng hộp kiểm trên máy tính để bàn và ẩn trên thiết bị di động. Luôn phát hiện biến thể một cách linh hoạt.
Giải quyết cái nào nhanh hơn?
Các giải pháp vô hình thường nhanh hơn một chút (10-25 giây so với 10-30 giây) vì chúng có xu hướng gây ra ít thử thách hình ảnh hơn. Nhưng sự khác biệt là rất nhỏ.
Hướng dẫn liên quan
- Cách giải reCAPTCHA v2 bằng API- hướng dẫn hộp kiểm v2 đầy đủ
- reCAPTCHA Invisible hoạt động như thế nào- giải thích cơ chế vô hình
- Cách giải reCAPTCHA Invisible bằng API- hướng dẫn giải quyết vô hình
- Các lỗi và cách khắc phục reCAPTCHA Invisible thường gặp- xử lý sự cố vô hình
- Cách giải reCAPTCHA Invisible bằng API
- reCAPTCHA Invisible hoạt động như thế nào
- Giải thích về reCAPTCHA v2 so với v3