GeeTest v3 không dùng một token duy nhất như reCAPTCHA — nó xâu chuỗi ba nhóm giá trị: gt (định danh trang), challenge (token phiên dùng một lần) và bộ ba geetest_challenge / geetest_validate / geetest_seccode sinh ra sau khi người dùng giải xong. Sai thứ tự lấy — dùng — nộp các giá trị này, hoặc dùng challenge đã hết hạn, là lý do phổ biến nhất khiến request tới CaptchaAI bị từ chối. Bài viết đi qua từng bước của quy trình phản hồi thử thách GeeTest v3, kèm code Python trích xuất tham số và request thực tế gửi tới CaptchaAI.
GeeTest v3 hoạt động qua hai giai đoạn phản hồi thử thách
Toàn bộ quy trình chia làm hai giai đoạn tách biệt — một giai đoạn chạy ở server của trang web, một giai đoạn chạy trên trình duyệt của người dùng:
Giai đoạn 1 — đăng ký thử thách ở phía server
Backend của trang web liên hệ GeeTest để xin một thử thách mới cho phiên hiện tại:
Site Backend → GeeTest Server: "Give me a challenge for this user"
GeeTest Server → Site Backend: { gt, challenge, new_captcha }
Site Backend → Browser: Passes gt and challenge to the page
Giai đoạn 2 — người dùng giải, server xác minh
Trình duyệt hiển thị thử thách bằng gt và challenge nhận được, người dùng thao tác (kéo thanh trượt, bấm icon…), rồi kết quả được gửi ngược về server để xác minh với GeeTest:
Browser: Renders slider/puzzle using gt + challenge
User: Solves the challenge
Browser → Site Backend: { geetest_challenge, geetest_validate, geetest_seccode }
Site Backend → GeeTest Server: Verifies the three values
GeeTest Server → Site Backend: { result: "success" }
GeeTest online và offline khác nhau thế nào
GeeTest v3 có chế độ dự phòng khi không kết nối được máy chủ GeeTest:
- Trực tuyến (
success=1) — phản hồi thử thách thông thường với máy chủ GeeTest. - Ngoại tuyến (
success=0) — xác minh cục bộ, đơn giản hoá, thử thách tạo ngay trên trình duyệt.
Phần lớn trang production dùng chế độ trực tuyến, nên các ví dụ dưới đây theo luồng đó.
Dưới đây là năm bước của quy trình phản hồi thử thách GeeTest v3 ở chế độ trực tuyến, từ lúc trang load tới lúc server xác nhận kết quả.
Bước 1 — gọi API đăng ký lấy gt và challenge
Backend gọi endpoint đăng ký của GeeTest:
GET https://api.geetest.com/register.php?gt=GT_ID&json_format=1
Kết quả trả về:
{
"success": 1,
"gt": "81dc9bdb52d04dc20036dbd8313ed055",
"challenge": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
"new_captcha": true
}
Ý nghĩa từng tham số:
gt— GeeTest ID, định danh tài khoản GeeTest của trang web.challenge— token thử thách, chỉ dùng cho phiên này.new_captcha— có dùng định dạng CAPTCHA mới hay không.
Lưu ý: giá trị
challengechỉ dùng được một lần và có thời hạn. Mỗi lần trang được tải lại, GeeTest sinh ra mộtchallengemới.
Bước 2 — trình duyệt render widget GeeTest
Trang nhận gt và challenge, rồi khởi tạo widget:
initGeetest({
gt: "81dc9bdb52d04dc20036dbd8313ed055",
challenge: "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
offline: false,
new_captcha: true,
product: "float"
}, function(captchaObj) {
captchaObj.appendTo('#captcha-container');
captchaObj.onSuccess(function() {
var result = captchaObj.getValidate();
// result contains: geetest_challenge, geetest_validate, geetest_seccode
});
});
Bước 3 — GeeTest chọn loại thử thách nào
GeeTest v3 có nhiều dạng thử thách, và trang web không tự chọn — GeeTest quyết định dựa trên cấu hình trang và hồ sơ rủi ro của người dùng:
Bốn dạng thử thách GeeTest v3 có thể hiển thị:
- Thanh trượt — kéo mảnh ghép để khớp đúng vị trí trong ảnh.
- Nhấp icon — bấm các biểu tượng đúng thứ tự hiển thị.
- Nhấp chữ — bấm ký tự tiếng Trung theo đúng thứ tự.
- Không gian — thử thách suy luận không gian, bấm/chọn theo yêu cầu.
Với CaptchaAI, loại thử thách không ảnh hưởng cách gửi request — luôn nộp cùng gt và challenge.
Bước 4 — ba giá trị trả về sau khi giải
Sau khi người dùng hoàn thành thử thách, widget sinh ra ba giá trị:
{
"geetest_challenge": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6xy",
"geetest_validate": "abc123def456_validate",
"geetest_seccode": "abc123def456_validate|jordan"
}
geetest_challenge— token thử thách đã biến đổi (bản gốc cộng thêm 2 ký tự).geetest_validate— hash xác thực.geetest_seccode— mã bảo mật (validate cộng hậu tố\|jordan).
Bước 5 — server gửi kết quả cho GeeTest xác minh
Backend gửi cả ba giá trị này cho GeeTest để xác nhận:
POST https://api.geetest.com/validate.php
seccode=abc123def456_validate|jordan
&challenge=a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6xy
&sdk=geetest-python-3.0.0
GeeTest phản hồi:
{
"seccode": "abc123def456_validate",
"validate": "abc123def456_validate"
}
Để CaptchaAI giải thử thách thay bạn, bạn phải tự lấy gt và challenge từ trang trước khi gọi API — có ba cách phổ biến để lấy hai giá trị này.
Ví dụ thực tế: một đội QA automation tại công ty outsourcing ở TP.HCM kiểm thử luồng đăng nhập được bảo vệ bởi GeeTest v3 slider trên staging trước khi release. Thay vì giải thủ công mỗi lần chạy CI, họ dùng Playwright chặn response đăng ký, lấy gt/challenge, rồi gửi cho CaptchaAI — pipeline end-to-end chạy tự động, không cần người ngồi giải captcha.
Cách 1 — bắt response của request đăng ký
from playwright.sync_api import sync_playwright
import json
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
geetest_params = {}
def handle_response(response):
if "register" in response.url and "geetest" in response.url:
data = response.json()
geetest_params["gt"] = data.get("gt")
geetest_params["challenge"] = data.get("challenge")
page.on("response", handle_response)
page.goto("https://staging.example.com/qa-login")
# Wait for GeeTest to load
page.wait_for_selector(".geetest_holder")
print(f"gt: {geetest_params.get('gt')}")
print(f"challenge: {geetest_params.get('challenge')}")
Cách 2 — đọc trực tiếp từ DOM
Nếu trang lưu gt/challenge trong thuộc tính data-*, đọc thẳng bằng JavaScript evaluate:
gt = page.evaluate("() => document.querySelector('[data-gt]')?.dataset.gt")
challenge = page.evaluate("() => document.querySelector('[data-challenge]')?.dataset.challenge")
Cách 3 — tìm trong lệnh gọi initGeetest
Khi hai cách trên không khả dụng, tìm trực tiếp trong mã nguồn trang, nơi initGeetest được gọi:
import re
source = page.content()
gt_match = re.search(r"gt['\"]?\s*[:=]\s*['\"]([a-f0-9]{32})['\"]", source)
challenge_match = re.search(r"challenge['\"]?\s*[:=]\s*['\"]([a-f0-9]{32})['\"]", source)
Gửi gt và challenge tới CaptchaAI để lấy seccode
Với gt và challenge đã có, gửi task tới CaptchaAI:
POST https://ocr.captchaai.com/in.php
key=YOUR_API_KEY
&method=geetest
>=81dc9bdb52d04dc20036dbd8313ed055
&challenge=a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
&pageurl=https://staging.example.com/qa-login
&json=1
Polling kết quả:
GET https://ocr.captchaai.com/res.php?key=YOUR_API_KEY&action=get&id=TASK_ID&json=1
CaptchaAI trả về:
{
"status": 1,
"request": {
"geetest_challenge": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6xy",
"geetest_validate": "abc123def456_validate",
"geetest_seccode": "abc123def456_validate|jordan"
}
}
Ba giá trị này — geetest_challenge, geetest_validate, geetest_seccode — chính là những gì bước xác minh phía server của trang web cần, y hệt như khi người dùng tự giải.
Các lỗi thường gặp khi tích hợp GeeTest v3
challengerỗng — bước đăng ký thất bại; kiểm tra xem trang có load GeeTest đúng cách không.- Giải pháp bị từ chối —
challengeđã hết hạn; lấychallengemới và giải ngay, không trì hoãn. - Sai giá trị
gt— trang có nhiều widget GeeTest; trích xuấtgttừ đúng widget đang hiển thị. - Trả đủ ba giá trị nhưng form không submit — thiếu trường input trên form; điền cả ba giá trị vào đúng input tương ứng.
Câu hỏi thường gặp về GeeTest v3
CaptchaAI có hỗ trợ giải GeeTest v4 không?
Chưa. CaptchaAI hiện chỉ hỗ trợ GeeTest v3 (method=geetest); GeeTest v4 đang sắp ra mắt, chưa có ngày phát hành chính thức.
Nên trích xuất gt và challenge vào thời điểm nào trong pipeline automation?
Ngay sau khi widget GeeTest render xong, thường là lúc selector .geetest_holder xuất hiện. Trích xuất càng sớm càng tốt vì challenge có thời hạn ngắn, chỉ khoảng 1–2 phút.
Loại thử thách (thanh trượt, icon, chữ Hán) có làm thay đổi cách gọi CaptchaAI không?
Không. Dù GeeTest hiển thị thanh trượt, icon hay chữ Hán, bạn luôn gửi cùng cặp gt/challenge tới in.php với method=geetest.
Vì sao request gửi tới CaptchaAI báo challenge không hợp lệ dù vừa lấy xong?
Nhiều khả năng challenge đã bị dùng hoặc hết hạn — mỗi challenge chỉ giải được một lần, thường hết hạn sau 1–2 phút. Lấy challenge mới ngay trước khi gửi, đừng cache lại để dùng nhiều lần.
Bài viết liên quan
- Giải GeeTest v3 bằng Node.js
- Tích hợp CaptchaAI giải GeeTest v3 trong Node.js
- Deep dive Assessment API của reCAPTCHA Enterprise
Bước tiếp theo với CaptchaAI
Đã hiểu rõ luồng gt/challenge/seccode — lấy API key CaptchaAI và đưa bộ ba giá trị này vào pipeline automation của bạn.