
Rajinder Singh
Deep Learning Researcher

GeeTest V3 是网络上部署最广泛的行为验证码之一。与简单的复选框挑战不同,GeeTest V3 使用交互式谜题——滑动验证、图标选择和单词匹配——来区分人类和机器人。它常见于登录页面、注册表单以及亚洲乃至全球范围内的数据密集型网站。
如果您可以在 n8n 工作流中自动解决 GeeTest V3——无论是构建可重用的解决器 API、抓取受验证码保护的网站,还是自动化登录表单——所有这些都无需编写一行传统代码,那会怎么样?
在本指南中,您将学习如何将 n8n(一个可视化工作流自动化工具)与 CapSolver(一个由 AI 驱动的验证码解决服务)结合起来,按需解决 GeeTest V3 挑战——无论是作为独立的 API 端点还是作为更大自动化工作流中的一个步骤。
您将构建什么:
解决器 API——一个可重用的端点,您的其他工具可以调用:
直接使用工作流——CapSolver 作为更大自动化中的一个步骤嵌入:
GeeTest V3 是一个挑战-响应式验证码系统,通过交互式任务验证用户。与 reCAPTCHA(使用单个令牌)或 Cloudflare Turnstile(隐形运行)不同,GeeTest V3 呈现需要用户交互的可见谜题:
从解决的角度来看,GeeTest V3 有两个关键参数:
gt——一个按站点标识符(类似于站点密钥)。这是静态的——它在会话之间不会改变。challenge——一个按会话令牌。这是动态的——它每次都会改变,并在大约 60-120 秒内过期。这个动态的 challenge 参数是与其他验证码类型的主要区别。每个解决 GeeTest V3 的工作流都需要一个额外步骤,在将其发送到 CapSolver 之前获取一个新的挑战。
解决方案格式:与 reCAPTCHA 或 Turnstile 返回单个令牌不同,GeeTest V3 返回三个独立的值:
challenge——已解决的挑战字符串validate——验证哈希seccode——安全码这些作为三个表单字段提交:geetest_challenge、geetest_validate 和 geetest_seccode。

GeeTest V3 与 V4: GeeTest V4 使用不同的 API 结构(
captcha_id而不是gt,没有单独的challenge获取)。本指南专门介绍 V3。如果您在页面源代码中看到captcha_id,则表示您正在处理 V4。
在开始之前,请确保您具备以下条件:
重要提示: 确保您的 CapSolver 账户中有足够的余额。GeeTest V3 解决任务会根据使用情况消耗积分。
CapSolver 作为 n8n 中的官方集成提供——无需安装社区节点。您可以在构建工作流时直接在节点面板中找到它。
由于它是官方集成,您需要在 n8n 中创建凭据,以便 CapSolver 节点可以使用您的账户进行身份验证。
转到您的 n8n 实例并导航到 Settings -> Credentials。您将在此处看到所有已配置的凭据。

All(默认)n8n 将自动测试连接。您应该会看到一个绿色的**“Connection tested successfully”**横幅,确认您的 API 密钥有效。

重要提示: 您的工作流中的每个 CapSolver 节点都将引用此凭据。您只需创建一次——所有解决器工作流都将共享相同的凭据。
现在您已准备好构建您的 GeeTest V3 解决器工作流!
在解决 GeeTest V3 挑战之前,您需要找到三件事:gt 参数、挑战 API 端点,并了解 challenge 值是如何动态获取的。
F12)-> 网络选项卡gt= 或响应中包含 "gt" 和 "challenge" 字段的请求/api/geetest/register/gt/register-slide/captcha?gt=...{
"gt": "81dc9bdb52d04dc20036dbd8313ed055",
"challenge": "4a8a08f09d37b73795649038408b5f33ab",
"success": 1,
"new_captcha": true
}
这是 GeeTest V3 自动化最重要的概念:
gt 值在每个站点是静态的——它在会话之间保持不变challenge 值是动态的——它每次都会改变,并在约 60-120 秒内过期challengehttps://example.com/api/geetest/register)这意味着每个 GeeTest V3 工作流在 CapSolver 节点之前都需要一个额外的 HTTP 请求节点来获取新的挑战。这是与 reCAPTCHA 或 Turnstile 工作流的关键结构差异。
提示: 在挑战 API URL 中添加
?t={{ Date.now() }}作为缓存清除参数,以确保您始终获得新的挑战。
有关识别验证码参数的详细指南,请查看 CapSolver 官方文档。
此工作流创建一个 POST 端点,接受 GeeTest V3 参数并返回已解决的挑战。与 reCAPTCHA 或 Turnstile 解决器不同,调用者必须提供 challenge 值(新获取的)以及 gt 和 websiteURL。

工作流由四个节点组成:
$json.error 不为空)进行分支{"error": "..."}| 设置 | 值 |
|---|---|
| HTTP 方法 | POST |
| 路径 | solver-geetest-v3 |
| 响应 | Response Node |
这将在以下位置创建端点:https://your-n8n-instance.com/webhook/solver-geetest-v3
| 参数 | 值 | 描述 |
|---|---|---|
| 操作 | GeeTest V3 |
必须设置为 GeeTest V3 |
| 类型 | GeeTestTaskProxyLess |
唯一可用选项——无代理变体 |
| 网站 URL | ={{ $json.body.websiteURL }} |
带有 GeeTest 挑战的页面的 URL |
| GT | ={{ $json.body.gt }} |
每个站点的 GeeTest 标识符 |
| 挑战 | ={{ $json.body.challenge }} |
动态的每个会话挑战(必须是新的) |
| GeeTest API 服务器子域 | (可选) | 如果站点使用自定义 GeeTest API 服务器 |
还要在节点中选择您的 CapSolver 凭据。
| 设置 | 值 |
|---|---|
| 条件 | ={{ $json.error }} 不为空 |
| 真分支 | 路由到错误响应 Webhook 节点 |
| 假分支 | 路由到成功响应 Webhook 节点 |
这使得画布上的错误路径明确。CapSolver 节点在错误时继续(onError: continueRegularOutput),因此失败会以 { "error": "..." } 的形式到达此处,而不是使工作流崩溃。
成功分支(CapSolver 错误?的假输出):
| 设置 | 值 |
|---|---|
| 响应方式 | JSON |
| 响应正文 | ={{ JSON.stringify($json.data) }} |
向您的 webhook 端点发送 POST 请求:
curl -X POST https://your-n8n-instance.com/webhook/solver-geetest-v3 \
-H "Content-Type: application/json" \
-d '{
"websiteURL": "https://example.com/login",
"gt": "81dc9bdb52d04dc20036dbd8313ed055",
"challenge": "4a8a08f09d37b73795649038408b5f33ab"
}'
预期响应:
{
"taskId": "abc123...",
"solution": {
"challenge": "4a8a08f09d37b73795649038408b5f33",
"validate": "68f0c05d0c8a8b2b1e2f3a4b5c6d7e8f",
"seccode": "68f0c05d0c8a8b2b1e2f3a4b5c6d7e8f|jordan"
},
"status": "ready"
}
重要提示: 请求正文中的
challenge必须是新获取的。如果您发送过期的挑战,CapSolver 将无法解决它。挑战通常在 60-120 秒内过期。
复制以下 JSON 并通过 Menu -> Import from JSON 导入到 n8n 中:
{
"name": "GeeTest V3 Scraping — Price & Product Details — CapSolver + Schedule + Webhook",
"nodes": [
{
"parameters": {
"content": "## GeeTest V3 抓取 — 价格和产品监控\n\n**适用对象:** 在受 GeeTest V3 保护的网站上监控价格或产品数据的团队。\n\n**功能:** 解决 GeeTest V3,获取产品页面,通过 CSS 选择器提取价格和名称,与存储值进行比较,并在发生变化时发出警报。\n\n**工作原理:**\n1. 计划(每 6 小时)或 Webhook 触发流程\n2. CapSolver 解决 GeeTest V3 挑战\n3. HTTP 请求使用已解决的令牌获取产品页面\n4. HTML 节点提取价格和产品名称\n5. 代码节点比较当前价格与存储价格 → 在发生变化时发出警报\n\n**设置:**\n1. 在 **Settings → Credentials** 下添加您的 CapSolver API 密钥\n2. 替换占位符 URL 和站点密钥\n3. 更新提取数据中的 CSS 选择器以匹配您的目标页面\n4. 将构建警报输出连接到您的通知渠道",
"height": 560,
"width": 460,
"color": 1
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-1220,
-380
],
"id": "sticky-blog-main-1773678228108-1",
"name": "Sticky Note"
},
{
"parameters": {
"content": "### 计划路径\n每 6 小时自动运行。\n结果存储在工作流静态数据中,用于跨执行比较。",
"height": 480,
"width": 2200,
"color": 6
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-740,
-280
],
"id": "sticky-blog-section-1773678228108-2",
"name": "Sticky Note1"
},
{
"parameters": {
"content": "### Webhook 路径\n按需触发 — 相同逻辑,将结果作为 JSON 响应返回。",
"height": 480,
"width": 2200,
"color": 6
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-740,
140
],
"id": "sticky-blog-section-1773678228108-3",
"name": "Sticky Note2"
},
{
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 6
}
]
}
},
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.3,
"position": [
-700,
0
],
"id": "88888888-8888-8888-8888-888888888801",
"name": "Every 6 Hours"
},
{
"parameters": {
"url": "https://YOUR-TARGET-SITE.com/api/geetest/register?t={{ Date.now() }}",
"options": {
"response": {
"response": {
"fullResponse": false
}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
-400,
0
],
"id": "88888888-8888-8888-8888-888888888802",
"name": "Fetch GeeTest Challenge"
},
{
"parameters": {
"operation": "GeeTest V3",
"websiteURL": "https://YOUR-TARGET-SITE.com/product-page",
"gt": "={{ $json.gt }}",
"challenge": "={{ $json.challenge }}",
"optional": {}
},
"type": "n8n-nodes-capsolver.capSolver",
"typeVersion": 1,
"position": [
-96,
0
],
"id": "88888888-8888-8888-8888-888888888803",
"name": "Solve GeeTest V3",
"credentials": {
"capSolverApi": {
"id": "YOUR_CREDENTIAL_ID",
"name": "CapSolver account"
}
}
},
{
"parameters": {
"method": "POST",
"url": "https://YOUR-TARGET-SITE.com/product-page",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "user-agent",
"value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
},
{
"name": "content-type",
"value": "application/x-www-form-urlencoded"
}
]
},
"sendBody": true,
"contentType": "form-urlencoded",
"bodyParameters": {
"parameters": [
{
"name": "geetest_challenge",
"value": "={{ $(\'Solve GeeTest V3\').item.json.data.solution.challenge }}"
},
{
"name": "geetest_validate",
"value": "={{ $(\'Solve GeeTest V3\').item.json.data.solution.validate }}"
},
{
"name": "geetest_seccode",
"value": "={{ $(\'Solve GeeTest V3\').item.json.data.solution.seccode }}"
}
]
},
"options": {
"response": {
"response": {
"fullResponse": false
}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
208,
0
],
"id": "88888888-8888-8888-8888-888888888804",
"name": "Fetch Product Page"
},
{
"parameters": {
"operation": "extractHtmlContent",
"extractionValues": {
"values": [
{
"key": "price",
"cssSelector": ".product-price, [data-price], .price",
"returnValue": "text",
"returnArray": false
},
{
"key": "productName",
"cssSelector": "h1, .product-title",
"returnValue": "text",
"returnArray": false
}
]
},
"options": {}
},
"type": "n8n-nodes-base.html",
"typeVersion": 1.2,
"position": [
512,
0
],
"id": "88888888-8888-8888-8888-888888888805",
"name": "Extract Data"
},
{
"parameters": {
"jsCode": "// Get current and previous price from workflow static data\nconst staticData = $workflow.staticData;\nconst currentPrice = $input.first().json.price;\nconst previousPrice = staticData.lastPrice;\nconst productName = $input.first().json.productName || \'Product\';\n\n// Parse numeric values for comparison\nconst parsePrice = (str) => {\n if (!str) return null;\n const match = str.match(/[\\d,]+\\.?\\d*/);\n return match ? parseFloat(match[0].replace(\\'\\', \'\')) : null;\n};\n\nconst currentNum = parsePrice(currentPrice);\nconst previousNum = parsePrice(previousPrice);\n\n// Update stored price\nstaticData.lastPrice = currentPrice;\nstaticData.lastChecked = new Date().toISOString();\n\nconst changed = previousNum !== null && currentNum !== null && currentNum !== previousNum;\nconst direction = changed ? (currentNum < previousNum ? \'dropped\' : \'increased\') : \'unchanged\';\nconst diff = changed ? Math.abs(currentNum - previousNum).toFixed(2) : \'0\';\n\nreturn [{\n json: {\n productName,\n currentPrice,\n previousPrice: previousPrice || \'first check\',\n changed,\n direction,\n diff: changed ? `\\$${diff}` : null,\n checkedAt: new Date().toISOString()\n }\n}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
800,
0
],
"id": "88888888-8888-8888-8888-888888888806",
"name": "Compare Data"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "price-if-001",
"leftValue": "={{ $json.changed }}",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
1104,
0
],
"id": "88888888-8888-8888-8888-888888888807",
"name": "Data Changed?"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "alert-001",
"name": "alert",
"value": "=Price {{ $json.direction }} for {{ $json.productName }}: {{ $json.previousPrice }} → {{ $json.currentPrice }} ({{ $json.direction === \'dropped\' ? \'-\' : \'+\' }}{{ $json.diff }})",
"type": "string"
},
{
"id": "alert-002",
"name": "severity",
"value": "={{ $json.direction === \'dropped\' ? \'deal\' : \'info\' }}",
"type": "string"
},
{
"id": "alert-003",
"name": "checkedAt",
"value": "={{ $json.checkedAt }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1408,
-80
],
"id": "88888888-8888-8888-8888-888888888808",
"name": "Build Alert"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "nc-001",
"name": "status",
"value": "no_change",
"type": "string"
},
{
"id": "nc-002",
"name": "currentPrice",
"value": "={{ $json.currentPrice }}",
"type": "string"
},
{
"id": "nc-003",
"name": "checkedAt",
"value": "={{ $json.checkedAt }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1408,
128
],
"id": "88888888-8888-8888-8888-888888888809",
"name": "No Change"
},
{
"parameters": {
"httpMethod": "POST",
"path": "price-monitor-geetest-v3",
"responseMode": "responseNode",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2.1,
"position": [
-700,
420
],
"id": "88888888-8888-8888-8888-888888888810",
"name": "Webhook Trigger",
"webhookId": "88888888-aaaa-bbbb-cccc-888888888810",
"onError": "continueRegularOutput"
},
{
"parameters": {
"url": "https://YOUR-TARGET-SITE.com/api/geetest/register?t={{ Date.now() }}",
"options": {
"response": {
"response": {
"fullResponse": false
}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
-400,
420
],
"id": "88888888-8888-8888-8888-888888888811",
"name": "Fetch GeeTest Challenge [Webhook]"
},
{
"parameters": {
"operation": "GeeTest V3",
"websiteURL": "https://YOUR-TARGET-SITE.com/product-page",
"gt": "={{ $json.gt }}",
"challenge": "={{ $json.challenge }}",
"optional": {}
},
"type": "n8n-nodes-capsolver.capSolver",
"typeVersion": 1,
"position": [
-96,
420
],
"id": "88888888-8888-8888-8888-888888888812",
"name": "Solve GeeTest V3 [Webhook]",
"credentials": {
"capSolverApi": {
"id": "YOUR_CREDENTIAL_ID",
"name": "CapSolver account"
}
}
},
{
"parameters": {
"method": "POST",
"url": "https://YOUR-TARGET-SITE.com/product-page",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "user-agent",
"value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
},
{
"name": "content-type",
"value": "application/x-www-form-urlencoded"
}
]
},
"sendBody": true,
"contentType": "form-urlencoded",
"bodyParameters": {
"parameters": [
{
"name": "geetest_challenge",
"value": "={{ $(\'Solve GeeTest V3 [Webhook]\').item.json.data.solution.challenge }}"
},
{
"name": "geetest_validate",
"value": "={{ $(\'Solve GeeTest V3 [Webhook]\').item.json.data.solution.validate }}"
},
{
"name": "geetest_seccode",
"value": "={{ $(\'Solve GeeTest V3 [Webhook]\').item.json.data.solution.seccode }}"
}
]
},
"options": {
"response": {
"response": {
"fullResponse": false
}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
208,
420
],
"id": "88888888-8888-8888-8888-888888888813",
"name": "Fetch Product Page [Webhook]"
},
{
"parameters": {
"operation": "extractHtmlContent",
"sourceData": "json",
"dataPropertyName": "data",
"extractionValues": {
"values": [
{
"key": "price",
"cssSelector": ".product-price, [data-price], .price",
"returnValue": "text",
"returnArray": false
},
{
"key": "productName",
"cssSelector": "h1, .product-title",
"returnValue": "text",
"returnArray": false
}
]
},
"options": {}
},
"type": "n8n-nodes-base.html",
"typeVersion": 1.2,
"position": [
512,
420
],
"id": "88888888-8888-8888-8888-888888888814",
"name": "Extract Data [Webhook]"
},
{
"parameters": {
"jsCode": "// Get current and previous price from workflow static data\nconst staticData = $workflow.staticData;\nconst currentPrice = $input.first().json.price;\nconst previousPrice = staticData.lastPrice;\nconst productName = $input.first().json.productName || \'Product\';\n\n// Parse numeric values for comparison\nconst parsePrice = (str) => {\n if (!str) return null;\n const match = str.match(/[\\d,]+\\.?\\d*/);\n return match ? parseFloat(match[0].replace(\\'\\', \'\')) : null;\n};\n\nconst currentNum = parsePrice(currentPrice);\nconst previousNum = parsePrice(previousPrice);\n\n// Update stored price\nstaticData.lastPrice = currentPrice;\nstaticData.lastChecked = new Date().toISOString();\n\nconst changed = previousNum !== null && currentNum !== null && currentNum !== previousNum;\nconst direction = changed ? (currentNum < previousNum ? \'dropped\' : \'increased\') : \'unchanged\';\nconst diff = changed ? Math.abs(currentNum - previousNum).toFixed(2) : \'0\';\n\nreturn [{\n json: {\n productName,\n currentPrice,\n previousPrice: previousPrice || \'first check\',\n changed,\n direction,\n diff: changed ? `\\$${diff}` : null,\n checkedAt: new Date().toISOString()\n }\n}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
800,
420
],
"id": "88888888-8888-8888-8888-888888888815",
"name": "Compare Data [Webhook]"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "price-if-002",
"leftValue": "={{ $json.changed }}",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
1104,
420
],
"id": "88888888-8888-8888-8888-888888888816",
"name": "Data Changed? [Webhook]"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "alert-004",
"name": "alert",
"value": "=Price {{ $json.direction }} for {{ $json.productName }}: {{ $json.previousPrice }} → {{ $json.currentPrice }} ({{ $json.direction === \'dropped\' ? \'-\' : \'+\' }}{{ $json.diff }})",
"type": "string"
},
{
"id": "alert-005",
"name": "severity",
"value": "={{ $json.direction === \'dropped\' ? \'deal\' : \'info\' }}",
"type": "string"
},
{
"id": "alert-006",
"name": "checkedAt",
"value": "={{ $json.checkedAt }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1408,
340
],
"id": "88888888-8888-8888-8888-888888888817",
"name": "Build Alert [Webhook]"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "nc-004",
"name": "status",
"value": "no_change",
"type": "string"
},
{
"id": "nc-005",
"name": "currentPrice",
"value": "={{ $json.currentPrice }}",
"type": "string"
},
{
"id": "nc-006",
"name": "checkedAt",
"value": "={{ $json.checkedAt }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1408,
548
],
"id": "88888888-8888-8888-8888-888888888818",
"name": "No Change [Webhook]"
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify($json) }}",
"options": {}
},
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.5,
"position": [
1712,
420
],
"id": "88888888-8888-8888-8888-888888888819",
"name": "Respond to Webhook [Webhook]"
}
],
"connections": {
"Every 6 Hours": {
"main": [
[
{
"node": "Fetch GeeTest Challenge",
"type": "main",
"index": 0
}
]
]
},
"Fetch GeeTest Challenge": {
"main": [
[
{
"node": "Solve GeeTest V3",
"type": "main",
"index": 0
}
]
]
},
"Solve GeeTest V3": {
"main": [
[
{
"node": "Fetch Product Page",
"type": "main",
"index": 0
}
]
]
},
"Fetch Product Page": {
"main": [
[
{
"node": "Extract Data",
"type": "main",
"index": 0
}
]
]
},
"Extract Data": {
"main": [
[
{
"node": "Compare Data",
"type": "main",
"index": 0
}
]
]
},
"Compare Data": {
"main": [
[
{
"node": "Data Changed?",
"type": "main",
"index": 0
}
]
]
},
"Data Changed?": {
"main": [
[
{
"node": "Build Alert",
"type": "main",
"index": 0
}
],
[
{
"node": "No Change",
"type": "main",
"index": 0
}
]
]
},
"Webhook Trigger": {
"main": [
[
{
"node": "Fetch GeeTest Challenge [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Fetch GeeTest Challenge [Webhook]": {
"main": [
[
{
"node": "Solve GeeTest V3 [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Solve GeeTest V3 [Webhook]": {
"main": [
[
{
"node": "Fetch Product Page [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Fetch Product Page [Webhook]": {
"main": [
[
{
"node": "Extract Data [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Extract Data [Webhook]": {
"main": [
[
{
"node": "Compare Data [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Compare Data [Webhook]": {
"main": [
[
{
"node": "Data Changed? [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Data Changed? [Webhook]": {
"main": [
[
{
"node": "Build Alert [Webhook]",
"type": "main",
"index": 0
}
],
[
{
"node": "No Change [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Build Alert [Webhook]": {
"main": [
[
{
"node": "Respond to Webhook [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"No Change [Webhook]": {
"main": [
[
{
"node": "Respond to Webhook [Webhook]",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
}
}
此工作流自动化了 GeeTest V3 保护的登录表单的端到端提交。它在提交凭据之前解决 GeeTest V3 挑战。
此工作流由五个节点组成:
challenge 值gt、challenge 和 websiteURL 发送到 CapSolver| 设置 | 值 |
|---|---|
| HTTP 方法 | POST |
| 路径 | login-geetest-v3 |
| 响应 | Response Node |
这将在以下位置创建端点:https://your-n8n-instance.com/webhook/login-geetest-v3
| 设置 | 值 |
|---|---|
| URL | https://YOUR-TARGET-SITE.com/api/geetest/register?t={{ Date.now() }} |
| 选项 | Full Response = false |
这将返回包含 gt 和 challenge 值的 JSON 响应。
| 参数 | 值 |
|---|---|
| 操作 | GeeTest V3 |
| 网站 URL | https://YOUR-TARGET-SITE.com/login |
| GT | ={{ $json.gt }} |
| 挑战 | ={{ $json.challenge }} |
还要选择您的 CapSolver 凭据。
| 设置 | 值 |
|---|---|
| 方法 | POST |
| URL | https://YOUR-TARGET-SITE.com/login |
| 内容类型 | form-urlencoded |
| 正文参数 | username=YOUR_USERNAME,password=YOUR_PASSWORD,geetest_challenge={{ $(\'Solve GeeTest V3\').item.json.data.solution.challenge }},geetest_validate={{ $(\'Solve GeeTest V3\').item.json.data.solution.validate }},geetest_seccode={{ $(\'Solve GeeTest V3\').item.json.data.solution.seccode }} |
重要提示: 确保将
YOUR_USERNAME和YOUR_PASSWORD替换为实际凭据。此外,您可能需要调整表单字段名称以匹配目标站点的 HTML。
| 设置 | 值 |
|---|---|
| 响应方式 | JSON |
| 响应正文 | ={{ JSON.stringify($json) }} |
向您的 webhook 端点发送 POST 请求:
curl -X POST https://your-n8n-instance.com/webhook/login-geetest-v3 \
-H "Content-Type: application/json" \
-d
预期响应(成功):
{
"status": "success",
"message": "Login successful",
"solution": {
"challenge": "...",
"validate": "...",
"seccode": "..."
}
}
预期响应(失败):
{
"status": "failed",
"message": "Login failed: Invalid credentials or captcha",
"error": "..."
}
复制以下 JSON 并通过 Menu -> Import from JSON 导入到 n8n 中:
{
"name": "Account Login Automation — Solve GeeTest V3 & Submit Credentials",
"nodes": [
{
"parameters": {
"content": "## 账户登录自动化 — 解决 GeeTest V3 并提交凭据\n\n**适用对象:** 需要自动化登录受 GeeTest V3 保护的账户的团队。\n\n**功能:** 获取 GeeTest V3 挑战,使用 CapSolver 解决,然后使用已解决的令牌和用户凭据提交登录表单。\n\n**工作原理:**\n1. Webhook 触发流程\n2. HTTP 请求获取新的 GeeTest V3 挑战\n3. CapSolver 解决挑战\n4. HTTP 请求提交登录表单,包含已解决的 GeeTest V3 令牌和用户凭据\n5. Webhook 响应登录结果\n\n**设置:**\n1. 在 **Settings → Credentials** 下添加您的 CapSolver API 密钥\n2. 替换占位符 URL 和凭据\n3. 调整表单字段名称以匹配您的目标站点\n4. 激活工作流",
"height": 480,
"width": 460,
"color": 1
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-1020,
-280
],
"id": "sticky-login-main-1773678228108-1",
"name": "Sticky Note"
},
{
"parameters": {
"httpMethod": "POST",
"path": "login-geetest-v3",
"responseMode": "responseNode",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2.1,
"position": [
-700,
0
],
"id": "99999999-9999-9999-9999-999999999901",
"name": "Webhook Trigger",
"webhookId": "99999999-aaaa-bbbb-cccc-999999999901",
"onError": "continueRegularOutput"
},
{
"parameters": {
"url": "https://YOUR-TARGET-SITE.com/api/geetest/register?t={{ Date.now() }}",
"options": {
"response": {
"response": {
"fullResponse": false
}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
-400,
0
],
"id": "99999999-9999-9999-9999-999999999902",
"name": "Fetch GeeTest Challenge"
},
{
"parameters": {
"operation": "GeeTest V3",
"websiteURL": "https://YOUR-TARGET-SITE.com/login",
"gt": "={{ $json.gt }}",
"challenge": "={{ $json.challenge }}",
"optional": {}
},
"type": "n8n-nodes-capsolver.capSolver",
"typeVersion": 1,
"position": [
-96,
0
],
"id": "99999999-9999-9999-9999-999999999903",
"name": "Solve GeeTest V3",
"credentials": {
"capSolverApi": {
"id": "YOUR_CREDENTIAL_ID",
"name": "CapSolver account"
}
}
},
{
"parameters": {
"method": "POST",
"url": "https://YOUR-TARGET-SITE.com/login",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "user-agent",
"value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
},
{
"name": "content-type",
"value": "application/x-www-form-urlencoded"
}
]
},
"sendBody": true,
"contentType": "form-urlencoded",
"bodyParameters": {
"parameters": [
{
"name": "username",
"value": "YOUR_USERNAME"
},
{
"name": "password",
"value": "YOUR_PASSWORD"
},
{
"name": "geetest_challenge",
"value": "={{ $(\'Solve GeeTest V3\').item.json.data.solution.challenge }}"
},
{
"name": "geetest_validate",
"value": "={{ $(\'Solve GeeTest V3\').item.json.data.solution.validate }}"
},
{
"name": "geetest_seccode",
"value": "={{ $(\'Solve GeeTest V3\').item.json.data.solution.seccode }}"
}
]
},
"options": {
"response": {
"response": {
"fullResponse": false
}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
208,
0
],
"id": "99999999-9999-9999-9999-999999999904",
"name": "Submit Login Form"
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify($json) }}",
"options": {}
},
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.5,
"position": [
512,
0
],
"id": "99999999-9999-9999-9999-999999999905",
"name": "Respond to Webhook"
}
],
"connections": {
"Webhook Trigger": {
"main": [
[
{
"node": "Fetch GeeTest Challenge",
"type": "main",
"index": 0
}
]
]
},
"Fetch GeeTest Challenge": {
"main": [
[
{
"node": "Solve GeeTest V3",
"type": "main",
"index": 0
}
]
]
},
"Solve GeeTest V3": {
"main": [
[
{
"node": "Submit Login Form",
"type": "main",
"index": 0
}
]
]
},
"Submit Login Form": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
}
}
此错误表示您的 CapSolver 账户或计划不包含 GeeTest V3 访问权限。请检查您的 CapSolver 仪表板 以验证您的计划是否包含此服务。
GeeTest V3 challenge 值是动态的,并且会快速过期(通常在 60-120 秒内)。您必须在向 CapSolver 发送解决请求之前立即获取一个新的 challenge。确保您的工作流在每次尝试解决之前都获取了最新的 challenge。
这些错误表示您在 CapSolver 节点中提供的 websiteURL 或 gt 参数不正确。仔细检查目标站点的开发者工具网络选项卡,以确保您正在使用正确的值。
如果 GeeTest V3 成功解决,但登录仍然失败,则可能存在以下问题:
此错误表示您在 n8n 中配置的 CapSolver API 密钥不正确或已过期。请检查您的 CapSolver 仪表板 并更新 n8n 中的凭据。
challenge 值。挑战会快速过期。gt、websiteURL 和 challenge 参数是否正确。这些是 GeeTest V3 解决成功的关键。准备好开始了吗? 注册 CapSolver 并使用奖励代码 n8n 在您的首次充值时获得额外的 8% 奖励!

您已经学习了如何使用 n8n 和 CapSolver 构建 GeeTest V3 解决器 API 和账户登录自动化工作流。
总结:
gt 和动态 challenge 参数。gt 和挑战 API 端点。challenge 值。GeeTest V3 的主要复杂性在于其动态的 challenge 参数和三部分解决方案格式。通过在 CapSolver 节点之前添加一个 HTTP 请求节点来获取新的挑战,您可以有效地自动化 GeeTest V3 解决。然后,您可以将这些已解决的令牌无缝集成到您的登录或抓取工作流中。
提示: 这些工作流使用 Webhook 触发器,但您可以将触发器节点替换为任何其他 n8n 触发器——手动、应用程序事件、表单提交等。一旦 GeeTest V3 解决,使用 n8n 的内置节点将结果保存到 Google 表格、数据库、云存储或通过 Telegram/Slack/电子邮件发送警报。
GeeTest V3 是一种行为验证码系统,通过交互式谜题(如滑动拼图、图标点击和单词匹配)来验证用户。它使用一个静态的 gt 参数和一个动态的 challenge 参数,该参数会快速过期。
GeeTest V4 使用不同的 API 结构,例如 captcha_id 而不是 gt,并且不需要单独获取 challenge。本指南专门针对 GeeTest V3。如果您在页面源代码中看到 captcha_id,则表示您正在处理 V4。
价格因使用情况而异。请查看 CapSolver 定价页面 以了解 GeeTest V3 的当前价格。GeeTest V3 解决任务通常比简单的图像到文本识别更昂贵,但比某些其他复杂的验证码类型更便宜。
GeeTest V3 解决任务通常需要 10-30 秒,具体取决于挑战的复杂性和 CapSolver 服务器的负载。与 ImageToTextTask 不同,GeeTest V3 解决涉及任务创建和轮询,因此它不是即时返回的。
CapSolver 的 GeeTest V3 解决服务通常不需要您提供代理。CapSolver 会在内部处理代理需求。您只需提供 websiteURL、gt 和 challenge 参数。
challenge 值总是过期?GeeTest V3 challenge 值是动态的,并且会快速过期(通常在 60-120 秒内)。您必须在向 CapSolver 发送解决请求之前立即获取一个新的 challenge。确保您的工作流在每次尝试解决之前都包含一个 HTTP 请求节点来获取最新的 challenge。
如果 GeeTest V3 解决成功但登录仍然失败,请检查以下几点:
是的。此工作流适用于自托管 n8n 和 n8n Cloud。CapSolver 节点已作为官方集成提供——只需添加您的 API 凭据即可。