tlsreq
English | 简体中文
A single Session / AsyncSession API over four TLS-capable HTTP stacks:
curl_cffi · wreq · niquests + xutls · httpx + xutls
Change backend and impersonate. Request code stays the same.
Install
pip install tlsreq # httpx + h2 + brotli + zstd + xutls
pip install "tlsreq[niquests]" # or wreq / curl_cffi / all
pip install tlsreq pulls the default httpx stack: HTTP/2 (h2), br/zstd body decoding, and Chrome 152 TLS via xutls.
| Extra | Pulls in | Notes |
|---|---|---|
| (default) | httpx, h2, brotli, zstandard, xutls | Chrome 152 TLS + HTTP/2; decodes br/zstd |
httpx |
(already in the default install) | Kept so tlsreq[httpx] still works |
niquests |
niquests | Chrome 152 TLS + HTTP/2 patches |
wreq |
wreq | Python ≥ 3.11 only; skipped on 3.9/3.10 |
curl_cffi |
curl_cffi | |
all |
niquests, curl_cffi; wreq if Python ≥ 3.11 |
xutls import name is still utls. Do not also install the upstream utls package — both provide the utls module. To upgrade later: pip install -U xutls.
Quick start
import asyncio
from tlsreq import AsyncSession, Session, niquests, wreq
async def main():
async with AsyncSession(
backend=niquests,
impersonate=niquests.chrome152,
proxy="http://user:pass@host:port",
timeout=30,
extra={"pool_maxsize": 1},
) as s:
r = await s.get("https://tls.peet.ws/api/all")
print(r.status_code, r.http_version, r.cookies)
print(r.json()["tls"]["ja4"])
r = await s.post(
"https://example.com/login",
data=b"user=a&pass=b",
headers={"content-type": "application/x-www-form-urlencoded"},
header_order=["user-agent", "accept", "content-type"],
)
print(r.status_code, r.text)
asyncio.run(main())
with Session(wreq, wreq.chrome154, proxy="http://127.0.0.1:7890") as s:
r = s.get("https://example.com")
print(r.status_code, r.headers)
The native client is on session.raw when you need a backend-specific knob.
Backends
backend |
Default impersonate | Latest Chrome alias | Sync | Async |
|---|---|---|---|---|
niquests |
chrome:152 |
chrome152 |
yes | yes |
httpx |
chrome:152 |
chrome152 |
yes | yes |
curl_cffi |
chrome150 |
chrome150 |
yes | yes |
wreq |
Chrome154 |
chrome154 |
yes | yes |
Unknown backend or impersonate values raise. There is no silent fallback to another profile.
chrome / chromestable map to that backend’s current default. Fingerprints are attributes on the library object, so the editor lists only that library: Session(wreq, wreq.chrome154), Session(httpx, httpx.chrome152), Session(curl_cffi, curl_cffi.chrome150). wreq includes chrome154, firefox152, safari26_4, edge148, opera131, and okhttp5. httpx and niquests, along with nirequest, nirequests, and nio, have the eight xutls presets (chrome131, chrome142, chrome146, chrome148, chrome150, chrome152, chrome, chromestable). curl, cffi, and curl_cffi share the curl_cffi list. Session(wreq, "chrome154") and Session("wreq", "chrome154") still run. A quoted fingerprint string does not offer that list. Session(impersonate=...) defaults to httpx.
httpx / niquests offer both HTTP/2 and HTTP/1.1. The protocol is chosen from the negotiated TLS ALPN (h2 vs http/1.1); an HTTP/1.1-only origin falls back instead of failing.
Chrome 152 (niquests / httpx)
These two backends apply Chrome 152 HTTP/2 framing on top of xutls ClientHello impersonation:
| Signal | Value |
|---|---|
| SETTINGS | 1:65536;2:0;4:6291456;6:262144 |
| WINDOW_UPDATE | 15663105 |
| HEADERS priority | exclusive, weight 256 |
| Pseudo-header order | m,a,s,p |
| JA4 | t13d1517h2_8daaf6152771_cb7bf5808d99 |
| Akamai fingerprint | 1:65536;2:0;4:6291456;6:262144|15663105|0|m,a,s,p |
Checked against tls.peet.ws.
curl_cffi and wreq use their own stacks; they do not take this HTTP/2 patch.
API
Session / AsyncSession
Session(
backend: Backend[Imp] | str = httpx,
impersonate: Imp | None = None,
*,
proxy: str | None = None,
timeout: float = 30,
verify: bool = True,
headers: Mapping[str, str] | None = None,
cookies: Mapping[str, str] | None = None,
allow_redirects: bool = True,
extra: dict[str, Any] | None = None,
)
httpx, niquests, wreq, and curl_cffi are Backend objects exported by tlsreq. Import the one you pass in, then pass one of its fingerprint attributes: Session(wreq, wreq.chrome154). AsyncSession has the same signature.
Context-manager safe. AsyncSession methods are coroutines.
Requests
get / post / put / patch / delete / head / options all call request.
| Argument | Meaning |
|---|---|
headers |
Per-request headers |
params |
Query string |
data |
Form dict or raw body (str / bytes) |
json |
JSON body |
cookies |
Per-request cookies |
timeout |
Override session timeout |
allow_redirects |
Override session redirect flag |
header_order |
Wire order of header names, when the backend supports it |
extra |
Backend-specific kwargs for this call |
extra on the session is merged into the underlying constructor; extra on a request is merged into that call. Later keys win.
Response
Body is fully read when the response is wrapped. .text and .json() are synchronous on both Session types.
| Attribute | Type |
|---|---|
status_code |
int |
content |
bytes |
text |
str |
headers |
dict[str, str] |
cookies |
dict[str, str] |
url |
str |
http_version |
str | None |
raw |
native response |
session.cookies is the cookie jar as a dict. session.set_cookies(dict, url=None) writes into it.
License
Metadata
Release files for tlsreq 0.1.9
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| tlsreq-0.1.9.tar.gz | 34.0 kB | Without provenance | Details for tlsreq-0.1.9.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| tlsreq-0.1.9-py3-none-any.whl | Python 3 | none | any | Details for tlsreq-0.1.9-py3-none-any.whl |
Total release size: 65.0 kB
Release files / tlsreq-0.1.9.tar.gz
| Download URL | tlsreq-0.1.9.tar.gz |
|---|---|
| Size | 34.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
22e246d50a225ac2c18d106254c0d11d758f9d1b227cb975d3d9d4e5aaeb5398
|
|
BLAKE2b-256 checksum How to use checksums |
08ecffe8edc82cff6f05bfd90a0523d900f0c5fa47b9dd942e184d6cc2cc54f4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.15
|
Release files / tlsreq-0.1.9-py3-none-any.whl
| Download URL | tlsreq-0.1.9-py3-none-any.whl |
|---|---|
| Size | 31.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
04b26b5cd55f301a182e443cac6385003b6fc48eb3d65edb5183b70f52add49e
|
|
BLAKE2b-256 checksum How to use checksums |
c4a423838e76d9c4ea06b54f913d577851d613937d946b764ca4ac868c31d6c0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.15
|
Security for tlsreq 0.1.9
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.