sardanioss/httpcloak
GitHub: sardanioss/httpcloak
一款 Go 实现的浏览器指纹模仿 HTTP 客户端,通过模拟 Chrome/Firefox/Safari 的 TLS 与 HTTP 特征来绕过机器人检测。
Stars: 940 | Forks: 68
Every Byte of your Request Indistinguishable from Chrome.
## 问题
机器人检测不再只检查你的 User-Agent。
它会指纹识别你的 **TLS 握手**。你的 **HTTP/2 帧**。你的 **QUIC 参数**。请求头的顺序。你的 SNI 是否加密。
一点不匹配 = 被拦截。
## 解决方案
```
import httpcloak
r = httpcloak.get("https://target.com", preset="chrome-latest")
```
仅此而已。完整的浏览器传输层指纹。
## 模拟的内容
|
### 🔐 TLS 层
- JA3 / JA4 指纹
- GREASE 随机化
- 后量子 X25519MLKEM768
- ECH(加密客户端问候)
|
### 🚀 传输层
- HTTP/2 SETTINGS 帧
- WINDOW_UPDATE 值
- 流优先级(HPACK)
- QUIC 传输参数
- HTTP/3 GREASE 帧
- TCP/IP 栈(TTL、MSS、窗口大小)
|
### 🧠 头部层
- Sec-Fetch-* 一致性
- 客户端提示(Sec-Ch-UA)
- Accept / Accept-Language
- 请求头顺序
- Cookie 持久化
|
## 结果
```
┌─────────────────────────────────┐
│ ECH (Encrypted Client Hello) │
├─────────────────────────────────┤
│ WITHOUT: sni=plaintext │
│ WITH: sni=encrypted + │
└─────────────────────────────────┘
```
```
┌─────────────────────────────────┐
│ HTTP/3 Fingerprint Match │
├─────────────────────────────────┤
│ Protocol: h3 + │
│ QUIC Version: 1 + │
│ Transport Params: + │
│ GREASE Frames: + │
└─────────────────────────────────┘
```
## 与 curl_cffi 对比
```
┌────────────────────────────────┬────────────────────────────────┐
│ BOTH LIBRARIES │ HTTPCLOAK ONLY │
├────────────────────────────────┼────────────────────────────────┤
│ │ │
│ + TLS fingerprint (JA3/JA4) │ + HTTP/3 fingerprinting │
│ + HTTP/2 fingerprint │ + ECH (encrypted SNI) │
│ + Post-quantum TLS │ + MASQUE proxy │
│ + Bot score: 99 │ + Domain fronting │
│ │ + Certificate pinning │
│ │ + Go, Python, Node.js, C# │
│ │ │
└────────────────────────────────┴────────────────────────────────┘
```
## 安装
```
pip install httpcloak # Python
npm install httpcloak # Node.js
go get github.com/sardanioss/httpcloak # Go
dotnet add package HttpCloak # C#
```
## 快速开始
### Python
```
import httpcloak
# 简单请求
r = httpcloak.get("https://example.com", preset="chrome-latest")
print(r.status_code, r.protocol)
# 使用 JSON 的 POST 请求
r = httpcloak.post("https://httpbin.org/post",
json={"key": "value"},
preset="chrome-latest"
)
# 自定义标头
r = httpcloak.get("https://httpbin.org/headers",
headers={"X-Custom": "value"},
preset="chrome-latest"
)
```
### Go
```
import (
"context"
"github.com/sardanioss/httpcloak/client"
)
// Simple request
c := client.NewClient("chrome-latest")
defer c.Close()
resp, _ := c.Get(ctx, "https://example.com", nil)
body, _ := resp.Text()
fmt.Println(resp.StatusCode, resp.Protocol)
// POST with JSON
jsonBody := []byte(`{"key": "value"}`)
resp, _ = c.Post(ctx, "https://httpbin.org/post",
bytes.NewReader(jsonBody),
map[string][]string{"Content-Type": {"application/json"}},
)
// Custom headers
resp, _ = c.Get(ctx, "https://httpbin.org/headers", map[string][]string{
"X-Custom": {"value"},
})
```
### Node.js
```
import httpcloak from "httpcloak";
// Simple request
const session = new httpcloak.Session({ preset: "chrome-latest" });
const r = await session.get("https://example.com");
console.log(r.statusCode, r.protocol);
// POST with JSON
const r = await session.post("https://httpbin.org/post", {
json: { key: "value" }
});
// Custom headers
const r = await session.get("https://httpbin.org/headers", {
headers: { "X-Custom": "value" }
});
session.close();
```
### C#
```
using HttpCloak;
// Simple request
using var session = new Session(preset: Presets.Chrome145);
var r = session.Get("https://example.com");
Console.WriteLine($"{r.StatusCode} {r.Protocol}");
// POST with JSON
var r = session.PostJson("https://httpbin.org/post",
new { key = "value" }
);
// Custom headers
var r = session.Get("https://httpbin.org/headers",
headers: new Dictionary
{ ["X-Custom"] = "value" }
);
```
## 功能特性
### 🔐 ECH(加密客户端问候)
隐藏你正在连接哪个域名,防止网络观察者窥探。
```
session = httpcloak.Session(
preset="chrome-latest",
ech_from="cloudflare.com" # Fetches ECH config from DNS
)
```
Cloudflare 追踪显示 `sni=encrypted` 而非 `sni=plaintext`。
### ⚡ 会话恢复(0-RTT)
TLS 会话票据让你看起来像回头客。
```
# 在任意 Cloudflare 站点上预热
session.get("https://cloudflare.com/")
session.save("session.json")
# 应用于目标网站
session = httpcloak.Session.load("session.json")
r = session.get("https://target.com/") # Bot score: 99
```
跨域预热有效,因为 Cloudflare 站点共享 TLS 基础设施。
### 🌐 通过代理的 HTTP/3
QUIC 通过代理的两种方法:
| 方法 | 工作原理 |
|--------|--------------|
| **SOCKS5 UDP ASSOCIATE** | 代理转发 UDP 数据包。大多数住宅代理支持此功能。 |
| **MASQUE(CONNECT-UDP)** | RFC 9298。通过 HTTP/3 隧道转发 UDP。仅限高级提供商使用。 |
```
# 带 UDP 的 SOCKS5
session = httpcloak.Session(proxy="socks5://user:pass@proxy:1080")
# MASQUE
session = httpcloak.Session(proxy="masque://proxy:443")
```
已知 MASQUE 提供商(自动识别):Bright Data、Oxylabs、Smartproxy、SOAX。
**推测性 TLS**(可选):CONNECT 与 TLS ClientHello 一起发送,节省一个代理往返(约快 25%)。为兼容的代理启用:
```
session = httpcloak.Session(proxy="socks5://...", enable_speculative_tls=True)
```
### 🎭 域名前置
连接到与 TLS SNI 中显示的不同主机。
```
client := httpcloak.NewClient("chrome-latest",
httpcloak.WithConnectTo("public-cdn.com", "actual-backend.internal"),
)
```
### 📌 证书固定
```
client.PinCertificate("sha256/AAAA...",
httpcloak.PinOptions{IncludeSubdomains: true})
```
### 🪝 请求钩子
```
client.OnPreRequest(func(req *http.Request) error {
req.Header.Set("X-Custom", "value")
return nil
})
client.OnPostResponse(func(resp *httpcloak.Response) {
log.Printf("Got %d from %s", resp.StatusCode, resp.FinalURL)
})
```
### ⏱️ 请求计时
```
fmt.Printf("DNS: %dms, TCP: %dms, TLS: %dms, Total: %dms\n",
resp.Timing.DNSLookup,
resp.Timing.TCPConnect,
resp.Timing.TLSHandshake,
resp.Timing.Total)
```
### 🔄 协议选择
```
session = httpcloak.Session(preset="chrome-latest", http_version="h3") # Force HTTP/3
session = httpcloak.Session(preset="chrome-latest", http_version="h2") # Force HTTP/2
session = httpcloak.Session(preset="chrome-latest", http_version="h1") # Force HTTP/1.1
```
自动模式优先尝试 HTTP/3,失败后优雅降级。
### 🖥️ TCP/IP 指纹识别
反机器人系统会检查 TCP SYN 包参数(TTL、窗口大小、MSS、窗口缩放)来验证你声称的操作系统是否匹配。如果一个声称使用 Chrome 的 Windows 请求却带有 Linux TCP 参数(TTL=64),会立即被标记。
httpcloak 会为每个预设平台自动设置正确的 TCP/IP 指纹。你也可以手动覆盖:
```
session = httpcloak.Session(
preset="chrome-latest-windows",
tcp_ttl=128, # Windows=128, Linux/macOS=64
tcp_window_size=64240, # Windows=64240, Linux/macOS=65535
tcp_window_scale=8, # Windows=8, Linux=7, macOS=6
tcp_mss=1460, # Standard Ethernet MTU
)
```
**Go:**
```
client := client.NewClient("chrome-latest-windows",
client.WithTCPFingerprint(fingerprint.TCPFingerprint{
TTL: 128, MSS: 1460, WindowSize: 64240, WindowScale: 8, DFBit: true,
}),
)
```
**Node.js:**
```
const session = new httpcloak.Session({
preset: "chrome-latest-windows",
tcpTtl: 128,
tcpWindowSize: 64240,
tcpWindowScale: 8,
});
```
**C#:**
```
var session = new Session(
preset: Presets.Chrome145Windows,
tcpTtl: 128,
tcpWindowSize: 64240,
tcpWindowScale: 8
);
```
内置平台配置:Windows(TTL=128,WS=8)、Linux(TTL=64,WS=7)、macOS(TTL=64,WS=6)。
### 🔀 运行时代理切换
在不创建新连接的情况下切换代理。适合代理轮换。
```
session = httpcloak.Session(preset="chrome-latest")
# 从直接连接开始
r = session.get("https://api.ipify.org")
print(f"Direct IP: {r.text}")
# 切换到代理 1
session.set_proxy("http://proxy1.example.com:8080")
r = session.get("https://api.ipify.org")
print(f"Proxy 1 IP: {r.text}")
# 切换到代理 2
session.set_proxy("socks5://proxy2.example.com:1080")
r = session.get("https://api.ipify.org")
print(f"Proxy 2 IP: {r.text}")
# 回到直接连接
session.set_proxy("")
```
**拆分代理配置** - 对 HTTP/2 和 HTTP/3 使用不同的代理:
```
session = httpcloak.Session(preset="chrome-latest")
# HTTP/1.1 和 HTTP/2 的 TCP 代理
session.set_tcp_proxy("http://tcp-proxy.example.com:8080")
# HTTP/3 的 UDP 代理(需要 SOCKS5 UDP 关联或 MASQUE)
session.set_udp_proxy("socks5://udp-proxy.example.com:1080")
# 检查当前配置
print(session.get_tcp_proxy()) # TCP proxy URL
print(session.get_udp_proxy()) # UDP proxy URL
```
### 📋 请求头顺序自定义
控制请求头的发送顺序,适用于高级指纹识别场景。
```
session = httpcloak.Session(preset="chrome-latest")
# 获取当前标头顺序(来自预设)
print(session.get_header_order())
# 设置自定义标头顺序
session.set_header_order([
"accept-language", "sec-ch-ua", "accept",
"sec-fetch-site", "sec-fetch-mode", "user-agent",
"sec-ch-ua-platform", "sec-ch-ua-mobile"
])
# 使用自定义顺序发起请求
r = session.get("https://example.com")
# 重置为预设的默认顺序
session.set_header_order([])
```
**JavaScript:**
```
session.setHeaderOrder(["accept-language", "sec-ch-ua", "accept", ...]);
console.log(session.getHeaderOrder());
session.setHeaderOrder([]); // Reset to default
```
**C#:**
```
session.SetHeaderOrder(new[] { "accept-language", "sec-ch-ua", "accept", ... });
Console.WriteLine(string.Join(", ", session.GetHeaderOrder()));
session.SetHeaderOrder(null); // Reset to default
```
**Go:**
```
c.SetHeaderOrder([]string{"accept-language", "sec-ch-ua", "accept", ...})
fmt.Println(c.GetHeaderOrder())
c.SetHeaderOrder(nil) // Reset to default
```
### 📤 流式传输与上传
```
# 流式大文件下载
stream = session.get_stream("https://example.com/large-file.zip")
print(f"Size: {stream.content_length} bytes")
with open("file.zip", "wb") as f:
while True:
chunk = stream.read(8192)
if not chunk:
break
f.write(chunk)
stream.close()
# 迭代器模式
for chunk in session.get_stream(url).iter_content(chunk_size=8192):
process(chunk)
# 多部分上传
r = session.post(url, files={
"file": ("filename.jpg", file_bytes, "image/jpeg")
})
```
### 🔒 身份验证
```
# 基本身份验证
r = httpcloak.get("https://api.example.com/data",
auth=("username", "password"),
preset="chrome-latest"
)
# 会话级身份验证
session = httpcloak.Session(
preset="chrome-latest",
auth=("username", "password")
)
```
### ⏱️ 超时与重试
```
# 超时
session = httpcloak.Session(preset="chrome-latest", timeout=30)
# 每个请求的超时
r = session.get("https://slow-api.com/data", timeout=60)
```
```
// Go: Timeout and retry configuration
client := client.NewClient("chrome-latest",
client.WithTimeout(30 * time.Second),
client.WithRetry(3), // Retry 3 times on 429, 500, 502, 503, 504
client.WithRetryConfig(
5, // Max retries
500 * time.Millisecond, // Min backoff
10 * time.Second, // Max backoff
[]int{429, 503}, // Status codes to retry
),
)
```
### 🚫 重定向控制
```
// Disable automatic redirects
client := client.NewClient("chrome-latest",
client.WithoutRedirects(),
)
resp, _ := client.Get(ctx, "https://example.com/redirect", nil)
fmt.Println(resp.StatusCode) // 302
fmt.Println(resp.GetHeader("location")) // Redirect URL
```
### 🔃 刷新(浏览器页面刷新)
模拟浏览器页面刷新 - 关闭所有 TCP/QUIC 连接但保持 TLS 会话缓存。下次请求时连接使用 TLS 恢复(就像真实浏览器一样)。
```
session = httpcloak.Session(preset="chrome-latest")
# 发起一些请求
session.get("https://example.com/page1")
session.get("https://example.com/page2")
# 模拟浏览器刷新(F5)
session.refresh()
# 下一个请求使用 TLS 恢复,看起来像回访用户
session.get("https://example.com/page1")
```
**Go:**
```
session := httpcloak.NewSession("chrome-latest")
session.Get(ctx, "https://example.com")
session.Refresh() // Close connections, keep TLS cache
session.Get(ctx, "https://example.com") // TLS resumption
```
**Node.js:**
```
session.refresh();
```
**C#:**
```
session.Refresh();
```
### 🌐 预热(浏览器页面加载)
模拟真实浏览器页面加载 - 获取 HTML 页面及其所有子资源(CSS、JS、图片、字体),使用真实的请求头、优先级和时机。预热完成后,会话将包含 TLS 会话票据、Cookie 和缓存头。
```
session = httpcloak.Session(preset="chrome-latest")
# 获取页面 + 子资源,行为如同真实浏览器
session.warmup("https://example.com")
# 后续请求看起来像是来自真实用户的跟进导航
r = session.get("https://example.com/api/data")
```
**Go:**
```
session := httpcloak.NewSession("chrome-latest")
session.Warmup(ctx, "https://example.com")
session.Get(ctx, "https://example.com/api/data") // Looks like real user
```
**Node.js:**
```
session.warmup("https://example.com");
```
**C#:**
```
session.Warmup("https://example.com");
```
### 🔀 分叉(并行浏览器标签页)
创建 N 个会话,与父会话共享 Cookie 和 TLS 会话缓存,但拥有独立的连接。这模拟了多个浏览器标签页 - 相同的 Cookie、相同的 TLS 恢复票据、相同的指纹,但 TCP/QUIC 连接独立,支持并行请求。
```
session = httpcloak.Session(preset="chrome-latest")
session.warmup("https://example.com")
# 创建 10 个并行“标签页”,共享 Cookie + TLS 缓存
tabs = session.fork(10)
for i, tab in enumerate(tabs):
threading.Thread(
target=lambda t, n: t.get(f"https://example.com/page/{n}"),
args=(tab, i)
).start()
```
**Go:**
```
session := httpcloak.NewSession("chrome-latest")
session.Warmup(ctx, "https://example.com")
tabs := session.Fork(10)
for i, tab := range tabs {
go func(t *httpcloak.Session, n int) {
t.Get(ctx, fmt.Sprintf("https://example.com/page/%d", n))
}(tab, i)
}
```
**Node.js:**
```
session.warmup("https://example.com");
const tabs = session.fork(10);
await Promise.all(tabs.map((tab, i) => tab.get(`https://example.com/page/${i}`)));
```
**C#:**
```
session.Warmup("https://example.com");
var tabs = session.Fork(10);
await Task.WhenAll(tabs.Select((tab, i) =>
Task.Run(() => tab.Get($"https://example.com/page/{i}"))
));
```
### 🌍 本地地址绑定
将传出连接绑定到特定的本地 IP 地址。在 IPv6 轮换场景中非常有用,当你的机器拥有多个分配的 IP 时。
```
# 绑定到特定 IPv6 地址
session = httpcloak.Session(
preset="chrome-latest",
local_address="2001:db8::1"
)
# 所有请求使用此源 IP
r = session.get("https://api.ipify.org")
print(r.text) # Shows 2001:db8::1
# IPv4 也适用
session = httpcloak.Session(
preset="chrome-latest",
local_address="192.168.1.100"
)
```
**Go:**
```
session := httpcloak.NewSession("chrome-latest",
httpcloak.WithLocalAddress("2001:db8::1"),
)
```
**Node.js:**
```
const session = new httpcloak.Session({
preset: "chrome-latest",
localAddress: "2001:db8::1"
});
```
**C#:**
```
var session = new Session(
preset: Presets.Chrome145,
localAddress: "2001:db8::1"
);
```
**注意:** 设置本地地址后,目标 IP 会自动筛选以匹配地址族(IPv6 本地 → 仅 IPv6 目标)。
### 🔑 TLS 密钥日志记录
将 TLS 会话密钥写入文件,以便在 Wireshark 中解密流量。支持 HTTP/1.1、HTTP/2 和 HTTP/3。
```
session = httpcloak.Session(
preset="chrome-latest",
key_log_file="/tmp/keys.log"
)
# 发起请求 - 密钥写入文件
session.get("https://example.com")
# 在 Wireshark 中:编辑 → 首选项 → 协议 → TLS → (预)主密钥日志文件名
```
**Go:**
```
session := httpcloak.NewSession("chrome-latest",
httpcloak.WithKeyLogFile("/tmp/keys.log"),
)
```
**Node.js:**
```
const session = new httpcloak.Session({
preset: "chrome-latest",
keyLogFile: "/tmp/keys.log"
});
```
**C#:**
```
var session = new Session(
preset: Presets.Chrome145,
keyLogFile: "/tmp/keys.log"
);
```
也支持 `SSLKEYLOGFILE` 环境变量(标准 NSS 密钥日志格式)。
## API 参考
### Python
```
import httpcloak
# 模块级函数
httpcloak.get(url, **kwargs)
httpcloak.post(url, **kwargs)
httpcloak.put(url, **kwargs)
httpcloak.patch(url, **kwargs)
httpcloak.delete(url, **kwargs)
httpcloak.head(url, **kwargs)
httpcloak.options(url, **kwargs)
# 会话类
session = httpcloak.Session(
preset="chrome-latest", # Browser preset (default)
proxy="socks5://...", # Proxy URL
timeout=30, # Timeout in seconds
http_version="h3", # Force protocol: h1, h2, h3, auto
ech_from="cloudflare.com", # ECH config source
auth=("user", "pass"), # Basic auth
)
# 会话方法
session.get(url, **kwargs)
session.post(url, data=None, json=None, **kwargs)
session.get_stream(url) # Streaming download
session.close()
# 代理切换
session.set_proxy(url) # Set both TCP and UDP proxy
session.set_tcp_proxy(url) # Set TCP proxy only (H1/H2)
session.set_udp_proxy(url) # Set UDP proxy only (H3)
session.get_proxy() # Get current proxy
session.get_tcp_proxy() # Get current TCP proxy
session.get_udp_proxy() # Get current UDP proxy
# 标头顺序自定义
session.set_header_order(order) # Set custom header order (list of lowercase names)
session.get_header_order() # Get current header order
# 会话持久性(0-RTT 恢复)
session.save("session.json") # Save to file
session = Session.load("session.json") # Load from file
data = session.marshal() # Export as string
session = Session.unmarshal(data) # Import from string
# 响应对象
response.status_code # HTTP status
response.ok # True if status < 400
response.text # Body as string
response.content # Body as bytes
response.json() # Parse JSON
response.headers # Response headers
response.protocol # h1, h2, or h3
response.url # Final URL
response.raise_for_status() # Raise on 4xx/5xx
```
### Go
```
import "github.com/sardanioss/httpcloak/client"
// Client creation
c := client.NewClient("chrome-latest",
client.WithTimeout(30 * time.Second),
client.WithProxy("socks5://..."),
client.WithRetry(3),
client.WithoutRedirects(),
client.WithInsecureSkipVerify(),
)
defer c.Close()
// Request methods
resp, err := c.Get(ctx, url, headers)
resp, err := c.Post(ctx, url, body, headers)
resp, err := c.Put(ctx, url, body, headers)
resp, err := c.Delete(ctx, url, headers)
// Advanced request
resp, err := c.Do(ctx, &client.Request{
Method: "GET",
URL: url,
Headers: map[string][]string{},
Body: io.Reader,
Params: map[string]string{},
ForceProtocol: client.ProtocolHTTP3,
FetchMode: client.FetchModeCORS,
Referer: "https://example.com",
})
// Proxy switching
c.SetProxy(url) // Set both TCP and UDP proxy
c.SetTCPProxy(url) // Set TCP proxy only (H1/H2)
c.SetUDPProxy(url) // Set UDP proxy only (H3)
c.GetProxy() // Get current proxy
c.GetTCPProxy() // Get current TCP proxy
c.GetUDPProxy() // Get current UDP proxy
// Session persistence (0-RTT resumption)
c.Save("session.json") // Save to file
c, _ = client.Load("session.json") // Load from file
data, _ := c.Marshal() // Export as string
c, _ = client.Unmarshal(data) // Import from string
// Response object
resp.StatusCode
resp.Protocol
resp.Headers
resp.Body // io.ReadCloser
resp.Text() // (string, error)
resp.Bytes() // ([]byte, error)
resp.JSON(&v) // error
resp.GetHeader(key) // string
resp.IsSuccess() // bool
resp.IsRedirect() // bool
```
### Node.js
```
import httpcloak from "httpcloak";
// Session creation
const session = new httpcloak.Session({
preset: "chrome-latest",
proxy: "socks5://...",
timeout: 30000,
httpVersion: "h3",
});
// Async methods
await session.get(url, options)
await session.post(url, { json, data, headers })
await session.put(url, options)
await session.delete(url, options)
// Sync methods
session.getSync(url, options)
session.postSync(url, options)
session.close()
// Proxy switching
session.setProxy(url) // Set both TCP and UDP proxy
session.setTcpProxy(url) // Set TCP proxy only (H1/H2)
session.setUdpProxy(url) // Set UDP proxy only (H3)
session.getProxy() // Get current proxy
session.getTcpProxy() // Get current TCP proxy
session.getUdpProxy() // Get current UDP proxy
session.proxy // Property accessor (get/set)
// Session persistence (0-RTT resumption)
session.save("session.json") // Save to file
session = httpcloak.Session.load("session.json") // Load from file
const data = session.marshal() // Export as string
session = httpcloak.Session.unmarshal(data) // Import from string
// Response object
response.statusCode
response.ok
response.text
response.json()
response.headers
response.protocol
```
### C#
```
using HttpCloak;
// Session creation
var session = new Session(
preset: Presets.Chrome145,
proxy: "socks5://...",
timeout: 30
);
// Request methods
session.Get(url, headers)
session.Post(url, body, headers)
session.PostJson(url, data, headers)
session.Put(url, body, headers)
session.Delete(url)
session.Dispose()
// Proxy switching
session.SetProxy(url) // Set both TCP and UDP proxy
session.SetTcpProxy(url) // Set TCP proxy only (H1/H2)
session.SetUdpProxy(url) // Set UDP proxy only (H3)
session.GetProxy() // Get current proxy
session.GetTcpProxy() // Get current TCP proxy
session.GetUdpProxy() // Get current UDP proxy
session.Proxy // Property accessor (get/set)
// Session persistence (0-RTT resumption)
session.Save("session.json") // Save to file
var session = Session.Load("session.json") // Load from file
var data = session.Marshal() // Export as string
var session = Session.Unmarshal(data) // Import from string
// Response object
response.StatusCode
response.Ok
response.Text
response.Json()
response.Headers
response.Protocol
```
## 浏览器预设
| 预设 | 平台 | PQ | H3 |
|--------|----------|:--:|:--:|
| `chrome-146` | 自动 | ✅ | ✅ |
| `chrome-146-windows` | Windows | ✅ | ✅ |
| `chrome-146-macos` | macOS | ✅ | ✅ |
| `chrome-146-linux` | Linux | ✅ | ✅ |
| `chrome-146-ios` | iOS | ✅ | ✅ |
| `chrome-146-android` | Android | ✅ | ✅ |
| `chrome-145` | 自动 | ✅ | ✅ |
| `chrome-145-windows` | Windows | ✅ | ✅ |
| `chrome-145-macos` | macOS | ✅ | ✅ |
| `chrome-145-linux` | Linux | ✅ | ✅ |
| `chrome-145-ios` | iOS | ✅ | ✅ |
| `chrome-145-android` | Android | ✅ | ✅ |
| `chrome-144` | 自动 | ✅ | ✅ |
| `chrome-144-windows` | Windows | ✅ | ✅ |
| `chrome-144-macos` | macOS | ✅ | ✅ |
| `chrome-144-linux` | Linux | ✅ | ✅ |
| `chrome-143` | 自动 | ✅ | ✅ |
| `chrome-143-windows` | Windows | ✅ | ✅ |
| `chrome-143-macos` | macOS | ✅ | ✅ |
| `chrome-143-linux` | Linux | ✅ | ✅ |
| `chrome-141` | 自动 | ✅ | ❌ |
| `chrome-133` | 自动 | ✅ | ❌ |
| `firefox-133` | 自动 | ❌ | ❌ |
| `safari-18` | macOS | ❌ | ✅ |
| `safari-18-ios` | iOS | ❌ | ✅ |
| `safari-17-ios` | iOS | ❌ | ❌ |
| `chrome-146-ios` | iOS | ✅ | ✅ |
| `chrome-145-ios` | iOS | ✅ | ✅ |
| `chrome-144-ios` | iOS | ✅ | ✅ |
| `chrome-143-ios` | iOS | ✅ | ✅ |
| `chrome-146-android` | Android | ✅ | ✅ |
| `chrome-145-android` | Android | ✅ | ✅ |
| `chrome-144-android` | Android | ✅ | ✅ |
| `chrome-143-android` | Android | ✅ | ✅ |
**PQ** = 后量子(X25519MLKEM768) · **H3** = HTTP/3
## 测试工具
| 工具 | 测试内容 |
|------|-------|
| [tls.peet.ws](https://tls.peet.ws/api/all) | JA3、JA4、HTTP/2 Akamai |
| [quic.browserleaks.com](https://quic.browserleaks.com/) | HTTP/3 QUIC 指纹 |
| [cf.erisa.uk](https://cf.erisa.uk/) | Cloudflare 机器人评分 |
| [cloudflare.com/cdn-cgi/trace](https://www.cloudflare.com/cdn-cgi/trace) | ECH 状态、TLS 版本 |
## 依赖项
浏览器指纹识别的定制分支:
- [sardanioss/utls](https://github.com/sardanioss/utls) — TLS 指纹识别
- [sardanioss/quic-go](https://github.com/sardanioss/quic-go) — HTTP/3 指纹识别
- [sardanioss/net](https://github.com/sardanioss/net) — HTTP/2 帧指纹识别
## 联系
- Discord:**sardanioss**
- 邮箱:**sakshamsolanki126@gmail.com**
MIT License
标签:Accept 语言, Akamai 指纹, Bot 绕过, Chrome 模拟, Cookie 持久化, ECH, EVTX分析, Firefox 模拟, Go HTTP 客户端, Go 包, GREASE 随机化, HPACK, HTTP/1.1, HTTP/2, HTTP/2 指纹, HTTP/3, HTTP/3 指纹, HTTP 代理, JA3, JA4, MITM代理, MSS, npm, NuGet, pkg.go.dev, PyPI, QUIC 传输参数, Safari 模拟, Sec-Fetch 标头, SNI 加密, Stream 优先级, TCP/IP 栈, TLS 指纹, TTL, X25519MLKEM768, 代理支持, 会话复用, 会话管理, 加密层模拟, 告警, 多架构支持, 客户端提示, 日志审计, 标头顺序, 浏览器指纹模拟, 窗口大小, 逆向工具, 防检测