极验对接示例支持直接在线查看、复制和下载源码,无需再下载压缩包。
对接示例
按语言环境展开查看代码,支持直接复制和下载源码。
Python
Python
该语言注意事项
跟随当前语言展示- =============================================================== 极验识别 对接示例 - Python版 使用说明 =============================================================== 【环境准备】 1. 安装 Python 3.6 或更高版本 下载地址:https://www.python.org/downloads/ 安装时请勾选 "Add Python to PATH" 验证安装:python --version 2. 安装依赖库 打开命令行,执行:pip install requests 如果网络慢可使用国内镜像:pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple 【文件说明】 - query_points.py 查询账户剩余点数(余额) - recognize_geetest.py 极验验证码识别(支持三代/四代,异步轮询) 【参数配置】 1. APPKEY - 用户密钥,登录平台后在个人中心获取 2. GT - 极验gt值(三代为gt值,四代为captcha_id值),从目标网站抓包获取 3. CHALLENGE - 三代必填(每次只能用一次),四代留空 4. ITEM_ID - 项目类型编号,请参照项目价格表选择对应的值 5. REFERER - 验证码所在页面URL,部分网站需要填写 6. PROXY - 代理IP(可选) 7. DEVKEY - 开发者密钥(可选) 【运行方式】 1. 查询点数:python query_points.py 2. 极验识别:python recognize_geetest.py 【极验识别流程说明】 极验识别为异步流程,分两步: 步骤1:提交识别任务 → 返回 resultid 步骤2:使用 resultid 轮询查询结果 → 返回识别数据 脚本已自动实现轮询逻辑,默认每2秒查询一次,最多等待60秒。 【三代与四代的区别】 - 三代:需要传 gt 和 challenge 参数,返回 validate/seccode - 四代:只需传 gt(即captcha_id),无需 challenge,返回 captchaOutput/lotNumber/passToken/genTime 【常见问题】 1. "ModuleNotFoundError: No module named 'requests'" → 执行 pip install requests 2. 提交后返回 "识别类型错误"(status: 4012) → 检查 ITEM_ID 是否与你的极验类型匹配,请参照项目价格表 3. 轮询超时(60秒内无结果) → 可能是网络延迟或服务繁忙,请稍后重试 4. 三代 challenge 无效或已被使用 → challenge 每次只能使用一次,请直接抓包获取新的challenge 【重要注意事项】 - 查询结果接口每秒不得超过1次,否则会被拉黑IP 10分钟 - 查询点数接口每秒不得超过1次,否则会被拉黑24小时 - APPKEY 属于敏感信息,请勿泄露 - 四代如遇无法通过,可能是编码问题,captchaOutput中的'='符号需用%3D替换
查询点数
query_points.py
# -*- coding: utf-8 -*-
"""
=============================================================
查询账户点数 Demo (Python版)
功能说明:
查询账户剩余点数(余额)
使用方法:
1. 安装依赖:pip install requests
2. 将下方的 APPKEY 替换为你自己的用户密钥
3. 运行脚本:python query_points.py
=============================================================
"""
import requests
import json
import sys
# ======================== 配置区域(请替换为你自己的参数)========================
# 用户密钥,登录平台后获取
APPKEY = "你的appkey"
# ===============================================================================
# API基础地址
API_BASE = "http://api.ttocr.com/api"
def query_points():
"""
查询账户剩余点数
接口地址:GET http://api.ttocr.com/api/points
注意:查询点数不得超过1秒1次,否则会被拉黑24小时
"""
print("=" * 50)
print("[查询点数] 正在查询账户剩余点数...")
print("=" * 50)
url = f"{API_BASE}/points"
params = {"appkey": APPKEY}
try:
response = requests.get(url, params=params, timeout=10)
result = response.json()
if result.get("status") == 1:
print(f"[成功] 查询成功!当前可用点数:{result.get('points')}")
else:
print(f"[失败] 查询失败,错误信息:{result.get('msg')}")
print(f"[提示] 错误状态码:{result.get('status')},请参考错误代码表排查")
print(f"[完整响应] {json.dumps(result, ensure_ascii=False, indent=2)}")
return result
except requests.exceptions.RequestException as e:
print(f"[异常] 网络请求出错:{e}")
return None
if __name__ == "__main__":
print("*" * 60)
print(" 查询账户点数 Demo (Python版)")
print("*" * 60)
if APPKEY == "你的appkey":
print("\n[错误] 请先在脚本顶部的配置区域填写你的 APPKEY")
sys.exit(1)
query_points()
print("\n" + "=" * 50)
print("[完成] 查询执行完毕")
print("=" * 50)
提交识别
recognize_geetest.py
# -*- coding: utf-8 -*-
"""
=============================================================
极验识别 Demo (Python版)
功能说明:
提交极验验证码识别任务(支持三代/四代)
极验识别为异步流程:先提交任务获取resultid,再轮询查询结果
使用方法:
1. 安装依赖:pip install requests
2. 将下方的配置参数替换为你自己的值
3. 运行脚本:python recognize_geetest.py
=============================================================
"""
import requests
import json
import sys
import time
# ======================== 配置区域(请替换为你自己的参数)========================
# 用户密钥,登录平台后获取
APPKEY = "你的appkey"
# 极验gt值(三代为gt值,四代为captcha_id值)
GT = "你获取到的gt值"
# challenge值(三代必填,每次只能使用一次;四代无需传此参数,留空即可)
CHALLENGE = ""
# 项目类型(请参照项目价格表,不同类型对应不同的itemid)
ITEM_ID = 0
# 验证码所在的页面URL(可选,部分网站需要填写)
REFERER = ""
# 可选参数:代理IP(格式示例:http://IP:端口,若需白名单支持请联系客服。http://账号:密码@proxy.com:8080 或 socks5://127.0.0.1:9888)
PROXY = ""
# 可选参数:开发者密钥(如果有的话填写)
DEVKEY = ""
# 可选参数:SDK版本(特殊版本为2,默认为1)
SDK = ""
# 可选参数:对接模式(按次计费:0,包月计费:1,默认为0。包月用户必填)
GIVEN = ""
# 可选参数:特殊网站极验域名(如api-na.geetest.com,不要带http://和/,只需域名)
HOST = ""
# 可选参数:User-Agent(适用于某些检验UA的网站,只支持传入安卓ua)
USER_AGENT = ""
# ===============================================================================
# API基础地址
API_BASE = "http://api.ttocr.com/api"
# 轮询配置
POLL_INTERVAL = 2 # 轮询间隔(秒),不得低于1秒
MAX_POLL_TIME = 60 # 最大等待时间(秒)
def submit_task():
"""
步骤1:提交极验识别任务
接口地址:POST http://api.ttocr.com/api/recognize
返回resultid用于后续查询结果
"""
print("=" * 50)
print("[提交任务] 正在提交极验识别任务...")
print("=" * 50)
url = f"{API_BASE}/recognize"
post_data = {
"appkey": APPKEY,
"gt": GT,
"itemid": ITEM_ID,
}
# 三代需要传challenge,四代不需要
if CHALLENGE:
post_data["challenge"] = CHALLENGE
# 验证码所在页面URL,部分网站需要填写
if REFERER:
post_data["referer"] = REFERER
if PROXY:
post_data["proxy"] = PROXY
if DEVKEY:
post_data["devkey"] = DEVKEY
if SDK:
post_data["sdk"] = SDK
if GIVEN:
post_data["given"] = GIVEN
if HOST:
post_data["host"] = HOST
if USER_AGENT:
post_data["userAgent"] = USER_AGENT
print(f"[请求参数] gt={GT[:20]}..." if len(GT) > 20 else f"[请求参数] gt={GT}")
print(f"[请求参数] itemid={ITEM_ID}")
print(f"[请求参数] referer={REFERER}")
try:
response = requests.post(url, data=post_data, timeout=30)
result = response.json()
print(f"[提交响应] {json.dumps(result, ensure_ascii=False, indent=2)}")
if result.get("status") == 1:
resultid = result.get("resultid")
print(f"[成功] 任务提交成功!resultid={resultid}")
return resultid
else:
print(f"[失败] 任务提交失败,错误信息:{result.get('msg')}")
return None
except requests.exceptions.RequestException as e:
print(f"[异常] 网络请求出错:{e}")
return None
def query_result(resultid):
"""
步骤2:轮询查询识别结果
接口地址:POST http://api.ttocr.com/api/results
注意:查询间隔不低于1秒,否则会被拉黑IP 10分钟
"""
print("\n" + "=" * 50)
print("[查询结果] 正在轮询识别结果...")
print(f"[查询结果] 轮询间隔:{POLL_INTERVAL}秒,最大等待:{MAX_POLL_TIME}秒")
print("=" * 50)
url = f"{API_BASE}/results"
start_time = time.time()
while True:
elapsed = time.time() - start_time
if elapsed > MAX_POLL_TIME:
print(f"[超时] 已等待{MAX_POLL_TIME}秒,识别超时,请稍后重试")
return None
try:
post_data = {"appkey": APPKEY, "resultid": resultid}
response = requests.post(url, data=post_data, timeout=30)
result = response.json()
if result.get("status") == 1:
print(f"\n[成功] 识别成功!耗时:{result.get('time')}ms")
print(f"[识别结果] {json.dumps(result.get('data'), ensure_ascii=False, indent=2)}")
print(f"\n[完整响应] {json.dumps(result, ensure_ascii=False, indent=2)}")
return result
else:
msg = result.get("msg", "")
print(f"[等待中] 第{int(elapsed)}秒 - {msg}")
except requests.exceptions.RequestException as e:
print(f"[异常] 查询请求出错:{e}")
time.sleep(POLL_INTERVAL)
if __name__ == "__main__":
print("*" * 60)
print(" 极验识别 Demo (Python版)")
print("*" * 60)
if APPKEY == "你的appkey":
print("\n[错误] 请先在脚本顶部的配置区域填写你的 APPKEY")
sys.exit(1)
if GT == "你获取到的gt值":
print("\n[错误] 请先在脚本顶部的配置区域填写 GT 值")
sys.exit(1)
if ITEM_ID == 0:
print("\n[错误] 请先在脚本顶部的配置区域填写 ITEM_ID(项目类型)")
sys.exit(1)
# 步骤1:提交任务
resultid = submit_task()
if resultid:
# 步骤2:轮询查询结果
query_result(resultid)
print("\n" + "=" * 50)
print("[完成] 识别执行完毕")
print("=" * 50)
Go
Go
该语言注意事项
跟随当前语言展示- ============================================================== 极验识别 对接示例 — Go版 使用说明 ============================================================== 【一、环境准备】 1. 安装 Go - 下载地址:https://go.dev/dl/ - 建议版本:Go 1.18 或以上 - 安装完成后执行: go version 2. 无需安装第三方依赖 - 本 Demo 仅使用 Go 标准库 - 直接执行 go run 即可 -------------------------------------------------------------- 【二、参数配置】 本 Demo 包含两个独立脚本: - query_points.go — 查询账户剩余点数 - recognize_geetest.go — 极验验证码识别(异步轮询) 需要重点填写: 1. APPKEY - 登录平台后在个人中心获取 2. GT - 三代为 gt,四代为 captcha_id 3. CHALLENGE - 三代必填,且每次只能使用一次 - 四代无需传,保持为空即可 4. ITEMID - 请参照项目价格表填写对应类型 5. REFERER / PROXY / DEVKEY / SDK / GIVEN / HOST / USERAGENT - 均为按需填写的可选参数 -------------------------------------------------------------- 【三、运行方式】 1. 进入当前目录: cd 极验/go 2. 查询点数: go run query_points.go 3. 极验识别: go run recognize_geetest.go -------------------------------------------------------------- 【四、极验识别流程说明】 1. 先调用 /recognize 提交任务,获取 resultid 2. 再调用 /results 按间隔轮询查询结果 3. Demo 默认每 2 秒查询一次,最大等待 60 秒 -------------------------------------------------------------- 【五、重要注意事项】 1. 查询结果接口每秒不得超过 1 次,否则会被拉黑 IP 10 分钟 2. 查询点数接口每秒不得超过 1 次,否则会被拉黑 24 小时 3. 四代如遇结果无法通过,可能需要对 captchaOutput 中的 "=" 做编码处理 4. 不要将 APPKEY 泄露给他人 ==============================================================
查询点数
query_points.go
package main
import (
"encoding/json"
"fmt"
"net/http"
"net/url"
"os"
"time"
)
/*
=============================================================
查询账户点数 Demo (Go版)
功能说明:
查询账户剩余点数(余额)
使用方法:
1. 确保已安装 Go 1.18 或更高版本
2. 将下方的 APPKEY 替换为你自己的用户密钥
3. 运行脚本:go run query_points.go
4. 本 Demo 仅使用 Go 标准库,无需安装第三方依赖
=============================================================
*/
const (
APPKEY = "你的appkey"
APIBase = "http://api.ttocr.com/api"
)
func queryPoints() (map[string]interface{}, error) {
client := &http.Client{Timeout: 10 * time.Second}
endpoint := APIBase + "/points?appkey=" + url.QueryEscape(APPKEY)
resp, err := client.Get(endpoint)
if err != nil {
return nil, err
}
defer resp.Body.Close()
var result map[string]interface{}
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
return nil, err
}
pretty, _ := json.MarshalIndent(result, "", " ")
if status, ok := result["status"].(float64); ok && status == 1 {
fmt.Printf("[成功] 查询成功!当前可用点数:%v\n", result["points"])
} else {
fmt.Printf("[失败] 查询失败,错误信息:%v\n", result["msg"])
fmt.Printf("[提示] 错误状态码:%v,请参考错误代码表排查\n", result["status"])
}
fmt.Printf("[完整响应] %s\n", string(pretty))
return result, nil
}
func main() {
fmt.Println("************************************************************")
fmt.Println(" 查询账户点数 Demo (Go版)")
fmt.Println("************************************************************")
if APPKEY == "你的appkey" {
fmt.Println("\n[错误] 请先在代码顶部的配置区域填写你的 APPKEY")
os.Exit(1)
}
fmt.Println("==================================================")
fmt.Println("[查询点数] 正在查询账户剩余点数...")
fmt.Println("==================================================")
if _, err := queryPoints(); err != nil {
fmt.Printf("[异常] 网络请求出错:%v\n", err)
os.Exit(1)
}
fmt.Println("\n==================================================")
fmt.Println("[完成] 查询执行完毕")
fmt.Println("==================================================")
}
提交识别
recognize_geetest.go
package main
import (
"encoding/json"
"fmt"
"net/http"
"net/url"
"os"
"time"
)
/*
=============================================================
极验识别 Demo (Go版)
功能说明:
提交极验验证码识别任务(支持三代/四代)
极验识别为异步流程:先提交任务获取 resultid,再轮询查询结果
使用方法:
1. 确保已安装 Go 1.18 或更高版本
2. 将下方的配置参数替换为你自己的值
3. 运行脚本:go run recognize_geetest.go
=============================================================
*/
const (
APPKEY = "你的appkey"
GT = "你获取到的gt值"
CHALLENGE = ""
ITEMID = "0"
REFERER = ""
PROXY = ""
DEVKEY = ""
SDK = ""
GIVEN = ""
HOST = ""
USERAGENT = ""
APIBase = "http://api.ttocr.com/api"
PollInterval = 2 * time.Second
MaxPollTime = 60 * time.Second
)
func postForm(endpoint string, values url.Values, timeout time.Duration) (map[string]interface{}, error) {
client := &http.Client{Timeout: timeout}
resp, err := client.PostForm(endpoint, values)
if err != nil {
return nil, err
}
defer resp.Body.Close()
var result map[string]interface{}
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
return nil, err
}
return result, nil
}
func submitTask() (string, error) {
fmt.Println("==================================================")
fmt.Println("[提交任务] 正在提交极验识别任务...")
fmt.Println("==================================================")
values := url.Values{}
values.Set("appkey", APPKEY)
values.Set("gt", GT)
values.Set("itemid", ITEMID)
if CHALLENGE != "" {
values.Set("challenge", CHALLENGE)
}
if REFERER != "" {
values.Set("referer", REFERER)
}
if PROXY != "" {
values.Set("proxy", PROXY)
}
if DEVKEY != "" {
values.Set("devkey", DEVKEY)
}
if SDK != "" {
values.Set("sdk", SDK)
}
if GIVEN != "" {
values.Set("given", GIVEN)
}
if HOST != "" {
values.Set("host", HOST)
}
if USERAGENT != "" {
values.Set("userAgent", USERAGENT)
}
fmt.Printf("[请求参数] gt=%s\n", GT)
fmt.Printf("[请求参数] itemid=%s\n", ITEMID)
result, err := postForm(APIBase+"/recognize", values, 30*time.Second)
if err != nil {
return "", err
}
pretty, _ := json.MarshalIndent(result, "", " ")
fmt.Printf("[提交响应] %s\n", string(pretty))
if status, ok := result["status"].(float64); ok && status == 1 {
resultID, _ := result["resultid"].(string)
fmt.Printf("[成功] 任务提交成功!resultid=%s\n", resultID)
return resultID, nil
}
return "", fmt.Errorf("任务提交失败:%v", result["msg"])
}
func queryResult(resultID string) error {
fmt.Println("\n==================================================")
fmt.Println("[查询结果] 正在轮询识别结果...")
fmt.Printf("[查询结果] 轮询间隔:%d秒,最大等待:%d秒\n", int(PollInterval.Seconds()), int(MaxPollTime.Seconds()))
fmt.Println("==================================================")
startedAt := time.Now()
for {
if time.Since(startedAt) > MaxPollTime {
return fmt.Errorf("已等待%d秒,识别超时,请稍后重试", int(MaxPollTime.Seconds()))
}
time.Sleep(PollInterval)
values := url.Values{}
values.Set("appkey", APPKEY)
values.Set("resultid", resultID)
result, err := postForm(APIBase+"/results", values, 30*time.Second)
if err != nil {
fmt.Printf("[异常] 查询请求出错:%v\n", err)
continue
}
if status, ok := result["status"].(float64); ok && status == 1 {
pretty, _ := json.MarshalIndent(result, "", " ")
fmt.Printf("\n[成功] 识别成功!耗时:%vms\n", result["time"])
fmt.Printf("[识别结果] %v\n", result["data"])
fmt.Printf("\n[完整响应] %s\n", string(pretty))
return nil
}
fmt.Printf("[等待中] 第%d秒 - %v\n", int(time.Since(startedAt).Seconds()), result["msg"])
}
}
func main() {
fmt.Println("************************************************************")
fmt.Println(" 极验识别 Demo (Go版)")
fmt.Println("************************************************************")
if APPKEY == "你的appkey" {
fmt.Println("\n[错误] 请先在代码顶部的配置区域填写你的 APPKEY")
os.Exit(1)
}
if GT == "你获取到的gt值" {
fmt.Println("\n[错误] 请先在代码顶部的配置区域填写 GT 值")
os.Exit(1)
}
if ITEMID == "0" {
fmt.Println("\n[错误] 请先在代码顶部的配置区域填写 ITEMID(项目类型)")
os.Exit(1)
}
resultID, err := submitTask()
if err != nil {
fmt.Printf("[失败] %v\n", err)
os.Exit(1)
}
if err := queryResult(resultID); err != nil {
fmt.Printf("[失败] %v\n", err)
os.Exit(1)
}
fmt.Println("\n==================================================")
fmt.Println("[完成] 识别执行完毕")
fmt.Println("==================================================")
}
易语言
易语言
该语言注意事项
跟随当前语言展示- ============================================================== 极验识别 对接示例 — 易语言版 使用说明 ============================================================== 【一、依赖说明】 1. 需要导入:精易模块 2. 本示例实际用到的命令 / 类: - 网页_访问_对象 - 类_POST数据类 - 类_json - 编码_URL编码 - 编码_Utf8到Ansi - 延时 3. 这次没有再额外依赖 `spec` -------------------------------------------------------------- 【二、这次写法的重点】 1. `功能_提交极验 / 功能_查询结果` 是示例子程序,不是系统命令 2. 写法参考了精易论坛里常见的网页访问生成格式 3. 示例已经把“提交任务 + 轮询结果”两步都写好了 -------------------------------------------------------------- 【三、参数说明】 1. `GT` - 三代填 `gt` - 四代填 `captcha_id` 2. `CHALLENGE` - 三代需要 - 四代留空即可 3. `ITEMID` - 按你的项目类型填写 4. `REFERER / PROXY / DEVKEY / SDK / GIVEN / HOST / USERAGENT` - 都是按需填写的可选参数 -------------------------------------------------------------- 【四、输出结果怎么看】 1. 示例默认用 `输出调试文本` 看每一步接口返回 2. 适合直接在 IDE 里调试 3. 如果要接到你自己的窗口程序: - 可把返回值写到编辑框 - 或者自己封装成按钮点击事件 -------------------------------------------------------------- 【五、调用注意事项】 1. 极验是异步流程: - 先调 `/api/recognize` - 再调 `/api/results` 2. 查询结果频率不能高于每秒 1 次 3. 示例里默认每 2 秒查一次,共查 30 次 4. 三代 `challenge` 是一次性的,必须实时抓取 5. 四代如果结果提交后无法通过,通常还需要继续检查目标站对结果字段的编码要求 ==============================================================
查询点数
QueryPoints.e
.版本 2
.子程序 _启动子程序, 整数型, , 本子程序在程序启动后最先执行
.局部变量 APPKEY, 文本型
.局部变量 返回文本, 文本型
.局部变量 json, 类_json
APPKEY = "你的appkey"
.如果真 (APPKEY = "你的appkey")
输出调试文本 ("[错误] 请先把 APPKEY 改成你自己的密钥")
返回 (0)
.如果真结束
返回文本 = 功能_查询点数 (APPKEY)
输出调试文本 ("[完整响应]" + #换行符 + 返回文本)
.如果真 (json.解析 (返回文本, , ))
.如果真 (json.取通用属性 ("status", ) = "1")
输出调试文本 ("[成功] 当前可用点数:" + 到文本 (json.取通用属性 ("points", )))
.否则
输出调试文本 ("[失败] " + 到文本 (json.取通用属性 ("msg", )))
.如果真结束
.否则
输出调试文本 ("[失败] JSON 解析失败,请检查返回内容")
.如果真结束
返回 (0)
.子程序 功能_查询点数, 文本型, , 本命令由〖精易网页调试助手〗生成,请配合精易模块使用。
.参数 APPKEY, 文本型
.局部变量 局_网址, 文本型
.局部变量 局_方式, 整数型
.局部变量 ADD_协议头, 类_POST数据类
.局部变量 局_提交协议头, 文本型
.局部变量 局_结果, 字节集
.局部变量 局_返回, 文本型
局_网址 = "http://api.ttocr.com/api/points?appkey=" + 编码_URL编码 (APPKEY, 真, 真)
局_方式 = 0
ADD_协议头.添加 ("Accept", "application/json", )
ADD_协议头.添加 ("User-Agent", "Mozilla/5.0", )
局_提交协议头 = ADD_协议头.获取协议头数据 ()
局_结果 = 网页_访问_对象 (局_网址, 局_方式, , , , 局_提交协议头, , , , , , , , , , , )
局_返回 = 到文本 (编码_Utf8到Ansi (局_结果))
返回 (局_返回)
提交识别
RecognizeGeetest.e
.版本 2
.子程序 _启动子程序, 整数型, , 本子程序在程序启动后最先执行
.局部变量 APPKEY, 文本型
.局部变量 GT, 文本型
.局部变量 CHALLENGE, 文本型
.局部变量 ITEMID, 文本型
.局部变量 REFERER, 文本型
.局部变量 PROXY, 文本型
.局部变量 DEVKEY, 文本型
.局部变量 SDK, 文本型
.局部变量 GIVEN, 文本型
.局部变量 HOST, 文本型
.局部变量 USERAGENT, 文本型
.局部变量 提交返回, 文本型
.局部变量 查询返回, 文本型
.局部变量 提交json, 类_json
.局部变量 查询json, 类_json
.局部变量 RESULTID, 文本型
.局部变量 循环次数, 整数型
APPKEY = "你的appkey"
GT = "你获取到的gt值"
CHALLENGE = ""
ITEMID = "0"
REFERER = ""
PROXY = ""
DEVKEY = ""
SDK = ""
GIVEN = ""
HOST = ""
USERAGENT = ""
.如果真 (APPKEY = "你的appkey")
输出调试文本 ("[错误] 请先把 APPKEY 改成你自己的密钥")
返回 (0)
.如果真结束
.如果真 (GT = "你获取到的gt值")
输出调试文本 ("[错误] 请先填写 GT;如果是四代,这里填写 captcha_id")
返回 (0)
.如果真结束
.如果真 (ITEMID = "0")
输出调试文本 ("[错误] 请先填写 ITEMID")
返回 (0)
.如果真结束
提交返回 = 功能_提交极验 (APPKEY, GT, CHALLENGE, ITEMID, REFERER, PROXY, DEVKEY, SDK, GIVEN, HOST, USERAGENT)
输出调试文本 ("[提交响应]" + #换行符 + 提交返回)
.如果真 (提交json.解析 (提交返回, , ))
.如果真 (提交json.取通用属性 ("status", ) = "1")
RESULTID = 到文本 (提交json.取通用属性 ("resultid", ))
输出调试文本 ("[成功] resultid = " + RESULTID)
.否则
输出调试文本 ("[失败] " + 到文本 (提交json.取通用属性 ("msg", )))
返回 (0)
.如果真结束
.否则
输出调试文本 ("[失败] 提交响应 JSON 解析失败")
返回 (0)
.如果真结束
.计次循环首 (30, 循环次数)
延时 (2000)
查询返回 = 功能_查询结果 (APPKEY, RESULTID)
输出调试文本 ("[第" + 到文本 (循环次数) + "次查询]" + #换行符 + 查询返回)
.如果真 (查询json.解析 (查询返回, , ))
.如果真 (查询json.取通用属性 ("status", ) = "1")
输出调试文本 ("[成功] 耗时:" + 到文本 (查询json.取通用属性 ("time", )) + "ms")
输出调试文本 ("[识别结果] " + 到文本 (查询json.取通用属性 ("data", )))
返回 (0)
.否则
输出调试文本 ("[等待中] " + 到文本 (查询json.取通用属性 ("msg", )))
.如果真结束
.否则
输出调试文本 ("[失败] 查询响应 JSON 解析失败")
.如果真结束
.计次循环尾 ()
输出调试文本 ("[超时] 已轮询 30 次,仍未拿到成功结果")
返回 (0)
.子程序 功能_提交极验, 文本型, , 本命令由〖精易网页调试助手〗生成,请配合精易模块使用。
.参数 APPKEY, 文本型
.参数 GT, 文本型
.参数 CHALLENGE, 文本型
.参数 ITEMID, 文本型
.参数 REFERER, 文本型
.参数 PROXY, 文本型
.参数 DEVKEY, 文本型
.参数 SDK, 文本型
.参数 GIVEN, 文本型
.参数 HOST, 文本型
.参数 USERAGENT, 文本型
.局部变量 局_网址, 文本型
.局部变量 局_方式, 整数型
.局部变量 局_提交数据, 文本型
.局部变量 ADD_协议头, 类_POST数据类
.局部变量 局_提交协议头, 文本型
.局部变量 局_结果, 字节集
.局部变量 局_返回, 文本型
局_网址 = "http://api.ttocr.com/api/recognize"
局_方式 = 1
局_提交数据 = "appkey=" + 编码_URL编码 (APPKEY, 真, 真)
局_提交数据 = 局_提交数据 + ">=" + 编码_URL编码 (GT, 真, 真)
局_提交数据 = 局_提交数据 + "&itemid=" + 编码_URL编码 (ITEMID, 真, 真)
.如果真 (CHALLENGE = "")
.否则
局_提交数据 = 局_提交数据 + "&challenge=" + 编码_URL编码 (CHALLENGE, 真, 真)
.如果真结束
.如果真 (REFERER = "")
.否则
局_提交数据 = 局_提交数据 + "&referer=" + 编码_URL编码 (REFERER, 真, 真)
.如果真结束
.如果真 (PROXY = "")
.否则
局_提交数据 = 局_提交数据 + "&proxy=" + 编码_URL编码 (PROXY, 真, 真)
.如果真结束
.如果真 (DEVKEY = "")
.否则
局_提交数据 = 局_提交数据 + "&devkey=" + 编码_URL编码 (DEVKEY, 真, 真)
.如果真结束
.如果真 (SDK = "")
.否则
局_提交数据 = 局_提交数据 + "&sdk=" + 编码_URL编码 (SDK, 真, 真)
.如果真结束
.如果真 (GIVEN = "")
.否则
局_提交数据 = 局_提交数据 + "&given=" + 编码_URL编码 (GIVEN, 真, 真)
.如果真结束
.如果真 (HOST = "")
.否则
局_提交数据 = 局_提交数据 + "&host=" + 编码_URL编码 (HOST, 真, 真)
.如果真结束
.如果真 (USERAGENT = "")
.否则
局_提交数据 = 局_提交数据 + "&userAgent=" + 编码_URL编码 (USERAGENT, 真, 真)
.如果真结束
ADD_协议头.添加 ("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8", )
ADD_协议头.添加 ("Accept", "application/json", )
ADD_协议头.添加 ("User-Agent", "Mozilla/5.0", )
局_提交协议头 = ADD_协议头.获取协议头数据 ()
局_结果 = 网页_访问_对象 (局_网址, 局_方式, 局_提交数据, , , 局_提交协议头, , , , , , , , , , , )
局_返回 = 到文本 (编码_Utf8到Ansi (局_结果))
返回 (局_返回)
.子程序 功能_查询结果, 文本型, , 本命令由〖精易网页调试助手〗生成,请配合精易模块使用。
.参数 APPKEY, 文本型
.参数 RESULTID, 文本型
.局部变量 局_网址, 文本型
.局部变量 局_方式, 整数型
.局部变量 局_提交数据, 文本型
.局部变量 ADD_协议头, 类_POST数据类
.局部变量 局_提交协议头, 文本型
.局部变量 局_结果, 字节集
.局部变量 局_返回, 文本型
局_网址 = "http://api.ttocr.com/api/results"
局_方式 = 1
局_提交数据 = "appkey=" + 编码_URL编码 (APPKEY, 真, 真)
局_提交数据 = 局_提交数据 + "&resultid=" + 编码_URL编码 (RESULTID, 真, 真)
ADD_协议头.添加 ("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8", )
ADD_协议头.添加 ("Accept", "application/json", )
ADD_协议头.添加 ("User-Agent", "Mozilla/5.0", )
局_提交协议头 = ADD_协议头.获取协议头数据 ()
局_结果 = 网页_访问_对象 (局_网址, 局_方式, 局_提交数据, , , 局_提交协议头, , , , , , , , , , , )
局_返回 = 到文本 (编码_Utf8到Ansi (局_结果))
返回 (局_返回)
Node.js
Node.js
该语言注意事项
跟随当前语言展示- =============================================================== 极验识别 对接示例 - Node.js版 使用说明 =============================================================== 【环境准备】 1. 安装 Node.js v12 或更高版本 下载地址:https://nodejs.org/ 建议选择 LTS(长期支持)版本 验证安装:node --version 2. 本Demo使用Node.js内置模块(http、querystring),无需安装第三方依赖 【文件说明】 - query_points.js 查询账户剩余点数(余额) - recognize_geetest.js 极验验证码识别(支持三代/四代,异步轮询) 【参数配置】 1. APPKEY - 用户密钥,登录平台后在个人中心获取 2. GT - 极验gt值(三代为gt值,四代为captcha_id值),从目标网站抓包获取 3. CHALLENGE - 三代必填(每次只能用一次),四代留空 4. ITEM_ID - 项目类型编号,请参照项目价格表选择对应的值 5. REFERER - 验证码所在页面URL,部分网站需要填写 6. PROXY - 代理IP(可选) 7. DEVKEY - 开发者密钥(可选) 【运行方式】 1. 查询点数:node query_points.js 2. 极验识别:node recognize_geetest.js 【极验识别流程说明】 极验识别为异步流程,分两步: 步骤1:提交识别任务 → 返回 resultid 步骤2:使用 resultid 轮询查询结果 → 返回识别数据 脚本已自动实现轮询逻辑(async/await),默认每2秒查询一次,最多等待60秒。 【三代与四代的区别】 - 三代:需要传 gt 和 challenge 参数,返回 validate/seccode - 四代:只需传 gt(即captcha_id),无需 challenge,返回 captchaOutput/lotNumber/passToken/genTime 【常见问题】 1. "'node' 不是内部或外部命令" → Node.js未安装或未添加到系统PATH 2. 提交后返回 "识别类型错误" → 检查 ITEM_ID 是否与你的极验类型匹配 3. 轮询超时 → 可能是网络延迟或服务繁忙,请稍后重试 4. 三代 challenge 无效 → challenge 每次只能使用一次,请直接抓包获取 【重要注意事项】 - 查询结果接口每秒不得超过1次,否则会被拉黑IP 10分钟 - 查询点数接口每秒不得超过1次,否则会被拉黑24小时 - APPKEY 属于敏感信息,请勿泄露 - 四代如遇无法通过,captchaOutput中的'='符号需用%3D替换
查询点数
query_points.js
/**
* =============================================================
* 查询账户点数 Demo (Node.js版)
*
* 功能说明:
* 查询账户剩余点数(余额)
*
* 使用方法:
* 1. 确保已安装 Node.js (建议 v12+)
* 2. 将下方的 APPKEY 替换为你自己的用户密钥
* 3. 运行脚本:node query_points.js
* 注意:本Demo使用Node.js内置模块,无需安装第三方依赖
* =============================================================
*/
const http = require('http');
// ======================== 配置区域(请替换为你自己的参数)========================
// 用户密钥,登录平台后获取
const APPKEY = "你的appkey";
// ===============================================================================
// API基础地址
const API_BASE = "http://api.ttocr.com/api";
/**
* 发送HTTP GET请求
*/
function httpGet(url) {
return new Promise((resolve, reject) => {
http.get(url, { timeout: 10000 }, (res) => {
let body = '';
res.on('data', (chunk) => { body += chunk; });
res.on('end', () => {
try { resolve(JSON.parse(body)); }
catch (e) { reject(new Error('JSON解析失败: ' + body)); }
});
}).on('error', reject);
});
}
async function main() {
console.log("*".repeat(60));
console.log(" 查询账户点数 Demo (Node.js版)");
console.log("*".repeat(60));
if (APPKEY === "你的appkey") {
console.log("\n[错误] 请先在脚本顶部的配置区域填写你的 APPKEY");
process.exit(1);
}
console.log("=".repeat(50));
console.log("[查询点数] 正在查询账户剩余点数...");
console.log("=".repeat(50));
try {
const url = `${API_BASE}/points?appkey=${encodeURIComponent(APPKEY)}`;
const result = await httpGet(url);
if (result.status === 1) {
console.log(`[成功] 查询成功!当前可用点数:${result.points}`);
} else {
console.log(`[失败] 查询失败,错误信息:${result.msg}`);
console.log(`[提示] 错误状态码:${result.status},请参考错误代码表排查`);
}
console.log(`[完整响应] ${JSON.stringify(result, null, 2)}`);
} catch (e) {
console.log(`[异常] 网络请求出错:${e.message}`);
}
console.log("\n" + "=".repeat(50));
console.log("[完成] 查询执行完毕");
console.log("=".repeat(50));
}
main().catch(err => {
console.error("[致命错误]", err.message);
process.exit(1);
});
提交识别
recognize_geetest.js
/**
* =============================================================
* 极验识别 Demo (Node.js版)
*
* 功能说明:
* 提交极验验证码识别任务(支持三代/四代)
* 极验识别为异步流程:先提交任务获取resultid,再轮询查询结果
*
* 使用方法:
* 1. 确保已安装 Node.js (建议 v12+)
* 2. 将下方的配置参数替换为你自己的值
* 3. 运行脚本:node recognize_geetest.js
* 注意:本Demo使用Node.js内置模块,无需安装第三方依赖
* =============================================================
*/
const http = require('http');
const querystring = require('querystring');
// ======================== 配置区域(请替换为你自己的参数)========================
// 用户密钥,登录平台后获取
const APPKEY = "你的appkey";
// 极验gt值(三代为gt值,四代为captcha_id值)
const GT = "你获取到的gt值";
// challenge值(三代必填,每次只能使用一次;四代无需传此参数,留空即可)
const CHALLENGE = "";
// 项目类型(请参照项目价格表,不同类型对应不同的itemid)
const ITEM_ID = 0;
// 验证码所在的页面URL(可选,部分网站需要填写)
const REFERER = "";
// 可选参数:代理IP(格式示例:http://IP:端口,若需白名单支持请联系客服。http://账号:密码@proxy.com:8080 或 socks5://127.0.0.1:9888)
const PROXY = "";
// 可选参数:开发者密钥(如果有的话填写)
const DEVKEY = "";
// 可选参数:SDK版本(特殊版本为2,默认为1)
const SDK = "";
// 可选参数:对接模式(按次计费:0,包月计费:1,默认为0。包月用户必填)
const GIVEN = "";
// 可选参数:特殊网站极验域名(如api-na.geetest.com,不要带http://和/,只需域名)
const HOST_PARAM = "";
// 可选参数:User-Agent(适用于某些检验UA的网站,只支持传入安卓ua)
const USER_AGENT = "";
// ===============================================================================
// API基础地址
const API_BASE = "http://api.ttocr.com/api";
// 轮询配置
const POLL_INTERVAL = 2000; // 轮询间隔(毫秒),不得低于1秒
const MAX_POLL_TIME = 60000; // 最大等待时间(毫秒)
/**
* 发送HTTP POST请求(表单数据)
*/
function httpPost(url, postData) {
return new Promise((resolve, reject) => {
const data = querystring.stringify(postData);
const urlObj = new URL(url);
const options = {
hostname: urlObj.hostname,
port: urlObj.port || 80,
path: urlObj.pathname,
method: 'POST',
timeout: 30000,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(data)
}
};
const req = http.request(options, (res) => {
let body = '';
res.on('data', (chunk) => { body += chunk; });
res.on('end', () => {
try { resolve(JSON.parse(body)); }
catch (e) { reject(new Error('JSON解析失败: ' + body)); }
});
});
req.on('error', reject);
req.write(data);
req.end();
});
}
/**
* 延时函数
*/
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function main() {
console.log("*".repeat(60));
console.log(" 极验识别 Demo (Node.js版)");
console.log("*".repeat(60));
if (APPKEY === "你的appkey") {
console.log("\n[错误] 请先在脚本顶部的配置区域填写你的 APPKEY");
process.exit(1);
}
if (GT === "你获取到的gt值") {
console.log("\n[错误] 请先在脚本顶部的配置区域填写 GT 值");
process.exit(1);
}
if (ITEM_ID === 0) {
console.log("\n[错误] 请先在脚本顶部的配置区域填写 ITEM_ID(项目类型)");
process.exit(1);
}
// ========== 步骤1:提交极验识别任务 ==========
console.log("=".repeat(50));
console.log("[提交任务] 正在提交极验识别任务...");
console.log("=".repeat(50));
const postData = { appkey: APPKEY, gt: GT, itemid: ITEM_ID };
if (CHALLENGE) { postData.challenge = CHALLENGE; }
if (REFERER) { postData.referer = REFERER; }
if (PROXY) { postData.proxy = PROXY; }
if (DEVKEY) { postData.devkey = DEVKEY; }
if (SDK) { postData.sdk = SDK; }
if (GIVEN) { postData.given = GIVEN; }
if (HOST_PARAM) { postData.host = HOST_PARAM; }
if (USER_AGENT) { postData.userAgent = USER_AGENT; }
console.log(`[请求参数] gt=${GT}`);
console.log(`[请求参数] itemid=${ITEM_ID}`);
try {
const submitResult = await httpPost(`${API_BASE}/recognize`, postData);
console.log(`[提交响应] ${JSON.stringify(submitResult, null, 2)}`);
if (submitResult.status !== 1 || !submitResult.resultid) {
console.log(`[失败] 任务提交失败,错误信息:${submitResult.msg}`);
process.exit(1);
}
const resultid = submitResult.resultid;
console.log(`[成功] 任务提交成功!resultid=${resultid}`);
// ========== 步骤2:轮询查询识别结果 ==========
console.log("\n" + "=".repeat(50));
console.log("[查询结果] 正在轮询识别结果...");
console.log(`[查询结果] 轮询间隔:${POLL_INTERVAL / 1000}秒,最大等待:${MAX_POLL_TIME / 1000}秒`);
console.log("=".repeat(50));
const startTime = Date.now();
while (true) {
const elapsed = Date.now() - startTime;
if (elapsed > MAX_POLL_TIME) {
console.log(`[超时] 已等待${MAX_POLL_TIME / 1000}秒,识别超时,请稍后重试`);
break;
}
await sleep(POLL_INTERVAL);
const queryResult = await httpPost(`${API_BASE}/results`, {
appkey: APPKEY,
resultid: resultid
});
const elapsedSec = Math.floor((Date.now() - startTime) / 1000);
if (queryResult.status === 1) {
console.log(`\n[成功] 识别成功!耗时:${queryResult.time}ms`);
console.log(`[识别结果] ${JSON.stringify(queryResult.data, null, 2)}`);
console.log(`\n[完整响应] ${JSON.stringify(queryResult, null, 2)}`);
break;
} else {
console.log(`[等待中] 第${elapsedSec}秒 - ${queryResult.msg || '正在识别中...'}`);
}
}
} catch (e) {
console.log(`[异常] 网络请求出错:${e.message}`);
}
console.log("\n" + "=".repeat(50));
console.log("[完成] 识别执行完毕");
console.log("=".repeat(50));
}
main().catch(err => {
console.error("[致命错误]", err.message);
process.exit(1);
});
Java
Java
该语言注意事项
跟随当前语言展示- =============================================================== 极验识别 对接示例 - Java版 使用说明 =============================================================== 【环境准备】 1. 安装 JDK 8 或更高版本 下载地址:https://www.oracle.com/java/technologies/downloads/ 或使用 OpenJDK:https://adoptium.net/ 验证安装:java -version 和 javac -version 【文件说明】 - QueryPoints.java 查询账户剩余点数(余额) - RecognizeGeetest.java 极验验证码识别(支持三代/四代,异步轮询) 【参数配置】 1. APPKEY - 用户密钥,登录平台后在个人中心获取 2. GT - 极验gt值(三代为gt值,四代为captcha_id值),从目标网站抓包获取 3. CHALLENGE - 三代必填(每次只能用一次),四代留空 4. ITEM_ID - 项目类型编号,请参照项目价格表选择对应的值 5. REFERER - 验证码所在页面URL,部分网站需要填写 6. PROXY - 代理IP(可选) 7. DEVKEY - 开发者密钥(可选) 【编译与运行】 1. 查询点数: javac -encoding UTF-8 QueryPoints.java java QueryPoints 2. 极验识别: javac -encoding UTF-8 RecognizeGeetest.java java RecognizeGeetest 注意:编译时必须加 -encoding UTF-8 参数,否则中文可能乱码。 【极验识别流程说明】 极验识别为异步流程,分两步: 步骤1:提交识别任务 → 返回 resultid 步骤2:使用 resultid 轮询查询结果 → 返回识别数据 脚本已自动实现轮询逻辑,默认每2秒查询一次,最多等待60秒。 本Demo使用纯JDK实现,无需任何第三方依赖库。 【三代与四代的区别】 - 三代:需要传 gt 和 challenge 参数,返回 validate/seccode - 四代:只需传 gt(即captcha_id),无需 challenge,返回 captchaOutput/lotNumber/passToken/genTime 【常见问题】 1. "javac 不是内部或外部命令" → JDK未安装或未配置环境变量,请将JDK的bin目录添加到PATH 2. 编译时出现中文乱码 → 编译命令加上 -encoding UTF-8 参数 3. 提交后返回 "识别类型错误" → 检查 ITEM_ID 是否与你的极验类型匹配 4. 三代 challenge 无效 → challenge 每次只能使用一次,请直接抓包获取 【重要注意事项】 - 查询结果接口每秒不得超过1次,否则会被拉黑IP 10分钟 - 查询点数接口每秒不得超过1次,否则会被拉黑24小时 - APPKEY 属于敏感信息,请勿泄露 - 四代如遇无法通过,captchaOutput中的'='符号需用%3D替换
查询点数
QueryPoints.java
import java.io.*;
import java.net.*;
import java.nio.charset.StandardCharsets;
/**
* =============================================================
* 查询账户点数 Demo (Java版)
*
* 功能说明:
* 查询账户剩余点数(余额)
*
* 使用方法:
* 1. 将下方的 APPKEY 替换为你自己的用户密钥
* 2. 编译运行:javac -encoding UTF-8 QueryPoints.java && java QueryPoints
* =============================================================
*/
public class QueryPoints {
// ======================== 配置区域(请替换为你自己的参数)========================
// 用户密钥,登录平台后获取
private static final String APPKEY = "你的appkey";
// ===============================================================================
// API基础地址
private static final String API_BASE = "http://api.ttocr.com/api";
/**
* 发送GET请求
*/
private static String httpGet(String urlStr) throws Exception {
URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(10000);
conn.setReadTimeout(10000);
BufferedReader reader = new BufferedReader(
new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
reader.close();
conn.disconnect();
return sb.toString();
}
public static void main(String[] args) {
System.out.println("************************************************************");
System.out.println(" 查询账户点数 Demo (Java版)");
System.out.println("************************************************************");
if ("你的appkey".equals(APPKEY)) {
System.out.println("\n[错误] 请先在代码顶部的配置区域填写你的 APPKEY");
System.exit(1);
}
System.out.println("==================================================");
System.out.println("[查询点数] 正在查询账户剩余点数...");
System.out.println("==================================================");
try {
String url = API_BASE + "/points?appkey=" + URLEncoder.encode(APPKEY, "UTF-8");
String result = httpGet(url);
System.out.println("[完整响应] " + result);
} catch (Exception e) {
System.out.println("[异常] 网络请求出错:" + e.getMessage());
}
System.out.println("\n==================================================");
System.out.println("[完成] 查询执行完毕");
System.out.println("==================================================");
}
}
提交识别
RecognizeGeetest.java
import java.io.*;
import java.net.*;
import java.nio.charset.StandardCharsets;
/**
* =============================================================
* 极验识别 Demo (Java版)
*
* 功能说明:
* 提交极验验证码识别任务(支持三代/四代)
* 极验识别为异步流程:先提交任务获取resultid,再轮询查询结果
*
* 使用方法:
* 1. 将下方的配置参数替换为你自己的值
* 2. 编译运行:javac -encoding UTF-8 RecognizeGeetest.java && java RecognizeGeetest
* =============================================================
*/
public class RecognizeGeetest {
// ======================== 配置区域(请替换为你自己的参数)========================
// 用户密钥,登录平台后获取
private static final String APPKEY = "你的appkey";
// 极验gt值(三代为gt值,四代为captcha_id值)
private static final String GT = "你获取到的gt值";
// challenge值(三代必填,每次只能使用一次;四代无需传此参数,留空即可)
private static final String CHALLENGE = "";
// 项目类型(请参照项目价格表,不同类型对应不同的itemid)
private static final int ITEM_ID = 0;
// 验证码所在的页面URL(可选,部分网站需要填写)
private static final String REFERER = "";
// 可选参数:代理IP(格式示例:http://IP:端口,若需白名单支持请联系客服。http://账号:密码@proxy.com:8080 或 socks5://127.0.0.1:9888)
private static final String PROXY = "";
// 可选参数:开发者密钥(如果有的话填写)
private static final String DEVKEY = "";
// 可选参数:SDK版本(特殊版本为2,默认为1)
private static final String SDK = "";
// 可选参数:对接模式(按次计费:0,包月计费:1,默认为0。包月用户必填)
private static final String GIVEN = "";
// 可选参数:特殊网站极验域名(如api-na.geetest.com,不要带http://和/,只需域名)
private static final String HOST_PARAM = "";
// 可选参数:User-Agent(适用于某些检验UA的网站,只支持传入安卓ua)
private static final String USER_AGENT = "";
// ===============================================================================
// API基础地址
private static final String API_BASE = "http://api.ttocr.com/api";
// 轮询配置
private static final int POLL_INTERVAL = 2000; // 轮询间隔(毫秒),不得低于1秒
private static final int MAX_POLL_TIME = 60000; // 最大等待时间(毫秒)
/**
* 发送POST请求(表单数据)
*/
private static String httpPost(String urlStr, String postData) throws Exception {
URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setConnectTimeout(10000);
conn.setReadTimeout(30000);
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
OutputStream os = conn.getOutputStream();
os.write(postData.getBytes(StandardCharsets.UTF_8));
os.flush();
os.close();
BufferedReader reader = new BufferedReader(
new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
reader.close();
conn.disconnect();
return sb.toString();
}
public static void main(String[] args) {
System.out.println("************************************************************");
System.out.println(" 极验识别 Demo (Java版)");
System.out.println("************************************************************");
if ("你的appkey".equals(APPKEY)) {
System.out.println("\n[错误] 请先在代码顶部的配置区域填写你的 APPKEY");
System.exit(1);
}
if ("你获取到的gt值".equals(GT)) {
System.out.println("\n[错误] 请先在代码顶部的配置区域填写 GT 值");
System.exit(1);
}
if (ITEM_ID == 0) {
System.out.println("\n[错误] 请先在代码顶部的配置区域填写 ITEM_ID(项目类型)");
System.exit(1);
}
try {
// ========== 步骤1:提交极验识别任务 ==========
System.out.println("==================================================");
System.out.println("[提交任务] 正在提交极验识别任务...");
System.out.println("==================================================");
StringBuilder postData = new StringBuilder();
postData.append("appkey=").append(URLEncoder.encode(APPKEY, "UTF-8"));
postData.append(">=").append(URLEncoder.encode(GT, "UTF-8"));
postData.append("&itemid=").append(ITEM_ID);
if (CHALLENGE != null && !CHALLENGE.isEmpty()) {
postData.append("&challenge=").append(URLEncoder.encode(CHALLENGE, "UTF-8"));
}
if (REFERER != null && !REFERER.isEmpty()) {
postData.append("&referer=").append(URLEncoder.encode(REFERER, "UTF-8"));
}
if (PROXY != null && !PROXY.isEmpty()) {
postData.append("&proxy=").append(URLEncoder.encode(PROXY, "UTF-8"));
}
if (DEVKEY != null && !DEVKEY.isEmpty()) {
postData.append("&devkey=").append(URLEncoder.encode(DEVKEY, "UTF-8"));
}
if (SDK != null && !SDK.isEmpty()) {
postData.append("&sdk=").append(URLEncoder.encode(SDK, "UTF-8"));
}
if (GIVEN != null && !GIVEN.isEmpty()) {
postData.append("&given=").append(URLEncoder.encode(GIVEN, "UTF-8"));
}
if (HOST_PARAM != null && !HOST_PARAM.isEmpty()) {
postData.append("&host=").append(URLEncoder.encode(HOST_PARAM, "UTF-8"));
}
if (USER_AGENT != null && !USER_AGENT.isEmpty()) {
postData.append("&userAgent=").append(URLEncoder.encode(USER_AGENT, "UTF-8"));
}
System.out.println("[请求参数] gt=" + GT);
System.out.println("[请求参数] itemid=" + ITEM_ID);
String submitUrl = API_BASE + "/recognize";
String submitResult = httpPost(submitUrl, postData.toString());
System.out.println("[提交响应] " + submitResult);
// 简单解析resultid(无需JSON库)
String resultid = null;
if (submitResult.contains("\"status\":") && submitResult.contains("\"resultid\":")) {
// 提取status值
if (submitResult.contains("\"status\": 1") || submitResult.contains("\"status\":1")) {
int ridStart = submitResult.indexOf("\"resultid\":");
if (ridStart >= 0) {
int valStart = submitResult.indexOf("\"", ridStart + 11) + 1;
int valEnd = submitResult.indexOf("\"", valStart);
resultid = submitResult.substring(valStart, valEnd);
System.out.println("[成功] 任务提交成功!resultid=" + resultid);
}
} else {
System.out.println("[失败] 任务提交失败");
}
}
if (resultid == null || resultid.isEmpty()) {
System.out.println("[失败] 未获取到resultid,请检查参数配置");
System.exit(1);
}
// ========== 步骤2:轮询查询识别结果 ==========
System.out.println("\n==================================================");
System.out.println("[查询结果] 正在轮询识别结果...");
System.out.println("[查询结果] 轮询间隔:" + (POLL_INTERVAL / 1000) + "秒,最大等待:" + (MAX_POLL_TIME / 1000) + "秒");
System.out.println("==================================================");
String queryUrl = API_BASE + "/results";
long startTime = System.currentTimeMillis();
while (true) {
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > MAX_POLL_TIME) {
System.out.println("[超时] 已等待" + (MAX_POLL_TIME / 1000) + "秒,识别超时,请稍后重试");
break;
}
Thread.sleep(POLL_INTERVAL);
String queryData = "appkey=" + URLEncoder.encode(APPKEY, "UTF-8")
+ "&resultid=" + URLEncoder.encode(resultid, "UTF-8");
String queryResult = httpPost(queryUrl, queryData);
elapsed = System.currentTimeMillis() - startTime;
if (queryResult.contains("\"status\": 1") || queryResult.contains("\"status\":1")) {
System.out.println("\n[成功] 识别成功!");
System.out.println("[完整响应] " + queryResult);
break;
} else {
System.out.println("[等待中] 第" + (elapsed / 1000) + "秒 - 正在识别中...");
}
}
} catch (Exception e) {
System.out.println("[异常] 网络请求出错:" + e.getMessage());
}
System.out.println("\n==================================================");
System.out.println("[完成] 识别执行完毕");
System.out.println("==================================================");
}
}
Rust
Rust
该语言注意事项
跟随当前语言展示- ============================================================== 极验识别 对接示例 — Rust版 使用说明 ============================================================== 【一、环境准备】 1. 安装 Rust / Cargo - 官方地址:https://www.rust-lang.org/tools/install - 安装完成后执行: rustc --version cargo --version 2. 安装依赖 - 进入你的 Cargo 项目后执行: cargo add reqwest --features blocking,json,rustls-tls cargo add serde_json -------------------------------------------------------------- 【二、参数配置】 本 Demo 包含两个独立脚本: - query_points.rs — 查询账户剩余点数 - recognize_geetest.rs — 极验验证码识别(异步轮询) 需要重点填写: 1. APPKEY 2. GT 3. CHALLENGE(三代必填,四代留空) 4. ITEM_ID(请参照项目价格表) 5. REFERER / PROXY / DEVKEY / SDK / GIVEN / HOST / USER_AGENT 按需填写 -------------------------------------------------------------- 【三、运行方式】 1. 将文件放入 Cargo 项目中,例如: src/bin/query_points.rs src/bin/recognize_geetest.rs 2. 查询点数: cargo run --bin query_points 3. 极验识别: cargo run --bin recognize_geetest -------------------------------------------------------------- 【四、极验识别流程说明】 1. 先调用 /recognize 提交任务,获取 resultid 2. 再调用 /results 轮询查询结果 3. Demo 默认每 2 秒查询一次,最大等待 60 秒 -------------------------------------------------------------- 【五、重要注意事项】 1. 查询结果接口每秒不得超过 1 次,否则会被拉黑 IP 10 分钟 2. 查询点数接口每秒不得超过 1 次,否则会被拉黑 24 小时 3. 三代 challenge 每次只能使用一次,需实时抓包 4. 四代如遇结果无法通过,可能需要对 captchaOutput 中的 "=" 做编码处理 5. 不要将 APPKEY 泄露给他人 ==============================================================
查询点数
query_points.rs
/*
=============================================================
查询账户点数 Demo (Rust版)
功能说明:
查询账户剩余点数(余额)
使用方法:
1. 确保已安装 Rust / Cargo(建议 stable 版本)
2. 执行:
cargo add reqwest --features blocking,json,rustls-tls
cargo add serde_json
3. 将下方的 APPKEY 替换为你自己的用户密钥
4. 运行脚本:cargo run --bin query_points
=============================================================
*/
use reqwest::blocking::Client;
use serde_json::Value;
use std::error::Error;
use std::process;
use std::time::Duration;
const APPKEY: &str = "你的appkey";
const API_BASE: &str = "http://api.ttocr.com/api";
fn query_points() -> Result<Value, Box<dyn Error>> {
let client = Client::builder().timeout(Duration::from_secs(10)).build()?;
let result: Value = client
.get(&format!("{}/points", API_BASE))
.query(&[("appkey", APPKEY)])
.send()?
.json()?;
if result["status"].as_i64() == Some(1) {
println!("[成功] 查询成功!当前可用点数:{}", result["points"]);
} else {
println!("[失败] 查询失败,错误信息:{}", result["msg"]);
println!("[提示] 错误状态码:{},请参考错误代码表排查", result["status"]);
}
println!(
"[完整响应] {}",
serde_json::to_string_pretty(&result).unwrap_or_else(|_| result.to_string())
);
Ok(result)
}
fn main() {
println!("************************************************************");
println!(" 查询账户点数 Demo (Rust版)");
println!("************************************************************");
if APPKEY == "你的appkey" {
println!("\n[错误] 请先在代码顶部的配置区域填写你的 APPKEY");
process::exit(1);
}
println!("==================================================");
println!("[查询点数] 正在查询账户剩余点数...");
println!("==================================================");
if let Err(error) = query_points() {
println!("[异常] 网络请求出错:{}", error);
process::exit(1);
}
println!("\n==================================================");
println!("[完成] 查询执行完毕");
println!("==================================================");
}
提交识别
recognize_geetest.rs
/*
=============================================================
极验识别 Demo (Rust版)
功能说明:
提交极验验证码识别任务(支持三代/四代)
极验识别为异步流程:先提交任务获取 resultid,再轮询查询结果
使用方法:
1. 确保已安装 Rust / Cargo(建议 stable 版本)
2. 执行:
cargo add reqwest --features blocking,json,rustls-tls
cargo add serde_json
3. 将下方的配置参数替换为你自己的值
4. 运行脚本:cargo run --bin recognize_geetest
=============================================================
*/
use reqwest::blocking::Client;
use serde_json::Value;
use std::collections::HashMap;
use std::error::Error;
use std::process;
use std::thread;
use std::time::{Duration, Instant};
const APPKEY: &str = "你的appkey";
const GT: &str = "你获取到的gt值";
const CHALLENGE: &str = "";
const ITEM_ID: &str = "0";
const REFERER: &str = "";
const PROXY: &str = "";
const DEVKEY: &str = "";
const SDK: &str = "";
const GIVEN: &str = "";
const HOST: &str = "";
const USER_AGENT: &str = "";
const API_BASE: &str = "http://api.ttocr.com/api";
const POLL_INTERVAL_SECONDS: u64 = 2;
const MAX_POLL_SECONDS: u64 = 60;
fn build_client(timeout_seconds: u64) -> Result<Client, Box<dyn Error>> {
Ok(Client::builder()
.timeout(Duration::from_secs(timeout_seconds))
.build()?)
}
fn submit_task() -> Result<String, Box<dyn Error>> {
println!("==================================================");
println!("[提交任务] 正在提交极验识别任务...");
println!("==================================================");
let client = build_client(30)?;
let mut params = HashMap::new();
params.insert("appkey", APPKEY.to_string());
params.insert("gt", GT.to_string());
params.insert("itemid", ITEM_ID.to_string());
if !CHALLENGE.is_empty() {
params.insert("challenge", CHALLENGE.to_string());
}
if !REFERER.is_empty() {
params.insert("referer", REFERER.to_string());
}
if !PROXY.is_empty() {
params.insert("proxy", PROXY.to_string());
}
if !DEVKEY.is_empty() {
params.insert("devkey", DEVKEY.to_string());
}
if !SDK.is_empty() {
params.insert("sdk", SDK.to_string());
}
if !GIVEN.is_empty() {
params.insert("given", GIVEN.to_string());
}
if !HOST.is_empty() {
params.insert("host", HOST.to_string());
}
if !USER_AGENT.is_empty() {
params.insert("userAgent", USER_AGENT.to_string());
}
println!("[请求参数] gt={}", GT);
println!("[请求参数] itemid={}", ITEM_ID);
let result: Value = client
.post(&format!("{}/recognize", API_BASE))
.form(¶ms)
.send()?
.json()?;
println!(
"[提交响应] {}",
serde_json::to_string_pretty(&result).unwrap_or_else(|_| result.to_string())
);
if result["status"].as_i64() == Some(1) {
let result_id = result["resultid"].as_str().unwrap_or("").to_string();
println!("[成功] 任务提交成功!resultid={}", result_id);
return Ok(result_id);
}
Err(format!("任务提交失败:{}", result["msg"]).into())
}
fn query_result(result_id: &str) -> Result<(), Box<dyn Error>> {
println!("\n==================================================");
println!("[查询结果] 正在轮询识别结果...");
println!(
"[查询结果] 轮询间隔:{}秒,最大等待:{}秒",
POLL_INTERVAL_SECONDS, MAX_POLL_SECONDS
);
println!("==================================================");
let client = build_client(30)?;
let started_at = Instant::now();
loop {
if started_at.elapsed() > Duration::from_secs(MAX_POLL_SECONDS) {
return Err(format!("已等待{}秒,识别超时,请稍后重试", MAX_POLL_SECONDS).into());
}
thread::sleep(Duration::from_secs(POLL_INTERVAL_SECONDS));
let mut params = HashMap::new();
params.insert("appkey", APPKEY.to_string());
params.insert("resultid", result_id.to_string());
let result: Value = client
.post(&format!("{}/results", API_BASE))
.form(¶ms)
.send()?
.json()?;
if result["status"].as_i64() == Some(1) {
println!("\n[成功] 识别成功!耗时:{}ms", result["time"]);
println!("[识别结果] {}", result["data"]);
println!(
"\n[完整响应] {}",
serde_json::to_string_pretty(&result).unwrap_or_else(|_| result.to_string())
);
return Ok(());
}
println!(
"[等待中] 第{}秒 - {}",
started_at.elapsed().as_secs(),
result["msg"]
);
}
}
fn main() {
println!("************************************************************");
println!(" 极验识别 Demo (Rust版)");
println!("************************************************************");
if APPKEY == "你的appkey" {
println!("\n[错误] 请先在代码顶部的配置区域填写你的 APPKEY");
process::exit(1);
}
if GT == "你获取到的gt值" {
println!("\n[错误] 请先在代码顶部的配置区域填写 GT 值");
process::exit(1);
}
if ITEM_ID == "0" {
println!("\n[错误] 请先在代码顶部的配置区域填写 ITEM_ID(项目类型)");
process::exit(1);
}
let result_id = match submit_task() {
Ok(result_id) => result_id,
Err(error) => {
println!("[失败] {}", error);
process::exit(1);
}
};
if let Err(error) = query_result(&result_id) {
println!("[失败] {}", error);
process::exit(1);
}
println!("\n==================================================");
println!("[完成] 识别执行完毕");
println!("==================================================");
}
C#
C#
该语言注意事项
跟随当前语言展示- =============================================================== 极验识别 对接示例 - C#版 使用说明 =============================================================== 【环境准备】 1. 安装 .NET Framework 4.5+ 或 .NET Core/.NET 5+ - Windows系统通常自带 .NET Framework 和 csc 编译器 - .NET Core 下载:https://dotnet.microsoft.com/download 验证安装:csc /? 或 dotnet --version 【文件说明】 - QueryPoints.cs 查询账户剩余点数(余额) - RecognizeGeetest.cs 极验验证码识别(支持三代/四代,异步轮询) 【参数配置】 1. APPKEY - 用户密钥,登录平台后在个人中心获取 2. GT - 极验gt值(三代为gt值,四代为captcha_id值),从目标网站抓包获取 3. CHALLENGE - 三代必填(每次只能用一次),四代留空 4. ITEM_ID - 项目类型编号,请参照项目价格表选择对应的值 5. REFERER - 验证码所在页面URL,部分网站需要填写 6. PROXY - 代理IP(可选) 7. DEVKEY - 开发者密钥(可选) 【编译与运行】 方式一:使用 .NET Framework csc 编译器 1. 查询点数: csc /out:QueryPoints.exe QueryPoints.cs QueryPoints.exe 2. 极验识别: csc /out:RecognizeGeetest.exe RecognizeGeetest.cs RecognizeGeetest.exe 注意:csc 通常位于: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe 如果 csc 不在 PATH 中,请使用完整路径。 方式二:使用 .NET Core / .NET 5+ 1. 创建项目:dotnet new console -n GeetestDemo 2. 将对应的 .cs 文件内容替换 Program.cs 3. 运行:dotnet run 【极验识别流程说明】 极验识别为异步流程,分两步: 步骤1:提交识别任务 → 返回 resultid 步骤2:使用 resultid 轮询查询结果 → 返回识别数据 脚本已自动实现轮询逻辑(Thread.Sleep),默认每2秒查询一次,最多等待60秒。 本Demo使用 System.Net 内置类,无需任何NuGet包。 【三代与四代的区别】 - 三代:需要传 gt 和 challenge 参数,返回 validate/seccode - 四代:只需传 gt(即captcha_id),无需 challenge,返回 captchaOutput/lotNumber/passToken/genTime 【常见问题】 1. "'csc' 不是内部或外部命令" → 使用完整路径:C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe 2. 编译报错中文乱码 → 确保源文件保存为 UTF-8 编码 3. 提交后返回 "识别类型错误" → 检查 ITEM_ID 是否与你的极验类型匹配 4. 三代 challenge 无效 → challenge 每次只能使用一次,请直接抓包获取 【重要注意事项】 - 查询结果接口每秒不得超过1次,否则会被拉黑IP 10分钟 - 查询点数接口每秒不得超过1次,否则会被拉黑24小时 - APPKEY 属于敏感信息,请勿泄露 - 四代如遇无法通过,captchaOutput中的'='符号需用%3D替换
查询点数
QueryPoints.cs
using System;
using System.IO;
using System.Net;
using System.Text;
/// <summary>
/// =============================================================
/// 查询账户点数 Demo (C#版)
///
/// 功能说明:
/// 查询账户剩余点数(余额)
///
/// 使用方法:
/// 1. 将下方的 APPKEY 替换为你自己的用户密钥
/// 2. 编译运行:csc /out:QueryPoints.exe QueryPoints.cs && QueryPoints.exe
/// =============================================================
/// </summary>
class QueryPoints
{
// ======================== 配置区域(请替换为你自己的参数)========================
// 用户密钥,登录平台后获取
static string APPKEY = "你的appkey";
// ===============================================================================
// API基础地址
static string API_BASE = "http://api.ttocr.com/api";
/// <summary>
/// 发送GET请求
/// </summary>
static string HttpGet(string url)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
request.Timeout = 10000;
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
{
return reader.ReadToEnd();
}
}
static void Main(string[] args)
{
Console.OutputEncoding = Encoding.UTF8;
Console.WriteLine(new string('*', 60));
Console.WriteLine(" 查询账户点数 Demo (C#版)");
Console.WriteLine(new string('*', 60));
if (APPKEY == "你的appkey")
{
Console.WriteLine("\n[错误] 请先在代码顶部的配置区域填写你的 APPKEY");
Environment.Exit(1);
}
Console.WriteLine(new string('=', 50));
Console.WriteLine("[查询点数] 正在查询账户剩余点数...");
Console.WriteLine(new string('=', 50));
try
{
string url = API_BASE + "/points?appkey=" + Uri.EscapeDataString(APPKEY);
string result = HttpGet(url);
Console.WriteLine("[完整响应] " + result);
}
catch (Exception e)
{
Console.WriteLine("[异常] 网络请求出错:" + e.Message);
}
Console.WriteLine("\n" + new string('=', 50));
Console.WriteLine("[完成] 查询执行完毕");
Console.WriteLine(new string('=', 50));
}
}
提交识别
RecognizeGeetest.cs
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;
/// <summary>
/// =============================================================
/// 极验识别 Demo (C#版)
///
/// 功能说明:
/// 提交极验验证码识别任务(支持三代/四代)
/// 极验识别为异步流程:先提交任务获取resultid,再轮询查询结果
///
/// 使用方法:
/// 1. 将下方的配置参数替换为你自己的值
/// 2. 编译运行:csc /out:RecognizeGeetest.exe RecognizeGeetest.cs && RecognizeGeetest.exe
/// =============================================================
/// </summary>
class RecognizeGeetest
{
// ======================== 配置区域(请替换为你自己的参数)========================
// 用户密钥,登录平台后获取
static string APPKEY = "你的appkey";
// 极验gt值(三代为gt值,四代为captcha_id值)
static string GT = "你获取到的gt值";
// challenge值(三代必填,每次只能使用一次;四代无需传此参数,留空即可)
static string CHALLENGE = "";
// 项目类型(请参照项目价格表,不同类型对应不同的itemid)
static int ITEM_ID = 0;
// 验证码所在的页面URL(可选,部分网站需要填写)
static string REFERER = "";
// 可选参数:代理IP(格式示例:http://IP:端口,若需白名单支持请联系客服。http://账号:密码@proxy.com:8080 或 socks5://127.0.0.1:9888)
static string PROXY = "";
// 可选参数:开发者密钥(如果有的话填写)
static string DEVKEY = "";
// 可选参数:SDK版本(特殊版本为2,默认为1)
static string SDK = "";
// 可选参数:对接模式(按次计费:0,包月计费:1,默认为0。包月用户必填)
static string GIVEN = "";
// 可选参数:特殊网站极验域名(如api-na.geetest.com,不要带http://和/,只需域名)
static string HOST_PARAM = "";
// 可选参数:User-Agent(适用于某些检验UA的网站,只支持传入安卓ua)
static string USER_AGENT = "";
// ===============================================================================
// API基础地址
static string API_BASE = "http://api.ttocr.com/api";
// 轮询配置
static int POLL_INTERVAL = 2000; // 轮询间隔(毫秒),不得低于1秒
static int MAX_POLL_TIME = 60000; // 最大等待时间(毫秒)
/// <summary>
/// 发送POST请求(表单数据)
/// </summary>
static string HttpPost(string url, string postData)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.Timeout = 30000;
byte[] data = Encoding.UTF8.GetBytes(postData);
request.ContentLength = data.Length;
using (Stream stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
{
return reader.ReadToEnd();
}
}
static void Main(string[] args)
{
Console.OutputEncoding = Encoding.UTF8;
Console.WriteLine(new string('*', 60));
Console.WriteLine(" 极验识别 Demo (C#版)");
Console.WriteLine(new string('*', 60));
if (APPKEY == "你的appkey")
{
Console.WriteLine("\n[错误] 请先在代码顶部的配置区域填写你的 APPKEY");
Environment.Exit(1);
}
if (GT == "你获取到的gt值")
{
Console.WriteLine("\n[错误] 请先在代码顶部的配置区域填写 GT 值");
Environment.Exit(1);
}
if (ITEM_ID == 0)
{
Console.WriteLine("\n[错误] 请先在代码顶部的配置区域填写 ITEM_ID(项目类型)");
Environment.Exit(1);
}
try
{
// ========== 步骤1:提交极验识别任务 ==========
Console.WriteLine(new string('=', 50));
Console.WriteLine("[提交任务] 正在提交极验识别任务...");
Console.WriteLine(new string('=', 50));
StringBuilder postData = new StringBuilder();
postData.Append("appkey=").Append(Uri.EscapeDataString(APPKEY));
postData.Append(">=").Append(Uri.EscapeDataString(GT));
postData.Append("&itemid=").Append(ITEM_ID);
if (!string.IsNullOrEmpty(CHALLENGE))
postData.Append("&challenge=").Append(Uri.EscapeDataString(CHALLENGE));
if (!string.IsNullOrEmpty(REFERER))
postData.Append("&referer=").Append(Uri.EscapeDataString(REFERER));
if (!string.IsNullOrEmpty(PROXY))
postData.Append("&proxy=").Append(Uri.EscapeDataString(PROXY));
if (!string.IsNullOrEmpty(DEVKEY))
postData.Append("&devkey=").Append(Uri.EscapeDataString(DEVKEY));
if (!string.IsNullOrEmpty(SDK))
postData.Append("&sdk=").Append(Uri.EscapeDataString(SDK));
if (!string.IsNullOrEmpty(GIVEN))
postData.Append("&given=").Append(Uri.EscapeDataString(GIVEN));
if (!string.IsNullOrEmpty(HOST_PARAM))
postData.Append("&host=").Append(Uri.EscapeDataString(HOST_PARAM));
if (!string.IsNullOrEmpty(USER_AGENT))
postData.Append("&userAgent=").Append(Uri.EscapeDataString(USER_AGENT));
Console.WriteLine("[请求参数] gt=" + GT);
Console.WriteLine("[请求参数] itemid=" + ITEM_ID);
string submitUrl = API_BASE + "/recognize";
string submitResult = HttpPost(submitUrl, postData.ToString());
Console.WriteLine("[提交响应] " + submitResult);
// 简单解析resultid(无需JSON库)
string resultid = null;
if (submitResult.Contains("\"status\":1") || submitResult.Contains("\"status\": 1"))
{
int ridStart = submitResult.IndexOf("\"resultid\":");
if (ridStart >= 0)
{
int valStart = submitResult.IndexOf("\"", ridStart + 11) + 1;
int valEnd = submitResult.IndexOf("\"", valStart);
resultid = submitResult.Substring(valStart, valEnd - valStart);
Console.WriteLine("[成功] 任务提交成功!resultid=" + resultid);
}
}
else
{
Console.WriteLine("[失败] 任务提交失败");
}
if (string.IsNullOrEmpty(resultid))
{
Console.WriteLine("[失败] 未获取到resultid,请检查参数配置");
Environment.Exit(1);
}
// ========== 步骤2:轮询查询识别结果 ==========
Console.WriteLine("\n" + new string('=', 50));
Console.WriteLine("[查询结果] 正在轮询识别结果...");
Console.WriteLine("[查询结果] 轮询间隔:" + (POLL_INTERVAL / 1000) + "秒,最大等待:" + (MAX_POLL_TIME / 1000) + "秒");
Console.WriteLine(new string('=', 50));
string queryUrl = API_BASE + "/results";
long startTime = Environment.TickCount;
while (true)
{
long elapsed = Environment.TickCount - startTime;
if (elapsed > MAX_POLL_TIME)
{
Console.WriteLine("[超时] 已等待" + (MAX_POLL_TIME / 1000) + "秒,识别超时,请稍后重试");
break;
}
Thread.Sleep(POLL_INTERVAL);
string queryData = "appkey=" + Uri.EscapeDataString(APPKEY)
+ "&resultid=" + Uri.EscapeDataString(resultid);
string queryResult = HttpPost(queryUrl, queryData);
elapsed = Environment.TickCount - startTime;
if (queryResult.Contains("\"status\":1") || queryResult.Contains("\"status\": 1"))
{
Console.WriteLine("\n[成功] 识别成功!");
Console.WriteLine("[完整响应] " + queryResult);
break;
}
else
{
Console.WriteLine("[等待中] 第" + (elapsed / 1000) + "秒 - 正在识别中...");
}
}
}
catch (Exception e)
{
Console.WriteLine("[异常] 网络请求出错:" + e.Message);
}
Console.WriteLine("\n" + new string('=', 50));
Console.WriteLine("[完成] 识别执行完毕");
Console.WriteLine(new string('=', 50));
}
}
C++
C++
该语言注意事项
跟随当前语言展示- ============================================================== 极验识别 对接示例 — C++版 使用说明 ============================================================== 【一、环境准备】 1. 安装 g++ - Ubuntu 可执行: sudo apt-get install g++ 2. 安装 libcurl 开发库 - Ubuntu 可执行: sudo apt-get install libcurl4-openssl-dev -------------------------------------------------------------- 【二、参数配置】 本 Demo 包含两个独立脚本: - QueryPoints.cpp — 查询账户剩余点数 - RecognizeGeetest.cpp — 极验验证码识别(异步轮询) 需要重点填写: 1. APPKEY 2. GT 3. CHALLENGE(三代必填,四代留空) 4. ITEM_ID(请参照项目价格表) 5. REFERER / PROXY / DEVKEY / SDK / GIVEN / HOST / USER_AGENT 按需填写 -------------------------------------------------------------- 【三、运行方式】 1. 查询点数: g++ -std=c++11 QueryPoints.cpp -lcurl -o query_points ./query_points 2. 极验识别: g++ -std=c++11 RecognizeGeetest.cpp -lcurl -o recognize_geetest ./recognize_geetest -------------------------------------------------------------- 【四、极验识别流程说明】 1. 先调用 /recognize 提交任务,获取 resultid 2. 再调用 /results 轮询查询结果 3. Demo 默认每 2 秒查询一次,最大等待 60 秒 -------------------------------------------------------------- 【五、重要注意事项】 1. 查询结果接口每秒不得超过 1 次,否则会被拉黑 IP 10 分钟 2. 查询点数接口每秒不得超过 1 次,否则会被拉黑 24 小时 3. 三代 challenge 每次只能使用一次,需实时抓包 4. 四代如遇结果无法通过,可能需要对 captchaOutput 中的 "=" 做编码处理 5. 不要将 APPKEY 泄露给他人 ==============================================================
查询点数
QueryPoints.cpp
#include <curl/curl.h>
#include <cctype>
#include <cstdlib>
#include <iostream>
#include <stdexcept>
#include <string>
/*
=============================================================
查询账户点数 Demo (C++版)
功能说明:
查询账户剩余点数(余额)
使用方法:
1. 确保已安装 g++ 和 libcurl 开发库
2. 将下方的 APPKEY 替换为你自己的用户密钥
3. 编译运行:
g++ -std=c++11 QueryPoints.cpp -lcurl -o query_points
./query_points
=============================================================
*/
const std::string APPKEY = "你的appkey";
const std::string API_BASE = "http://api.ttocr.com/api";
static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp) {
size_t total = size * nmemb;
static_cast<std::string*>(userp)->append(static_cast<char*>(contents), total);
return total;
}
std::string Trim(const std::string& input) {
size_t start = 0;
while (start < input.size() && std::isspace(static_cast<unsigned char>(input[start]))) {
++start;
}
size_t end = input.size();
while (end > start && std::isspace(static_cast<unsigned char>(input[end - 1]))) {
--end;
}
return input.substr(start, end - start);
}
std::string StripQuotes(const std::string& input) {
if (input.size() >= 2 && input.front() == '"' && input.back() == '"') {
return input.substr(1, input.size() - 2);
}
return input;
}
std::string ExtractJsonValue(const std::string& json, const std::string& key) {
std::string needle = "\"" + key + "\"";
size_t keyPos = json.find(needle);
if (keyPos == std::string::npos) {
return "";
}
size_t colon = json.find(':', keyPos + needle.size());
if (colon == std::string::npos) {
return "";
}
size_t pos = colon + 1;
while (pos < json.size() && std::isspace(static_cast<unsigned char>(json[pos]))) {
++pos;
}
bool inString = false;
bool escaped = false;
int braceDepth = 0;
int bracketDepth = 0;
size_t end = pos;
for (; end < json.size(); ++end) {
char ch = json[end];
if (inString) {
if (escaped) {
escaped = false;
continue;
}
if (ch == '\\') {
escaped = true;
continue;
}
if (ch == '"') {
inString = false;
}
continue;
}
if (ch == '"') {
inString = true;
continue;
}
if (ch == '{') {
++braceDepth;
continue;
}
if (ch == '}') {
if (braceDepth == 0 && bracketDepth == 0) {
break;
}
--braceDepth;
continue;
}
if (ch == '[') {
++bracketDepth;
continue;
}
if (ch == ']') {
--bracketDepth;
continue;
}
if (ch == ',' && braceDepth == 0 && bracketDepth == 0) {
break;
}
}
return Trim(json.substr(pos, end - pos));
}
bool IsSuccessStatus(const std::string& json) {
return ExtractJsonValue(json, "status") == "1";
}
std::string HttpGet(const std::string& url) {
CURL* curl = curl_easy_init();
if (!curl) {
throw std::runtime_error("初始化 CURL 失败");
}
std::string response;
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
CURLcode code = curl_easy_perform(curl);
curl_easy_cleanup(curl);
if (code != CURLE_OK) {
throw std::runtime_error(curl_easy_strerror(code));
}
return response;
}
int main() {
std::cout << "************************************************************" << std::endl;
std::cout << " 查询账户点数 Demo (C++版)" << std::endl;
std::cout << "************************************************************" << std::endl;
if (APPKEY == "你的appkey") {
std::cout << "\n[错误] 请先在代码顶部的配置区域填写你的 APPKEY" << std::endl;
return 1;
}
curl_global_init(CURL_GLOBAL_DEFAULT);
std::cout << "==================================================" << std::endl;
std::cout << "[查询点数] 正在查询账户剩余点数..." << std::endl;
std::cout << "==================================================" << std::endl;
try {
CURL* encoder = curl_easy_init();
char* escaped = curl_easy_escape(encoder, APPKEY.c_str(), static_cast<int>(APPKEY.size()));
std::string url = API_BASE + "/points?appkey=" + (escaped ? escaped : "");
if (escaped) {
curl_free(escaped);
}
curl_easy_cleanup(encoder);
std::string result = HttpGet(url);
if (IsSuccessStatus(result)) {
std::cout << "[成功] 查询成功!当前可用点数:" << StripQuotes(ExtractJsonValue(result, "points")) << std::endl;
} else {
std::cout << "[失败] 查询失败,错误信息:" << StripQuotes(ExtractJsonValue(result, "msg")) << std::endl;
std::cout << "[提示] 错误状态码:" << ExtractJsonValue(result, "status") << ",请参考错误代码表排查" << std::endl;
}
std::cout << "[完整响应] " << result << std::endl;
} catch (const std::exception& error) {
std::cout << "[异常] 网络请求出错:" << error.what() << std::endl;
curl_global_cleanup();
return 1;
}
curl_global_cleanup();
std::cout << "\n==================================================" << std::endl;
std::cout << "[完成] 查询执行完毕" << std::endl;
std::cout << "==================================================" << std::endl;
return 0;
}
提交识别
RecognizeGeetest.cpp
#include <curl/curl.h>
#include <cctype>
#include <cstdlib>
#include <iostream>
#include <stdexcept>
#include <string>
#include <thread>
#include <chrono>
/*
=============================================================
极验识别 Demo (C++版)
功能说明:
提交极验验证码识别任务(支持三代/四代)
极验识别为异步流程:先提交任务获取 resultid,再轮询查询结果
使用方法:
1. 确保已安装 g++ 和 libcurl 开发库
2. 将下方的配置参数替换为你自己的值
3. 编译运行:
g++ -std=c++11 RecognizeGeetest.cpp -lcurl -o recognize_geetest
./recognize_geetest
=============================================================
*/
const std::string APPKEY = "你的appkey";
const std::string GT = "你获取到的gt值";
const std::string CHALLENGE = "";
const std::string ITEM_ID = "0";
const std::string REFERER = "";
const std::string PROXY = "";
const std::string DEVKEY = "";
const std::string SDK = "";
const std::string GIVEN = "";
const std::string HOST = "";
const std::string USER_AGENT = "";
const std::string API_BASE = "http://api.ttocr.com/api";
const int POLL_INTERVAL_SECONDS = 2;
const int MAX_POLL_SECONDS = 60;
static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp) {
size_t total = size * nmemb;
static_cast<std::string*>(userp)->append(static_cast<char*>(contents), total);
return total;
}
std::string Trim(const std::string& input) {
size_t start = 0;
while (start < input.size() && std::isspace(static_cast<unsigned char>(input[start]))) {
++start;
}
size_t end = input.size();
while (end > start && std::isspace(static_cast<unsigned char>(input[end - 1]))) {
--end;
}
return input.substr(start, end - start);
}
std::string StripQuotes(const std::string& input) {
if (input.size() >= 2 && input.front() == '"' && input.back() == '"') {
return input.substr(1, input.size() - 2);
}
return input;
}
std::string ExtractJsonValue(const std::string& json, const std::string& key) {
std::string needle = "\"" + key + "\"";
size_t keyPos = json.find(needle);
if (keyPos == std::string::npos) {
return "";
}
size_t colon = json.find(':', keyPos + needle.size());
if (colon == std::string::npos) {
return "";
}
size_t pos = colon + 1;
while (pos < json.size() && std::isspace(static_cast<unsigned char>(json[pos]))) {
++pos;
}
bool inString = false;
bool escaped = false;
int braceDepth = 0;
int bracketDepth = 0;
size_t end = pos;
for (; end < json.size(); ++end) {
char ch = json[end];
if (inString) {
if (escaped) {
escaped = false;
continue;
}
if (ch == '\\') {
escaped = true;
continue;
}
if (ch == '"') {
inString = false;
}
continue;
}
if (ch == '"') {
inString = true;
continue;
}
if (ch == '{') {
++braceDepth;
continue;
}
if (ch == '}') {
if (braceDepth == 0 && bracketDepth == 0) {
break;
}
--braceDepth;
continue;
}
if (ch == '[') {
++bracketDepth;
continue;
}
if (ch == ']') {
--bracketDepth;
continue;
}
if (ch == ',' && braceDepth == 0 && bracketDepth == 0) {
break;
}
}
return Trim(json.substr(pos, end - pos));
}
bool IsSuccessStatus(const std::string& json) {
return ExtractJsonValue(json, "status") == "1";
}
void AppendFormField(CURL* curl, std::string& postData, const std::string& key, const std::string& value) {
char* escaped = curl_easy_escape(curl, value.c_str(), static_cast<int>(value.size()));
if (!postData.empty()) {
postData += "&";
}
postData += key + "=" + (escaped ? escaped : "");
if (escaped) {
curl_free(escaped);
}
}
std::string HttpPost(const std::string& url, const std::string& postData, long timeoutSeconds) {
CURL* curl = curl_easy_init();
if (!curl) {
throw std::runtime_error("初始化 CURL 失败");
}
std::string response;
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_POST, 1L);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postData.c_str());
curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeoutSeconds);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
struct curl_slist* headers = NULL;
headers = curl_slist_append(headers, "Content-Type: application/x-www-form-urlencoded");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
CURLcode code = curl_easy_perform(curl);
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
if (code != CURLE_OK) {
throw std::runtime_error(curl_easy_strerror(code));
}
return response;
}
std::string SubmitTask() {
std::cout << "==================================================" << std::endl;
std::cout << "[提交任务] 正在提交极验识别任务..." << std::endl;
std::cout << "==================================================" << std::endl;
CURL* encoder = curl_easy_init();
std::string postData;
AppendFormField(encoder, postData, "appkey", APPKEY);
AppendFormField(encoder, postData, "gt", GT);
AppendFormField(encoder, postData, "itemid", ITEM_ID);
if (!CHALLENGE.empty()) {
AppendFormField(encoder, postData, "challenge", CHALLENGE);
}
if (!REFERER.empty()) {
AppendFormField(encoder, postData, "referer", REFERER);
}
if (!PROXY.empty()) {
AppendFormField(encoder, postData, "proxy", PROXY);
}
if (!DEVKEY.empty()) {
AppendFormField(encoder, postData, "devkey", DEVKEY);
}
if (!SDK.empty()) {
AppendFormField(encoder, postData, "sdk", SDK);
}
if (!GIVEN.empty()) {
AppendFormField(encoder, postData, "given", GIVEN);
}
if (!HOST.empty()) {
AppendFormField(encoder, postData, "host", HOST);
}
if (!USER_AGENT.empty()) {
AppendFormField(encoder, postData, "userAgent", USER_AGENT);
}
curl_easy_cleanup(encoder);
std::cout << "[请求参数] gt=" << GT << std::endl;
std::cout << "[请求参数] itemid=" << ITEM_ID << std::endl;
std::string result = HttpPost(API_BASE + "/recognize", postData, 30L);
std::cout << "[提交响应] " << result << std::endl;
if (!IsSuccessStatus(result)) {
throw std::runtime_error("任务提交失败:" + StripQuotes(ExtractJsonValue(result, "msg")));
}
std::string resultID = StripQuotes(ExtractJsonValue(result, "resultid"));
std::cout << "[成功] 任务提交成功!resultid=" << resultID << std::endl;
return resultID;
}
void QueryResult(const std::string& resultID) {
std::cout << "\n==================================================" << std::endl;
std::cout << "[查询结果] 正在轮询识别结果..." << std::endl;
std::cout << "[查询结果] 轮询间隔:" << POLL_INTERVAL_SECONDS << "秒,最大等待:" << MAX_POLL_SECONDS << "秒" << std::endl;
std::cout << "==================================================" << std::endl;
for (int elapsed = 0; elapsed <= MAX_POLL_SECONDS; elapsed += POLL_INTERVAL_SECONDS) {
std::this_thread::sleep_for(std::chrono::seconds(POLL_INTERVAL_SECONDS));
CURL* encoder = curl_easy_init();
std::string postData;
AppendFormField(encoder, postData, "appkey", APPKEY);
AppendFormField(encoder, postData, "resultid", resultID);
curl_easy_cleanup(encoder);
std::string result = HttpPost(API_BASE + "/results", postData, 30L);
if (IsSuccessStatus(result)) {
std::cout << "\n[成功] 识别成功!耗时:" << StripQuotes(ExtractJsonValue(result, "time")) << "ms" << std::endl;
std::cout << "[识别结果] " << ExtractJsonValue(result, "data") << std::endl;
std::cout << "\n[完整响应] " << result << std::endl;
return;
}
std::cout << "[等待中] 第" << (elapsed + POLL_INTERVAL_SECONDS) << "秒 - "
<< StripQuotes(ExtractJsonValue(result, "msg")) << std::endl;
}
throw std::runtime_error("已等待60秒,识别超时,请稍后重试");
}
int main() {
std::cout << "************************************************************" << std::endl;
std::cout << " 极验识别 Demo (C++版)" << std::endl;
std::cout << "************************************************************" << std::endl;
if (APPKEY == "你的appkey") {
std::cout << "\n[错误] 请先在代码顶部的配置区域填写你的 APPKEY" << std::endl;
return 1;
}
if (GT == "你获取到的gt值") {
std::cout << "\n[错误] 请先在代码顶部的配置区域填写 GT 值" << std::endl;
return 1;
}
if (ITEM_ID == "0") {
std::cout << "\n[错误] 请先在代码顶部的配置区域填写 ITEM_ID(项目类型)" << std::endl;
return 1;
}
curl_global_init(CURL_GLOBAL_DEFAULT);
try {
std::string resultID = SubmitTask();
QueryResult(resultID);
} catch (const std::exception& error) {
std::cout << "[失败] " << error.what() << std::endl;
curl_global_cleanup();
return 1;
}
curl_global_cleanup();
std::cout << "\n==================================================" << std::endl;
std::cout << "[完成] 识别执行完毕" << std::endl;
std::cout << "==================================================" << std::endl;
return 0;
}
PHP
PHP
该语言注意事项
跟随当前语言展示- =============================================================== 极验识别 对接示例 - PHP版 使用说明 =============================================================== 【环境准备】 1. 安装 PHP 7.0 或更高版本 下载地址:https://www.php.net/downloads Windows用户推荐下载 Thread Safe 版本 验证安装:php -v 2. 确保启用 curl 扩展 编辑 php.ini,去掉 extension=curl 前面的分号 验证:php -m | findstr curl(Windows) 验证:php -m | grep curl(Linux/Mac) 【文件说明】 - query_points.php 查询账户剩余点数(余额) - recognize_geetest.php 极验验证码识别(支持三代/四代,异步轮询) 【参数配置】 1. $APPKEY - 用户密钥,登录平台后在个人中心获取 2. $GT - 极验gt值(三代为gt值,四代为captcha_id值),从目标网站抓包获取 3. $CHALLENGE - 三代必填(每次只能用一次),四代留空 4. $ITEM_ID - 项目类型编号,请参照项目价格表选择对应的值 5. $REFERER - 验证码所在页面URL,部分网站需要填写 6. $PROXY - 代理IP(可选) 7. $DEVKEY - 开发者密钥(可选) 【运行方式】 1. 查询点数:php query_points.php 2. 极验识别:php recognize_geetest.php 【极验识别流程说明】 极验识别为异步流程,分两步: 步骤1:提交识别任务 → 返回 resultid 步骤2:使用 resultid 轮询查询结果 → 返回识别数据 脚本已自动实现轮询逻辑(sleep),默认每2秒查询一次,最多等待60秒。 【三代与四代的区别】 - 三代:需要传 gt 和 challenge 参数,返回 validate/seccode - 四代:只需传 gt(即captcha_id),无需 challenge,返回 captchaOutput/lotNumber/passToken/genTime 【常见问题】 1. "Call to undefined function curl_init()" → PHP未启用curl扩展,编辑php.ini启用 extension=curl 2. "'php' 不是内部或外部命令" → PHP未安装或未添加到系统PATH 3. 提交后返回 "识别类型错误" → 检查 $ITEM_ID 是否与你的极验类型匹配 4. 三代 challenge 无效 → challenge 每次只能使用一次,请直接抓包获取 【重要注意事项】 - 查询结果接口每秒不得超过1次,否则会被拉黑IP 10分钟 - 查询点数接口每秒不得超过1次,否则会被拉黑24小时 - APPKEY 属于敏感信息,请勿泄露 - 四代如遇无法通过,captchaOutput中的'='符号需用%3D替换
查询点数
query_points.php
<?php
/**
* =============================================================
* 查询账户点数 Demo (PHP版)
*
* 功能说明:
* 查询账户剩余点数(余额)
*
* 使用方法:
* 1. 确保PHP已安装并启用curl扩展
* 2. 将下方的 APPKEY 替换为你自己的用户密钥
* 3. 运行脚本:php query_points.php
* =============================================================
*/
// ======================== 配置区域(请替换为你自己的参数)========================
// 用户密钥,登录平台后获取
$APPKEY = "你的appkey";
// ===============================================================================
// API基础地址
$API_BASE = "http://api.ttocr.com/api";
echo str_repeat("*", 60) . "\n";
echo " 查询账户点数 Demo (PHP版)\n";
echo str_repeat("*", 60) . "\n";
if ($APPKEY === "你的appkey") {
echo "\n[错误] 请先在脚本顶部的配置区域填写你的 APPKEY\n";
exit(1);
}
echo str_repeat("=", 50) . "\n";
echo "[查询点数] 正在查询账户剩余点数...\n";
echo str_repeat("=", 50) . "\n";
$url = $API_BASE . "/points?appkey=" . urlencode($APPKEY);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$response = curl_exec($ch);
if (curl_errno($ch)) {
echo "[异常] 网络请求出错:" . curl_error($ch) . "\n";
curl_close($ch);
exit(1);
}
curl_close($ch);
$result = json_decode($response, true);
if ($result && $result["status"] == 1) {
echo "[成功] 查询成功!当前可用点数:" . $result["points"] . "\n";
} else {
echo "[失败] 查询失败,错误信息:" . ($result["msg"] ?? "未知") . "\n";
echo "[提示] 错误状态码:" . ($result["status"] ?? "未知") . ",请参考错误代码表排查\n";
}
echo "[完整响应] " . json_encode($result, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) . "\n";
echo "\n" . str_repeat("=", 50) . "\n";
echo "[完成] 查询执行完毕\n";
echo str_repeat("=", 50) . "\n";
?>
提交识别
recognize_geetest.php
<?php
/**
* =============================================================
* 极验识别 Demo (PHP版)
*
* 功能说明:
* 提交极验验证码识别任务(支持三代/四代)
* 极验识别为异步流程:先提交任务获取resultid,再轮询查询结果
*
* 使用方法:
* 1. 确保PHP已安装并启用curl扩展
* 2. 将下方的配置参数替换为你自己的值
* 3. 运行脚本:php recognize_geetest.php
* =============================================================
*/
// ======================== 配置区域(请替换为你自己的参数)========================
// 用户密钥,登录平台后获取
$APPKEY = "你的appkey";
// 极验gt值(三代为gt值,四代为captcha_id值)
$GT = "你获取到的gt值";
// challenge值(三代必填,每次只能使用一次;四代无需传此参数,留空即可)
$CHALLENGE = "";
// 项目类型(请参照项目价格表,不同类型对应不同的itemid)
$ITEM_ID = 0;
// 验证码所在的页面URL(可选,部分网站需要填写)
$REFERER = "";
// 可选参数:代理IP(格式示例:http://IP:端口,若需白名单支持请联系客服。http://账号:密码@proxy.com:8080 或 socks5://127.0.0.1:9888)
$PROXY = "";
// 可选参数:开发者密钥(如果有的话填写)
$DEVKEY = "";
// 可选参数:SDK版本(特殊版本为2,默认为1)
$SDK = "";
// 可选参数:对接模式(按次计费:0,包月计费:1,默认为0。包月用户必填)
$GIVEN = "";
// 可选参数:特殊网站极验域名(如api-na.geetest.com,不要带http://和/,只需域名)
$HOST_PARAM = "";
// 可选参数:User-Agent(适用于某些检验UA的网站,只支持传入安卓ua)
$USER_AGENT = "";
// ===============================================================================
// API基础地址
$API_BASE = "http://api.ttocr.com/api";
// 轮询配置
$POLL_INTERVAL = 2; // 轮询间隔(秒),不得低于1秒
$MAX_POLL_TIME = 60; // 最大等待时间(秒)
/**
* 发送POST请求
*/
function httpPost($url, $postData) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
$response = curl_exec($ch);
if (curl_errno($ch)) {
$error = curl_error($ch);
curl_close($ch);
throw new Exception("网络请求出错:" . $error);
}
curl_close($ch);
return json_decode($response, true);
}
echo str_repeat("*", 60) . "\n";
echo " 极验识别 Demo (PHP版)\n";
echo str_repeat("*", 60) . "\n";
if ($APPKEY === "你的appkey") {
echo "\n[错误] 请先在脚本顶部的配置区域填写你的 APPKEY\n";
exit(1);
}
if ($GT === "你获取到的gt值") {
echo "\n[错误] 请先在脚本顶部的配置区域填写 GT 值\n";
exit(1);
}
if ($ITEM_ID === 0) {
echo "\n[错误] 请先在脚本顶部的配置区域填写 ITEM_ID(项目类型)\n";
exit(1);
}
try {
// ========== 步骤1:提交极验识别任务 ==========
echo str_repeat("=", 50) . "\n";
echo "[提交任务] 正在提交极验识别任务...\n";
echo str_repeat("=", 50) . "\n";
$postData = [
"appkey" => $APPKEY,
"gt" => $GT,
"itemid" => $ITEM_ID,
];
if (!empty($CHALLENGE)) { $postData["challenge"] = $CHALLENGE; }
if (!empty($REFERER)) { $postData["referer"] = $REFERER; }
if (!empty($PROXY)) { $postData["proxy"] = $PROXY; }
if (!empty($DEVKEY)) { $postData["devkey"] = $DEVKEY; }
if (!empty($SDK)) { $postData["sdk"] = $SDK; }
if (!empty($GIVEN)) { $postData["given"] = $GIVEN; }
if (!empty($HOST_PARAM)) { $postData["host"] = $HOST_PARAM; }
if (!empty($USER_AGENT)) { $postData["userAgent"] = $USER_AGENT; }
echo "[请求参数] gt=" . $GT . "\n";
echo "[请求参数] itemid=" . $ITEM_ID . "\n";
$submitResult = httpPost($API_BASE . "/recognize", $postData);
echo "[提交响应] " . json_encode($submitResult, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) . "\n";
if (!isset($submitResult["status"]) || $submitResult["status"] != 1 || !isset($submitResult["resultid"])) {
echo "[失败] 任务提交失败,错误信息:" . ($submitResult["msg"] ?? "未知") . "\n";
exit(1);
}
$resultid = $submitResult["resultid"];
echo "[成功] 任务提交成功!resultid=" . $resultid . "\n";
// ========== 步骤2:轮询查询识别结果 ==========
echo "\n" . str_repeat("=", 50) . "\n";
echo "[查询结果] 正在轮询识别结果...\n";
echo "[查询结果] 轮询间隔:" . $POLL_INTERVAL . "秒,最大等待:" . $MAX_POLL_TIME . "秒\n";
echo str_repeat("=", 50) . "\n";
$startTime = time();
while (true) {
$elapsed = time() - $startTime;
if ($elapsed > $MAX_POLL_TIME) {
echo "[超时] 已等待" . $MAX_POLL_TIME . "秒,识别超时,请稍后重试\n";
break;
}
sleep($POLL_INTERVAL);
$queryResult = httpPost($API_BASE . "/results", [
"appkey" => $APPKEY,
"resultid" => $resultid
]);
$elapsed = time() - $startTime;
if (isset($queryResult["status"]) && $queryResult["status"] == 1) {
echo "\n[成功] 识别成功!耗时:" . ($queryResult["time"] ?? "未知") . "ms\n";
echo "[识别结果] " . json_encode($queryResult["data"] ?? [], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) . "\n";
echo "\n[完整响应] " . json_encode($queryResult, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) . "\n";
break;
} else {
echo "[等待中] 第" . $elapsed . "秒 - " . ($queryResult["msg"] ?? "正在识别中...") . "\n";
}
}
} catch (Exception $e) {
echo "[异常] " . $e->getMessage() . "\n";
}
echo "\n" . str_repeat("=", 50) . "\n";
echo "[完成] 识别执行完毕\n";
echo str_repeat("=", 50) . "\n";
?>