GeeTest(极验)在国内登录、报名、下单页面几乎无处不在,但 GeeTest v3 不是 reCAPTCHA 那种单 token 模式——它靠注册、渲染、三值校验三步走,抓错阶段就拿不到正确参数。下文按顺序拆解全流程,并给出提取 gt、challenge 的三种方法。
GeeTest v3 的核心机制:先注册,再验证
阶段一:服务端注册,拿到 gt 和 challenge
页面加载时,站点后端先向 GeeTest 服务器发起注册请求:
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
阶段二:客户端渲染,提交三值校验
浏览器渲染挑战,用户完成后,后端拿三个值去 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 服务器不可达时的降级校验
生产环境偶尔会遇到 GeeTest 服务器不可达,这时 v3 会自动降级:
- 在线模式(
success为1):走 GeeTest 服务器完整校验,绝大多数生产站点的实际状态。 - 离线模式(
success为0):本地生成挑战,校验更简单,强度更低。
抓包时若看到 success 是 0,大概率是 GeeTest 服务端的问题,不必排查自己代码。
完整调用流程:从注册接口到三值校验
第一步:调用注册接口
站点后端请求 GeeTest 的注册端点,直接拿到三个字段:
GET https://api.geetest.com/register.php?gt=GT_ID&json_format=1
{
"success": 1,
"gt": "81dc9bdb52d04dc20036dbd8313ed055",
"challenge": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
"new_captcha": true
}
gt:标识站点绑定的 GeeTest 账户。challenge:本次会话专属的挑战令牌。new_captcha:是否启用新版验证码格式。
每次页面加载都会生成新的
challenge,不要缓存复用上一次的值。
第二步:渲染验证挑战
浏览器拿到 gt 和 challenge 后初始化 GeeTest 小部件:
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
});
});
第三步:常见的挑战类型
GeeTest v3 按站点配置和用户风险画像,动态选择以下挑战形式:
- 滑块:拖动拼图块,补全图像。
- 图标点击:按提示顺序点击指定图标。
- 文字点击:按顺序点击图中的汉字。
- 空间推理:点击/选择,空间判断类挑战。
具体出哪种由 GeeTest 后台决定,前端无法指定。
第四步:拿到三个校验值
用户完成操作后,小部件会生成三个值:
{
"geetest_challenge": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6xy",
"geetest_validate": "abc123def456_validate",
"geetest_seccode": "abc123def456_validate|jordan"
}
geetest_challenge:challenge 加 2 个字符后的新令牌。geetest_validate:校验哈希。geetest_seccode:安全码,即 validate 加\|jordan后缀。
第五步:服务端二次校验
站点后端把三个值发给 GeeTest 做最终确认,拿到最终结果:
POST https://api.geetest.com/validate.php
seccode=abc123def456_validate|jordan
&challenge=a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6xy
&sdk=geetest-python-3.0.0
{
"seccode": "abc123def456_validate",
"validate": "abc123def456_validate"
}
怎么把 gt 和 challenge 交给 CaptchaAI
GeeTest v3 只需要 gt 和 challenge 两个值即可求解,抓取方式有三种:
方法一:拦截注册请求的响应
直接监听浏览器发出的注册请求,读取 GeeTest 服务器返回的原始数据:
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')}")
方法二:直接读取页面 DOM 属性
如果参数写进了 data 属性,可直接用选择器取值:
gt = page.evaluate("() => document.querySelector('[data-gt]')?.dataset.gt")
challenge = page.evaluate("() => document.querySelector('[data-challenge]')?.dataset.challenge")
方法三:正则匹配 initGeetest 调用
部分站点把参数硬编码在内联脚本里,搜索源码里的 initGeetest 调用即可:
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)
提交给 CaptchaAI,拿回三值结果
参数到手后提交给 CaptchaAI 的识别接口,拿到任务 ID 后轮询结果即可:
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
GET https://ocr.captchaai.com/res.php?key=YOUR_API_KEY&action=get&id=TASK_ID&json=1
{
"status": 1,
"request": {
"geetest_challenge": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6xy",
"geetest_validate": "abc123def456_validate",
"geetest_seccode": "abc123def456_validate|jordan"
}
}
按第五步格式提交给站点后端即可。
故障排查:这几类问题最常见
challenge值为空——注册请求失败,检查页面是否正常加载 GeeTest 小部件。- 提交后被拒绝——
challenge已过期,重新抓取新的challenge并立刻提交。 gt值不对——页面上有多个 GeeTest 实例,确认取自目标那个小部件的gt。- 三个值都拿到了但表单没提交出去——表单字段没对上,把三个值注入对应的输入框。
常见问题
GeeTest v3 和极验 v4 是一回事吗?CaptchaAI 支持 v4 吗?
不是,两者协议和参数格式不同。CaptchaAI 只支持 GeeTest v3,v4 即将支持,暂不能识别。
为什么每次请求都要同时带 gt 和 challenge,只传一个不行吗?
gt 是站点账号标识,长期不变;challenge 是防重放的会话一次性令牌,缺一个都无法完成校验。
GeeTest 弹出的是滑块还是点击图标,能提前判断吗?
不能。挑战类型由 GeeTest 按站点配置和用户风险画像动态决定,前端只能拿到渲染好的结果,抓取逻辑需覆盖多种类型。
challenge 提交失败或过期了,能直接重试同一个值吗?
不能。challenge 通常 1-2 分钟内过期且只能校验一次,需重新调用注册接口拿新值。
相关文章
- Node.js 识别 GeeTest v3
- Node.js + CaptchaAI 识别 GeeTest v3
- reCAPTCHA Enterprise Assessment API 深度解析
下一步
把 GeeTest v3 挑战接入你的识别流程:获取 CaptchaAI API Key,对接三值响应即可。