客户端配置¶
x-api-rs 是 SDK,HTTP/性能/可用性相关参数都通过 RquestClientBuilder 暴露给上层使用方。
本文档列出所有可配置项的默认值、风险、何时该改。
设计原则¶
- 安全默认 + 可覆盖:默认值对非幂等写操作(DM/Posts/Like/上传)安全,高级用户可通过 builder 覆盖
- 协议常量不暴露:与 Twitter API 协议绑定的常量(如
MAX_MESSAGE_LENGTH = 10000、GraphQL queryId、Bearer Token)写死在 SDK 内,不可配置 - 传输/性能参数暴露:timeout、retry、proxy、pool size、JA3 指纹等可调
配置项参考¶
http2_max_retry_count: usize 🔴¶
HTTP/2 自动重试次数。控制 rquest 在收到 RST_STREAM(REFUSED_STREAM) 或 GOAWAY(NO_ERROR)
时是否自动重发请求。
| 项目 | 值 |
|---|---|
| 本 SDK 默认 | 0(禁用) |
| rquest 原始默认 | 2 |
| 风险等级 | 🔴 高(影响数据正确性) |
为什么默认禁用:
rquest 把 H2 REFUSED_STREAM 视为"请求未到达 server"自动重发(RFC 9113 §8.7-3.2)。
但 Twitter 在限流时会先处理请求再发 RST_STREAM——server 已经收到并执行了请求,
rquest 仍重发,导致同一条 DM/Tweet 被发送 2 次。
200 并发 DM 场景实测:11-19 条消息出现重复(5.5%-9.5% 重复率)。
何时可以改成 >0:
- ✅ 客户端只用于幂等读操作:搜索、获取用户资料、获取 timeline、获取私信列表
- ❌ 绝对不能用于:DM 发送、发帖、点赞、转发、关注、上传——任何写操作
如果同一个客户端实例会混用读写,保留默认 0。
用法:
use x_api_rs::{RquestClientBuilder, CookieAuth, ClientTransaction};
use std::sync::Arc;
// ✅ 安全默认(推荐)
let client = RquestClientBuilder::new(auth, transaction).build()?;
// ⚠️ 仅在纯读场景下可考虑
let client = RquestClientBuilder::new(auth, transaction)
.http2_max_retry_count(2)
.build()?;
proxy_url: Option<String>¶
代理服务器 URL,支持 HTTP / HTTPS / SOCKS5。
| 项目 | 值 |
|---|---|
| 默认 | None(直连) |
| 风险等级 | 🟢 低 |
已知陷阱:
- Burp Suite 会破坏 JA3 指纹模拟(TLS MITM 终止连接)→ 触发 Twitter 226 反爬
- 大文件 multipart 上传 (>~100KB) 通过 Burp 会失败:
Stream failed to close correctly - 测试场景建议使用 mitmproxy 或直连
用法:
RquestClientBuilder::new(auth, transaction)
.proxy_url("http://127.0.0.1:8080".to_string())
.build()?;
profile: Option<ClientProfile>¶
浏览器指纹 profile —— 把 TLS 指纹(JA3/JA4 + HTTP/2 SETTINGS)与 HTTP 头部(User-Agent / Sec-Ch-Ua)绑成一个自洽身份。支持每账号独立配置。
| 项目 | 值 |
|---|---|
| 默认(不传) | ClientProfile::Chrome { os: Windows, arch: X64 }(Chrome 136 Windows x64) |
| 风险等级 | 🟢 低 |
为什么是一个参数而不是 enable_ja3 + fingerprint 两个:真实浏览器的 TLS 指纹和 HTTP 头是同一个身份,拆成两个独立开关会产生「UA 自称 Chrome 140、TLS 握手却是 Chrome 136」这种错配——而 UA/JA3 错配本身就是反爬识别机器人的特征。ClientProfile 保证两层永远一致。
默认为何固定 Chrome 136 Windows x64(而非随机):指纹模拟的目标是混进最大的真实人群,不是变独特。Chrome Windows 是全球 Twitter Web 桌面占比最大的配置,淹没在真人流量里最安全。随机化反而可能制造唯一性或 UA/JA3 错配。
跨账号差异化:要让 A 账号和 B 账号在 JA3 层真正不同,必须跨浏览器家族(Chrome / Safari / Firefox / Edge / OkHttp 各自 TLS 不同);在同一 Chrome 家族内换 OS/版本不改变 JA3。
支持的 profile:
| 家族 | 构造 | TLS 来源 | HTTP 头 |
|---|---|---|---|
| Chrome 136 | ClientProfile::Chrome { os, arch } |
Emulation::Chrome136 |
SDK 自建完整 Sec-Ch-Ua-* |
| Safari macOS | ClientProfile::SafariMac(v) |
rquest-util Safari emulation | emulation 自带(Safari 不发 Sec-Ch-Ua) |
| Safari iOS | ClientProfile::SafariIos(v) |
同上 | 同上 |
| Safari iPad | ClientProfile::SafariIpad |
同上 | 同上 |
| Firefox | ClientProfile::Firefox(v) |
rquest-util Firefox emulation | 同上 |
| Edge | ClientProfile::Edge(v) |
rquest-util Edge emulation | 同上 |
| OkHttp(Android app) | ClientProfile::OkHttp(v) |
rquest-util OkHttp emulation | 同上 |
| 禁用 TLS 模拟(调试) | ClientProfile::None |
rquest 默认 | 无模拟 |
HTTP/2:始终开启,h2 SETTINGS 帧指纹随 profile 一起模拟(
ClientProfile::None除外)。TLS 版本锚定:Chrome 只锚定 136——这是 rquest-util 2.2.1 TLS emulation 的上限,也是唯一能保证 TLS 与 HTTP 头自洽的 Chrome 版本。不提供 137–144(其真实 JA3 未经库验证,会与 Chrome136 握手错配)。
Rust 用法:
use x_api_rs::ClientProfile;
use x_api_rs::common::fingerprint::types::{OsType, Architecture};
// 默认(Chrome 136 Windows x64)
let client = Twitter::create(cookies, None, None).await?;
// 指定 Chrome macOS arm64
let p = ClientProfile::Chrome { os: OsType::MacOS, arch: Architecture::Arm64 };
let client = Twitter::create(cookies, None, Some(p)).await?;
// 查看当前身份
let info = client.fingerprint_info();
println!("{} {} {} {}", info.browser, info.version, info.platform, info.user_agent);
完整示例¶
use x_api_rs::{Twitter, ClientProfile};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let cookies = "ct0=xxx; auth_token=yyy; twid=u%3D123".to_string();
// 默认安全配置(Chrome 136 Windows x64,启用 JA3,H2 重试禁用)
let twitter = Twitter::create(cookies.clone(), None, None).await?;
// 带代理 + 指定 profile
use x_api_rs::common::fingerprint::types::{OsType, Architecture};
let p = ClientProfile::Chrome { os: OsType::MacOS, arch: Architecture::Arm64 };
let twitter = Twitter::create(cookies, Some("http://127.0.0.1:8080".into()), Some(p)).await?;
Ok(())
}
需要细粒度控制
http2_max_retry_count等传输参数时,用RquestClientBuilder::new(auth, transaction).profile(...).http2_max_retry_count(0).build()?+Twitter::with_client(...)。
Python 用户¶
from x_api_rs import Twitter, ClientProfile
# 默认(Chrome 136 Windows x64)
client = await Twitter.create(cookies)
# 带代理
client = await Twitter.create(cookies, proxy_url="http://127.0.0.1:8080")
# 每账号独立身份——跨家族才有真实 JA3 差异
a = await Twitter.create(cookies_a, profile=ClientProfile.chrome("macos", "arm64"))
b = await Twitter.create(cookies_b, profile=ClientProfile.safari_ios("18.1.1"))
c = await Twitter.create(cookies_c, profile=ClientProfile.okhttp("5"))
# 禁用 TLS 模拟(仅调试)
d = await Twitter.create(cookies, profile=ClientProfile.none())
# 查看实际身份
info = a.fingerprint_info()
print(info.browser, info.version, info.platform)
print(info.user_agent)
ClientProfile 工厂方法:
| 方法 | 说明 |
|---|---|
ClientProfile.chrome(os, arch) |
Chrome 136。os: windows/macos/linux;arch: x64/arm64 |
ClientProfile.safari_mac(version) |
Safari macOS。17.5/18/18.2/18.3/18.3.1 |
ClientProfile.safari_ios(version) |
Safari iOS。17.4.1/18.1.1 |
ClientProfile.safari_ipad() |
Safari iPadOS 18 |
ClientProfile.firefox(version) |
Firefox。133/135/136/private136/android135 |
ClientProfile.edge(version) |
Edge。131/134 |
ClientProfile.okhttp(version) |
OkHttp(Android app)。5/4.12 |
ClientProfile.none() |
禁用 TLS 模拟(调试) |
fingerprint_info() 返回 ProfileInfo,字段:browser / version / platform / user_agent。
http2_max_retry_count 当前未在 Python 层暴露——因为 Python 用户场景几乎都涉及写操作,
强制使用安全默认(0)。如需读专用客户端,请联系 issue 反馈。
历史¶
- 2026-05-09:发现 rquest 默认
http2_max_retry_count=2导致 DM 重复发送,本 SDK 默认改为 0,并通过RquestClientBuilder::http2_max_retry_count暴露为可配置(v1.0.15)