Skip to main content

Browser-level (Firefox 152) HTTP client — real NSS TLS, HTTP/2, byte-identical fingerprint

Project description

never_fox

发出去的请求在字节层面就是 Firefox 152 —— 不是模拟,是真的。

never_fox 是一个 requests 风格的 Python HTTP 客户端,底层链接 Firefox 真正的 TLS 引擎 NSS,所以它的 TLS ClientHello 与真 Firefox 152 逐字节相同(含 ECH、X25519MLKEM768 后量子组),HTTP/2 帧与 header 也与真火狐一致。专为高并发爬虫 / 风控对抗设计。

一句话原理:Chrome 有 Cronet、Firefox 的网络栈是 NSS(TLS)+ Necko。NSS 开源可独立链接 —— 我们直接链接真 NSS,用逆向出来的 Firefox 152 配置驱动它。这是"模拟"做不到的:curl_cffi 这类能对齐 JA3/JA4,但 ECH 等细节对不上,因为它们用的不是 NSS。

为什么它是"真的"

在本地受控 HTTPS 服务器上,让真 Firefox 152 和 never_fox 都访问,逐字段对比握手数据,并在 4 个指纹站(peet.ws / browserleaks / scrapfly / howsmyssl,算法各不同) 交叉验证:

维度 与真 Firefox 152
TLS ClientHello 原始字节 ✅ 0 差异
JA3 / JA3N / JA4 / JA4_o / JA4_r ✅ 全部一致
HTTP/2 Akamai 指纹(SETTINGS/WINDOW_UPDATE/优先级/伪头序) ✅ 一致
所有 HTTP header(名 / 顺序 / 值) ✅ 一致
ECH、record_size_limit、MLKEM、delegated_credentials ✅ 一致

特性

真指纹 真 NSS 引擎,ClientHello 字节级 == Firefox 152(含 ECH)
requests 兼容 get/post/put/patch/delete/head/options;headers= 合并进默认头(不替换);Response.headers 大小写不敏感、.elapsed(timedelta)、.request/.links/.iter_lines/.is_redirect/bool(resp);异常层级 RequestException/HTTPError/ConnectionError/Timeout/TooManyRedirects;auth=(u,p)files=(multipart)、hooks=、按请求 verify
异步 AsyncSession,future 驱动,线程数≈连接数而非请求数
高并发 冷启动单飞建连(一个 origin 收敛到 1 条 h2,像浏览器)+ 多路复用 + 引用计数防崩
Cookie RFC 6265 cookie jar:Expires+Max-Age、host-only 不泄漏子域、/ 边界 path 匹配、default-path、__Host-/__Secure- 前缀校验;curl_cffi 风格接口(get/set/delete/clear/update/get_dict/jar[]/in/迭代,Cookies 别名;get(name) 为 last-wins,重名不抛)
稳健 幂等方法才自动重试、取消/超时/超限发 RST_STREAM、max_response_bytes 上限 + 解压炸弹防护、跨域重定向剥离 Authorization
代理 HTTP CONNECT + SOCKS5(可认证);目标看到真 FF152,代理只见加密隧道
限流 每 host 限速(带抖动)+ 429/503 指数退避(尊重 Retry-After)
HTTP/3 Alt-Svc 感知,基于真 neqo,回读真实 status/headers(失败自动降级 h2)

环境要求与构建

native 引擎是编译产物,按平台分发(像 Cronet)。重依赖 NSS/NSPR/brotli/zstd 不用我们编译 —— 由各平台包管理器提供预编译版,我们只编 ~250 行的引擎(几秒)。

# 1) 系统依赖(预编译的 NSS 等)
brew install nss nspr brotli zstd                                  # macOS
sudo apt-get install libnss3-dev libnspr4-dev libbrotli-dev libzstd-dev zlib1g-dev patchelf  # Linux
# Windows: MSYS2 装 mingw-w64-x86_64-{nss,nspr,brotli,zstd,zlib,gcc,pkg-config}

# 2) Python 依赖
pip install hpack brotli zstandard

# 3) 跨平台编译(自动找 NSS,产出 libfxtls.{dylib,so,dll})
python native/build.py

# 4) 自检指纹 == Firefox 152(NSS 版本漂移会在这里报错)
python native/verify.py

# 5)(可选)打包自包含,拷到同 OS+架构机器免依赖运行
python native/bundle.py                                            # -> native/vendor/

然后把仓库目录加入 PYTHONPATH,import never_fox 即可。

多平台预编译(GitHub CI)

.github/workflows/build.yml 用矩阵在 Linux x86_64 / Linux arm64 / macOS arm64 / Windows x86_64 原生 runner 上自动:装预编译 NSS → build.pyverify.py 指纹门禁 → 上传各平台产物;打 vX.Y.Z tag 会把四平台产物附到 GitHub Release。NSS 由包管理器缓存,只在升版本时重拉。

快速开始

import never_fox as nf

r = nf.get("https://example.com/", params={"q": "x"})
print(r.status_code, r.ok, r.http_version, r.text[:200])
r.raise_for_status()

r = nf.post("https://httpbin.org/post", json={"hello": "firefox152"})   # 或 data={...} 表单
print(r.json())

Session(Cookie / 重定向 / 连接池)

s = nf.Session()                      # verify=True, h3="auto"
s.get("https://site/login")           # Set-Cookie 自动保存
s.post("https://site/api", data={"a": 1})   # 自动带 Cookie、自动重定向(r.history)
print(s.cookies.as_dict())
s.put(...); s.delete(...); s.patch(...); s.head(...); s.options(...)
s.close()

异步(高并发)

import asyncio, never_fox as nf

async def main():
    async with nf.AsyncSession() as s:
        # 上千并发共享连接池中的多路复用连接;响应通过 future 等待,
        # 不为每个请求占一个线程(线程数≈连接数,不随请求数增长)。
        rs = await asyncio.gather(*[s.get(f"https://site/p/{i}") for i in range(1000)])
        print(sum(r.ok for r in rs), "ok")

asyncio.run(main())

爬虫调优(代理 / 限速 / 退避)

s = nf.Session(
    max_connections_per_host=16,    # 每 host 最多连接数
    rate_limit=5,                   # 每 host <= 5 请求/秒(0=不限)
    backoff_retries=3,              # 429/503 指数退避重试,尊重 Retry-After
    retries=3,                      # 连接级重试
    verify=True,                    # 用 Firefox 同款 Mozilla 根证书校验
)

# 代理:HTTP CONNECT 或 SOCKS5(可认证),按会话或按请求,可自由轮换
s = nf.Session(proxy="http://user:pass@proxy:8080")
r = nf.get(url, proxy="socks5://user:pass@10.0.0.1:1080")     # 或 proxies={"https": "..."}

Response:.status_code .ok .reason .url .text .content .json() .headers .cookies .history .elapsed .encoding .raise_for_status() .iter_content()

工作原理

never_fox/            Python 层
  client.py           Session / Response / 连接池 / Cookie / 重定向 / 限速 / 代理解析
  aio.py              AsyncSession(future 驱动的异步)
  h2conn.py           HTTP/2 多路复用(复刻 Firefox 的 SETTINGS/优先级/伪头序)
  http1.py            HTTP/1.1 回退
  h3.py               HTTP/3(经真 neqo,实验性)
  cookies.py          CookieJar
  _native.py          ctypes 绑定到原生引擎
native/               原生引擎(C,链接真 NSS)
  fxtls_config.h      Firefox 152 的 ClientHello 配置(密码套件/组/签名算法/ECH/证书压缩…)
  fxtls_lib.c         连接 + TLS 握手 + 收发 + 代理(CONNECT/SOCKS5)-> libfxtls.dylib
  bundle.py           把依赖 dylib 收进 vendor/ 并改 @loader_path,便于跨机
harness/              指纹验证脚本(本地抓包对比 + 多站交叉验证)

证书用 NSS 内置的 Mozilla 根证书列表(libnssckbi) 校验 —— 和 Firefox 同款信任库。

已知限制

  • 原生库是平台相关二进制:跨 OS / 架构需在目标机重新 build.sh(像 Cronet 按平台分发)。Firefox/Linux 是 OS 自洽目标,适合做服务端。
  • 会话复用:TLS 1.3 复用握手会带 pre_shared_key 扩展,JA3/JA4 与全握手不同 —— 两者都是真 Firefox 指纹(连接池默认复用同一握手,一般不出现)。
  • HTTP/3:需运行环境 UDP/443 出网;失败自动降级 h2。请求体(POST/PUT)暂走 h2。
  • requests 差异:stream=True 收下但 body 始终全量缓冲;cert=(客户端证书)不支持(NSS 用 Mozilla 根),会抛 NotImplementedError;verify='/ca.pem' 自定义 CA 包不认(走 NSS 根)。
  • Cookie:未内置 Public Suffix List(Domain=co.uk 这类多标签公共后缀不拒,只拒裸 TLD);SameSite 解析存储但不强制(需请求发起方 site 上下文)。

验证复现

# 本地起 HTTPS/h2 服务,真 Firefox + never_fox 都访问,逐字段对比
python harness/localcap/diff_h2cap.py        # 看 harness/localcap/FULL_DIFF.md
# 多站交叉验证报告
cat harness/localcap/MULTISITE.md

详细逆向与对比过程见 REPORT.md

免责声明

仅用于授权范围内的安全研究、风控对抗测试与合规数据采集。请遵守目标站点的条款与当地法律。

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

never_fox-0.3.9-py3-none-win_amd64.whl (4.0 MB view details)

Uploaded Python 3Windows x86-64

never_fox-0.3.9-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (5.1 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

never_fox-0.3.9-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl (5.0 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

never_fox-0.3.9-py3-none-macosx_14_0_arm64.whl (4.9 MB view details)

Uploaded Python 3macOS 14.0+ ARM64

File details

Details for the file never_fox-0.3.9-py3-none-win_amd64.whl.

File metadata

  • Download URL: never_fox-0.3.9-py3-none-win_amd64.whl
  • Upload date:
  • Size: 4.0 MB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.11

File hashes

Hashes for never_fox-0.3.9-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 3824309dcc309f39504793fc5e615202feb6390910eac807ecc9bfdceb96ad82
MD5 b5104bec0b1d13b06fd32e3e3622065d
BLAKE2b-256 f9753c42e8c32554d7c87437c792a13a322627ab830b849791850a26b010a44e

See more details on using hashes here.

File details

Details for the file never_fox-0.3.9-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for never_fox-0.3.9-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 943bcb8b26e578edcfa4aa531850cae3047051f7a4accb0e9a99434ce985def1
MD5 2b945d7dfc4e2758422516b75fbd497c
BLAKE2b-256 dbfb4128d3385f8caf298aeac14bb03ea3432e3ebb857d15bec6e7c734478b38

See more details on using hashes here.

File details

Details for the file never_fox-0.3.9-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl.

File metadata

File hashes

Hashes for never_fox-0.3.9-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 3ba96eda8d55c080f1a676d6ea8db869cd71e455564695cc54714d7f4a58085f
MD5 60b1ed1f4a943313c88bd33fd25fdd68
BLAKE2b-256 ffa3bb41027d75987f2a857320a736e35811a0d28bb78c844cc93ef9674d467d

See more details on using hashes here.

File details

Details for the file never_fox-0.3.9-py3-none-macosx_14_0_arm64.whl.

File metadata

File hashes

Hashes for never_fox-0.3.9-py3-none-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 aa00818bb4a743c813179c1f66a24dce1107bc23c4abc038ad2f64d551175572
MD5 f232e14e2d742a6613b7c0fbb46a9ddf
BLAKE2b-256 2d988bba7a357ec3ec03d14fc6997b8ab3e7e941cb9c6b5828e239cbabd51dd5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page