Khi người dùng hoàn thành thử thách reCAPTCHA v2, Google sẽ gọi hàm gọi lại JavaScript do trang web xác định. Cuộc gọi lại này thường kích hoạt nút gửi, xác thực biểu mẫu hoặc gửi yêu cầu AJAX. Sau khi đưa mã thông báo đã giải quyết từ CaptchaAI, bạn cần kích hoạt lệnh gọi lại tương tự — nếu không biểu mẫu sẽ không nhận ra rằng CAPTCHA đã được giải quyết.
Cách gọi lại hoạt động
Trang web xác định lệnh gọi lại trong tiện ích reCAPTCHA:
<div class="g-recaptcha"
data-sitekey="6Le-SITEKEY"
data-callback="onCaptchaSuccess"
data-expired-callback="onCaptchaExpired">
</div>
<script>
function onCaptchaSuccess(token) {
document.getElementById('submit-btn').disabled = false;
document.getElementById('captcha-token').value = token;
}
</script>
Khi người dùng giải CAPTCHA, JavaScript của Google sẽ gọi onCaptchaSuccess(token). Hàm nhận chuỗi mã thông báo làm đối số duy nhất của nó.
Tìm chức năng gọi lại
Cách 1: Kiểm tra thuộc tính data-callback
// In browser console
const widget = document.querySelector('.g-recaptcha');
const callbackName = widget?.getAttribute('data-callback');
console.log('Callback:', callbackName);
Cách 2: Kiểm tra nội bộ grecaptcha
Một số trang web sử dụng grecaptcha.render() với tùy chọn gọi lại thay vì thuộc tính data-callback:
// Search page source for grecaptcha.render
document.querySelectorAll('script:not([src])').forEach(s => {
if (s.textContent.includes('grecaptcha.render')) {
console.log(s.textContent.match(/callback\s*:\s*(\w+)/)?.[1]);
}
});
Cách 3: Chặn đăng ký gọi lại
Chạy phần này trong DevTools trước khi tải trang (Nguồn → Snippets):
const origRender = grecaptcha.render;
grecaptcha.render = function(container, params) {
console.log('Render callback:', params.callback);
console.log('Expired callback:', params['expired-callback']);
return origRender.apply(this, arguments);
};
Kích hoạt lệnh gọi lại sau khi chèn mã thông báo
Python (Selen)
import requests
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
API_KEY = "YOUR_API_KEY"
driver = webdriver.Chrome()
driver.get("https://staging.example.com/qa-login")
# Extract sitekey and callback
sitekey = driver.find_element(
By.CSS_SELECTOR, ".g-recaptcha"
).get_attribute("data-sitekey")
callback = driver.find_element(
By.CSS_SELECTOR, ".g-recaptcha"
).get_attribute("data-callback")
# Solve with CaptchaAI
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": driver.current_url,
"json": "1",
}).json()
task_id = resp["request"]
token = None
for _ in range(24):
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["status"] == 1:
token = result["request"]
break
# Inject token into textarea
driver.execute_script("""
document.querySelector('textarea[name="g-recaptcha-response"]').value = arguments[0];
""", token)
# Trigger the callback
if callback:
driver.execute_script(f"window['{callback}'](arguments[0]);", token)
print(f"Triggered callback: {callback}")
else:
# Fallback: try ___grecaptcha_cfg
driver.execute_script("""
try {
var widgetId = Object.keys(___grecaptcha_cfg.clients)[0];
var callback = ___grecaptcha_cfg.clients[widgetId].aa.l.callback;
if (typeof callback === 'function') callback(arguments[0]);
} catch(e) {}
""", token)
print("Triggered callback via ___grecaptcha_cfg")
JavaScript (Puppeteer)
const puppeteer = require('puppeteer');
// After solving and getting the token...
await page.evaluate((token, callbackName) => {
// Set textarea value
const textarea = document.querySelector(
'textarea[name="g-recaptcha-response"]'
);
textarea.value = token;
textarea.style.display = 'block'; // sometimes hidden
// Trigger callback
if (callbackName && typeof window[callbackName] === 'function') {
window[callbackName](token);
console.log(`Called ${callbackName}()`);
} else {
// Fallback: search grecaptcha config
try {
const clients = ___grecaptcha_cfg.clients;
const widgetId = Object.keys(clients)[0];
const cb = clients[widgetId]?.aa?.l?.callback;
if (typeof cb === 'function') cb(token);
} catch (e) {}
}
}, token, callbackName);
Các trang web không có dữ liệu gọi lại
Một số trang web không sử dụng lệnh gọi lại. Thay vào đó, họ kiểm tra grecaptcha.getResponse() khi biểu mẫu được gửi. Đối với các trang web này, hãy ghi đè chức năng:
driver.execute_script("""
const token = arguments[0];
document.querySelector('textarea[name="g-recaptcha-response"]').value = token;
// Override getResponse to return the token
if (typeof grecaptcha !== 'undefined') {
grecaptcha.getResponse = function() { return token; };
}
""", token)
# Then submit the form normally
driver.find_element(By.CSS_SELECTOR, "form").submit()
Cuộc gọi lại đã hết hạn
Một số trang web xác định data-expired-callback để tắt nút gửi khi mã thông báo hết hạn. Nếu mã thông báo của bạn sắp hết hạn, lệnh gọi lại này có thể kích hoạt và khóa lại biểu mẫu. Giải quyết gần thời gian nộp bài để tránh điều này.
// Check for expired callback
const expiredCallback = document.querySelector('.g-recaptcha')
?.getAttribute('data-expired-callback');
console.log('Expired callback:', expiredCallback);
Khắc phục sự cố
| Vấn đề | Nguyên nhân | Cách xử lý |
|---|---|---|
| Biểu mẫu vẫn bị vô hiệu hóa sau khi tiêm | Cuộc gọi lại không được kích hoạt | Tìm và gọi hàm gọi lại |
ReferenceError: function not defined |
Gọi lại được xác định trong một bao đóng | Sử dụng dự phòng ___grecaptcha_cfg |
| Đã chèn mã thông báo nhưng AJAX không được gửi | Gọi lại kích hoạt AJAX, không gửi biểu mẫu | Kiểm tra chức năng gọi lại làm gì |
| Mã thông báo được chấp nhận nhưng trang hiển thị lỗi | Mã thông báo đã hết hạn trước khi gọi lại | Giải quyết gần thời gian nộp bài |
Câu hỏi thường gặp
Điều gì sẽ xảy ra nếu không có cuộc gọi lại nào cả?
Một số trang web chỉ kiểm tra mã thông báo ở phía máy chủ khi biểu mẫu được gửi. Trong trường hợp đó, chỉ cần đặt giá trị vùng văn bản g-recaptcha-response và gửi biểu mẫu là đủ.
Tên hàm gọi lại có thể thay đổi giữa các lần tải trang không?
Có, trên một số trang web. Luôn trích xuất tên gọi lại một cách linh hoạt từ DOM thay vì mã hóa cứng nó.
reCAPTCHA v3 có sử dụng cơ chế gọi lại tương tự không?
Không. reCAPTCHA v3 sử dụng grecaptcha.execute() để trả về Lời hứa. Không có tiện ích hiển thị hoặc thuộc tính data-callback.
Giải quyết reCAPTCHA v2 bằng cách xử lý gọi lại thích hợp bằng CaptchaAI
Nhận khóa API của bạn tạicaptchaai.com.
Hướng dẫn liên quan
- reCAPTCHA v2 Vô hình: Phát hiện kích hoạt
- Trích xuất tham số reCAPTCHA từ nguồn trang
- Xử lý nhiều CAPTCHA trên một trang