如何使用CapSolver解决n8n中的TLS指纹问题

Emma Foster
Machine Learning Engineer
18-Mar-2026

如果你曾经尝试过抓取受企业级反机器人检测保护的网站,你可能遇到了一个看不见的障碍:即使你的请求头、Cookie和User-Agent都完美无缺,请求仍会被阻止。原因在于TLS指纹识别——它发生在你的HTTP请求发送之前。
像Cloudflare、Akamai、DataDome等反机器人服务会检查原始的TLS握手,以确定客户端是真实浏览器还是自动化工具。标准HTTP客户端——Go的net/http、Python的requests、curl、Node.js的axios——都有独特的TLS指纹,会立即被标记。
在本指南中,你将使用**httpcloak构建一个轻量级的Go服务器**,模拟真实的Chrome TLS指纹,并将其连接到你的n8n工作流,使每条HTTP请求在网络安全层面看起来都像真实的Chrome浏览器流量。
什么是TLS指纹识别?
每次客户端通过HTTPS连接到网站时,它会通过发送一个ClientHello消息启动TLS握手。此消息包含:
- 密码套件——客户端支持的加密算法及其顺序
- TLS扩展——如SNI、ALPN、支持的组、签名算法等特性
- 椭圆曲线和点格式——加密参数
- TLS版本——客户端支持的最大TLS版本
反机器人服务会提取这些值并计算一个指纹——称为JA3或JA4指纹——该指纹唯一标识客户端软件。每个浏览器、HTTP库和编程语言运行时都会产生不同的指纹。
| 客户端 | JA3指纹 | 被识别为 |
|---|---|---|
| Chrome 145 | 与Chrome的密码套件顺序匹配的唯一哈希 | 真实浏览器 |
| Firefox 130 | 不同的哈希——Firefox使用不同的密码套件偏好 | 真实浏览器 |
Go net/http |
完全不同的哈希——Go的TLS栈显而易见 | 机器人/自动化工具 |
Python requests |
另一个独特的哈希——Python的urllib3 TLS可被识别 |
机器人/自动化工具 |
| curl | 又一个不同的哈希——curl的TLS指纹广为人知 | 机器人/自动化工具 |
Node.js axios |
Node.js的TLS指纹——很容易被标记 | 机器人/自动化工具 |
关键洞察:TLS指纹识别发生在握手期间,在任何HTTP头发送之前。 无论你如何修改请求头,都无法修复非浏览器的TLS指纹。
为什么标准HTTP客户端会失败?
当浏览器通过HTTPS连接到网站时,它会发送一个包含其支持的密码套件、扩展和设置的TLS ClientHello。反机器人服务会记录此指纹(称为JA3或JA4指纹),并将其与已知的浏览器配置文件进行比较。
Go的net/http、Python的requests、curl和大多数HTTP库都有独特的TLS指纹。即使Cookie和头信息正确,如果反机器人系统检测到非浏览器的TLS指纹,也会阻止请求。
以下是逐步发生的过程:
- 你的n8n工作流向受保护的网站发送HTTP请求
- TLS握手开始——你的客户端发送其
ClientHello - 反机器人服务从握手中记录JA3/JA4指纹
- 指纹匹配Go/Python/Node.js——而不是Chrome或Firefox
- 请求被阻止、挑战或返回一个假页面——在你的头信息被评估之前
这就是为什么设置User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...没有帮助的原因。User-Agent是HTTP层的头信息。TLS指纹识别发生在更低的层级。如果你的User-Agent显示Chrome,但你的TLS指纹显示Go,请求会立即被标记。
哪些人使用TLS指纹识别?
TLS指纹识别已成为企业级反机器人保护的标准实践。以下是检查TLS指纹的主要服务:
| 反机器人服务 | TLS检查 | 说明 |
|---|---|---|
| Cloudflare Bot Management | 是 | 全页面“验证你的浏览器...”挑战。对每条请求检查JA3/JA4 |
| Akamai Bot Manager | 是 | 使用TLS指纹作为机器人评分的多个信号之一 |
| DataDome | 是 | 在分析TLS指纹的同时结合行为信号 |
| 许多其他服务 | 各不相同 | TLS指纹识别正在成为企业级反机器人保护的标准 |
CapSolver 支持解决这些服务中的许多挑战。本指南中的TLS服务器设计用于与任何验证码解决工作流配合使用,当最终HTTP获取需要看起来像真实浏览器时——无论你是绕过Cloudflare挑战、Akamai、DataDome还是其他反机器人系统。
前提条件
| 要求 | 说明 |
|---|---|
| n8n自托管 | 必需——TLS服务器必须与n8n运行在同一台机器上。n8n Cloud不适用。 |
| Go 1.21+ | 必须安装在服务器上。通过go version检查。 |
| 进程管理器 (推荐) | 任何进程管理器(systemd、supervisor、Docker、PM2)以在重启后保持TLS服务器运行 |
步骤1 —— 构建TLS服务器
TLS服务器是一个轻量级的Go HTTP服务器,监听端口7878,并通过httpcloak的Chrome-145 TLS预设转发请求。
创建源文件
bash
mkdir -p ~/tls-server && cd ~/tls-server
创建一个名为main.go的文件,内容如下:
go
package main
import (
"context"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"strings"
"time"
"github.com/sardanioss/httpcloak/client"
)
type FetchRequest struct {
URL string `json:"url"`
Method string `json:"method"`
Headers map[string]string `json:"headers"`
Proxy string `json:"proxy"`
Body string `json:"body"`
}
type FetchResponse struct {
Status int `json:"status"`
Body string `json:"body"`
Headers map[string][]string `json:"headers"`
}
type ErrorResponse struct {
Error string `json:"error"`
}
func writeError(w http.ResponseWriter, status int, msg string) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(status)
json.NewEncoder(w).Encode(ErrorResponse{Error: msg})
}
func fetchHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
writeError(w, http.StatusMethodNotAllowed, "only POST allowed")
return
}
var req FetchRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
writeError(w, http.StatusBadRequest, "invalid JSON: "+err.Error())
return
}
if req.URL == "" {
writeError(w, http.StatusBadRequest, "url is required")
return
}
if req.Method == "" {
req.Method = "GET"
}
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()
c := client.NewClient("chrome-145", client.WithTimeout(60*time.Second))
defer c.Close()
if req.Proxy != "" {
c.SetProxy(req.Proxy)
}
headers := make(map[string][]string, len(req.Headers))
var userAgent string
for k, v := range req.Headers {
lower := strings.ToLower(k)
if lower == "user-agent" {
userAgent = v
} else {
headers[k] = []string{v}
}
}
var bodyReader io.Reader
if req.Body != "" {
bodyReader = strings.NewReader(req.Body)
}
hcReq := &client.Request{
Method: strings.ToUpper(req.Method),
URL: req.URL,
Headers: headers,
Body: bodyReader,
UserAgent: userAgent,
FetchMode: client.FetchModeNavigate,
}
resp, err := c.Do(ctx, hcReq)
if err != nil {
writeError(w, http.StatusBadGateway, "fetch failed: "+err.Error())
return
}
body, err := resp.Text()
if err != nil {
writeError(w, http.StatusInternalServerError, "read body failed: "+err.Error())
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(FetchResponse{
Status: resp.StatusCode,
Body: body,
Headers: resp.Headers,
})
}
func main() {
const port = "7878"
mux := http.NewServeMux()
mux.HandleFunc("/fetch", fetchHandler)
mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
fmt.Fprint(w, `{"status":"ok"}`)
})
log.Printf("TLS server (httpcloak chrome-145) listening on :%s", port)
log.Fatal(http.ListenAndServe(":"+port, mux))
}
初始化并构建
bash
go mod init tls-server
go get github.com/sardanioss/httpcloak/client
go build -o main main.go
运行服务器
bash
./main
服务器在前台运行。要使其在后台运行,请使用任何进程管理器(systemd、supervisor、Docker等)或在screen/tmux会话中运行。
验证是否运行(在新终端中)
bash
curl http://localhost:7878/health
预期结果:{"status":"ok"}
注意: TLS服务器必须运行在与你的n8n实例同一台机器上。n8n工作流会通过
http://localhost:7878/fetch调用它。
步骤2 —— 允许n8n调用本地主机
默认情况下,n8n会阻止HTTP请求节点调用本地主机地址(SSRF保护)。你需要禁用此功能,以便你的工作流可以访问localhost:7878上的TLS服务器。
添加环境变量N8N_BLOCK_ACCESS_TO_LOCALHOST=false并重启你的n8n实例。如何操作取决于你运行n8n的方式:
如果你直接运行n8n:
bash
export N8N_BLOCK_ACCESS_TO_LOCALHOST=false
n8n start
如果你使用Docker:
在docker run命令中添加-e N8N_BLOCK_ACCESS_TO_LOCALHOST=false,或在docker-compose.yml的environment部分添加它。
步骤3 —— 从n8n使用TLS服务器
TLS服务器提供了一个单一端点,接受任何HTTP请求并使用Chrome TLS指纹转发它。
API参考
端点: POST http://localhost:7878/fetch
请求体(JSON):
json
{
"url": "https://example.com",
"method": "GET",
"headers": {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36",
"cookie": "cf_clearance=abc123; session=xyz"
},
"proxy": "http://user:pass@host:port",
"body": ""
}
| 字段 | 类型 | 是否必需 | 说明 |
|---|---|---|---|
url |
字符串 | 是 | 要获取的目标URL |
method |
字符串 | 否 | HTTP方法——默认为GET |
headers |
对象 | 否 | 要发送的HTTP头的键值对 |
proxy |
字符串 | 否 | http://user:pass@host:port格式的代理URL |
body |
字符串 | 否 | 请求体(用于POST/PUT请求) |
响应(JSON):
json
{
"status": 200,
"body": "<html>...</html>",
"headers": { "content-type": ["text/html"], "..." : ["..."] }
}
配置n8n HTTP请求节点
要在n8n工作流中调用TLS服务器,请使用以下设置的HTTP请求节点:
| 参数 | 值 | 说明 |
|---|---|---|
| 方法 | POST |
始终向TLS服务器发送POST |
| URL | http://localhost:7878/fetch |
本地TLS服务器端点 |
| 内容类型 | Raw |
不要使用JSON——n8n的JSON模式会错误地序列化 |
| 原始内容类型 | application/json |
告诉TLS服务器正文是JSON |
| 正文 | ={{ JSON.stringify({ url: "...", method: "GET", headers: {...}, proxy: "..." }) }} |
要转发的实际请求 |
重要提示: 在正文中使用
contentType: "json"和JSON.stringify()会导致n8n双重序列化,发送{"": ""}而不是你的数据。始终使用contentType: "raw"和rawContentType: "application/json"。
示例:获取受保护的页面
在HTTP请求节点的正文表达式中:
javascript
={{ JSON.stringify({
url: "https://protected-site.com/data",
method: "GET",
headers: {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36",
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"accept-language": "en-US,en;q=0.9"
},
proxy: "http://user:pass@proxy-host:8080"
}) }}
TLS服务器将使用Chrome-145 TLS指纹转发此请求,目标网站将看到真实的Chrome浏览器连接。
测试它
直接从命令行测试TLS服务器:
bash
curl -X POST http://localhost:7878/fetch \
-H "Content-Type: application/json" \
-d '{
"url": "https://tls-check.example.com",
"method": "GET",
"headers": {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36"
}
}'
你可以通过将服务器指向JA3/JA4指纹检查器来验证你的TLS指纹——结果应与真实Chrome浏览器匹配,而不是Go标准库客户端。
导入此工作流
此工作流创建了一个Webhook端点,通过TLS服务器转发任何请求,使用Chrome TLS指纹。发送一个包含url、method、headers和可选proxy的POST请求——工作流将其传递给localhost:7878/fetch并返回结果。
Webhook (POST /tls-fetch) → 通过TLS服务器获取 → 向Webhook响应
复制以下JSON并使用菜单 → 从JSON导入将其导入n8n。
点击展开工作流JSON
json
{
"name": "TLS Fetch — Chrome Fingerprint Proxy",
"nodes": [
{
"parameters": {
"content": "## TLS Fetch — Chrome Fingerprint Proxy\n\n**谁适用:** 需要带有真实浏览器TLS指纹的HTTP请求的开发者。\n\n**功能:** 通过Go TLS服务器(httpcloak)代理HTTP请求,模拟Chrome的TLS指纹,绕过机器人检测。\n\n**工作原理:**\n1. Webhook接收目标URL和请求详情\n2. 请求通过本地TLS服务器转发,带有Chrome指纹\n3. 响应返回给调用者\n\n**设置:**\n1. 确保TLS服务器(httpcloak)在端口7878上运行\n2. 启用工作流\n3. 向Webhook URL发送POST请求,附上你的请求详情",
"height": 494,
"width": 460,
"color": 1
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-720,
-300
],
"id": "sticky-blog-main-1773678228122-1",
"name": "便签"
},
{
"parameters": {
"httpMethod": "POST",
"path": "tls-fetch",
"responseMode": "responseNode",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2.1,
"position": [
-200,
0
],
"id": "tls00001-0001-0001-0001-000000000001",
"name": "接收求解请求",
"webhookId": "tls00001-aaaa-bbbb-cccc-000000000001"
},
{
"parameters": {
"method": "POST",
"url": "http://localhost:7878/fetch",
"sendBody": true,
"contentType": "raw",
"rawContentType": "application/json",
"body": "={{ JSON.stringify($json.body) }}",
"options": {
"timeout": 60000
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
100,
0
],
"id": "tls00001-0001-0001-0001-000000000002",
"name": "通过 TLS 服务器获取"
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify($json) }}",
"options": {}
},
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.5,
"position": [
400,
0
],
"id": "tls00001-0001-0001-0001-000000000003",
"name": "响应 Webhook"
}
],
"connections": {
"接收求解器请求": {
"main": [
[
{
"node": "通过 TLS 服务器获取",
"type": "main",
"index": 0
}
]
]
},
"通过 TLS 服务器获取": {
"main": [
[
{
"node": "响应 Webhook",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
}
}
结论
您已经设置了一个 TLS 指纹欺骗服务器,使 n8n 的 HTTP 请求在网络安全层看起来像真实的 Chrome 浏览器流量。这对于绕过检查 TLS 指纹的反机器人服务保护的网站至关重要。
此 TLS 服务器可用于绕过:
- Cloudflare Bot Management — 检查 TLS 指纹的全页挑战
- Akamai Bot Manager — 使用 TLS 分析的企业级机器人检测
- DataDome — 行为 + TLS 指纹分析
- PerimeterX / HUMAN — 设备 + TLS 指纹识别
- 许多其他 CapSolver 支持的反机器人服务
httpcloak 库及其 Chrome-145 预设处理 JA3/JA4 指纹欺骗、HTTP/2 SETTINGS 帧、ALPN 协商和头顺序 — 使您的请求在 TLS 层无法与真实 Chrome 浏览器区分。
需要在 TLS 欺骗的同时解决 CAPTCHAs? 请查看 CapSolver — 它直接集成到 n8n 中作为官方节点,支持 Cloudflare 挑战、Turnstile、reCAPTCHA 等多种服务。使用优惠码 n8n 在首次充值时额外获得 8% 的奖励!

常见问题
什么是 TLS 指纹识别?
TLS 指纹识别是一种技术,服务器分析您的 TLS ClientHello 消息的特征 — 包括密码套件、扩展及其顺序 — 以识别发起连接的软件。每个 HTTP 客户端(Chrome、Firefox、curl、Go、Python)都有独特的指纹模式。
为什么不能仅将 User-Agent 头设置为 Chrome?
User-Agent 头是 HTTP 层的属性。TLS 指纹识别发生在更低的层次 — 在发送任何 HTTP 头之前进行 TLS 握手。反机器人服务会同时比较这两层:如果您的 User-Agent 显示 Chrome 但 TLS 指纹显示 Go/Python,则请求会被标记为机器人。
什么是 httpcloak?
httpcloak 是一个 Go 库,用于欺骗真实的浏览器 TLS 配置。它处理 JA3/JA4 指纹匹配、HTTP/2 SETTINGS 帧、ALPN 协商和头顺序。chrome-145 预设使连接与真实 Chrome 145 浏览器无法区分。
可以使用其他 Chrome 版本预设吗?
可以。httpcloak 支持多个浏览器预设。请查看 httpcloak 文档 以获取可用预设。要更改预设,请将 client.NewClient("chrome-145", ...) 修改为 main.go 中的所需浏览器配置。
这与 n8n Cloud 兼容吗?
不太容易。TLS 服务器是一个本地 Go 二进制文件,必须与 n8n 在同一台机器上运行,以便工作流可以调用 http://localhost:7878/fetch。n8n Cloud 不允许在工作流旁边运行本地服务。您需要自托管的 n8n 实例。
可以在其他机器上运行 TLS 服务器吗?
可以,但需要将 n8n HTTP 请求节点中的 URL 从 http://localhost:7878/fetch 更改为 http://your-server-ip:7878/fetch,并确保端口 7878 可访问。您还需要禁用 n8n 的 SSRF 保护或白名单服务器的 IP。
如何在新版本发布时更新 Chrome 预设?
更新 httpcloak 依赖项:go get -u github.com/sardanioss/httpcloak/client,将 main.go 中的预设字符串更改为新版本,使用 go build -o main main.go 重新构建,并重启服务器。
TLS 服务器支持并发请求吗?
支持。Go 的 HTTP 服务器原生处理并发请求。每个请求都会创建一个新的 httpcloak 客户端实例和自己的 TLS 连接。对于高负载工作,需监控内存使用情况,因为每个连接都会维护自己的 TLS 状态。
性能开销是多少?
TLS 服务器添加的延迟很小 — 通常本地代理跳转需要 10-50ms。大部分请求时间花费在实际的 HTTPS 连接到目标上。Chrome TLS 握手比 Go 的默认设置稍重,但在实践中可以忽略。
如何在服务器重启后保持 TLS 服务器运行?
使用任何进程管理器 — systemd、supervisor、Docker 或类似工具 — 将 TLS 服务器注册为开机启动的服务。快速设置的话,也可以在 screen 或 tmux 会话中运行它。
合规声明: 本博客提供的信息仅供参考。CapSolver 致力于遵守所有适用的法律和法规。严禁以非法、欺诈或滥用活动使用 CapSolver 网络,任何此类行为将受到调查。我们的验证码解决方案在确保 100% 合规的同时,帮助解决公共数据爬取过程中的验证码难题。我们鼓励负责任地使用我们的服务。如需更多信息,请访问我们的服务条款和隐私政策。
更多

如何在 n8n 中使用 CapSolver:解决工作流程中的 CAPTCHA 的完整指南
学习如何将CapSolver与n8n集成,以轻松解决CAPTCHAs并构建可靠的自动化工作流。

Emma Foster
18-Mar-2026

如何使用CapSolver解决n8n中的TLS指纹问题
使用 CapSolver 解决 n8n 中的 TLS 指纹识别问题。让请求看起来像真实的浏览器,并避免被机器人检测拦截。

Emma Foster
18-Mar-2026

如何在n8n中使用CapSolver解决视觉谜题
使用 CapSolver Vision Engine 在 n8n 中解决视觉验证码。立即处理滑块、旋转、对象选择和 GIF 文字识别。

Emma Foster
18-Mar-2026

如何使用 CapSolver 和 n8n 解决 Cloudflare Turnstile
使用CapSolver和n8n构建一个Cloudflare Turnstile求解API。学习如何自动化解决令牌,将其提交到网站,并无需编码即可提取受保护的数据。

Adélia Cruz
10-Mar-2026

