Skip to main content

Browser TLS fingerprint impersonation library powered by Rust (BoringSSL + hyper).

Project description

rqsession

中文 | English

A Python HTTP library that impersonates real browser TLS fingerprints, powered by a Rust native extension (BoringSSL + hyper + tokio).

PyPI version Python versions License


What it does

Most anti-bot systems (Cloudflare, Akamai, DataDome, etc.) inspect the TLS ClientHello and HTTP/2 SETTINGS frame to distinguish scrapers from real browsers. Standard requests or httpx produce a recognizable Python fingerprint regardless of what User-Agent you set.

rqsession controls the full fingerprint stack at the Rust level:

Layer What is controlled
TLS ClientHello Cipher suite order, supported groups (curves), ALPN, signature algorithms, version range
HTTP/2 SETTINGS frame values (window size, max frame size), connection WINDOW_UPDATE
HTTP headers Exact header order, browser-specific headers (sec-ch-ua, sec-fetch-*, etc.)

No external proxy process required — it's a compiled .pyd / .so extension, imported directly.


Installation

pip install rqsession

Pre-built wheels are available for Windows x86_64 and Linux x86_64 (Python 3.9+).
Other platforms require a local Rust toolchain to build from the source distribution.


Quick Start

Synchronous

from rqsession.rust_session import BrowserSession, Chrome120

with BrowserSession(Chrome120) as s:
    resp = s.get("https://httpbin.org/get")
    print(resp.status_code)   # 200
    print(resp.json())

Async

import asyncio
from rqsession.rust_session import AsyncBrowserSession, Chrome120

async def main():
    async with AsyncBrowserSession(Chrome120) as s:
        resp = await s.get("https://httpbin.org/get")
        print(resp.status_code)
        print(resp.json())

asyncio.run(main())

Concurrent async requests

import asyncio
from rqsession.rust_session import AsyncBrowserSession, Chrome120

async def main():
    async with AsyncBrowserSession(Chrome120) as s:
        results = await asyncio.gather(
            s.get("https://httpbin.org/get"),
            s.get("https://httpbin.org/ip"),
            s.get("https://httpbin.org/user-agent"),
        )
    for r in results:
        print(r.status_code)

asyncio.run(main())

Built-in Browser Profiles

Import name Browser OS
Chrome138 Chrome 138 Windows
Chrome120 Chrome 120 Windows
Chrome119 Chrome 119 Windows
Edge147 Edge 147 Windows
Edge142 Edge 142 Windows
Edge141 Edge 141 Windows
Firefox146 Firefox 146 Windows
Firefox133 Firefox 133 Windows
Tor128 Tor Browser 128 Windows
Safari17 Safari 17 macOS
MacosChrome140 Chrome 140 macOS
AndroidChrome114 Chrome 114 Android
Py37Aiohttp381 Python aiohttp 3.8.1 Windows
from rqsession.rust_session import (
    BrowserSession, AsyncBrowserSession,
    Chrome138, Chrome120, Chrome119,
    Edge147, Edge142, Edge141,
    Firefox146, Firefox133,
    Tor128, Safari17, MacosChrome140,
    AndroidChrome114, Py37Aiohttp381,
)

Each profile carries its own cipher suite order, curves, signature algorithms, HTTP/2 settings, and header order — matching the real browser's wire behavior.


Proxy Support

Both sync and async sessions accept a proxy URL at construction time:

# HTTP proxy
s = BrowserSession(Chrome120, proxy="http://127.0.0.1:7890")

# Authenticated proxy
s = BrowserSession(Chrome120, proxy="http://user:pass@host:port")

# Async
async with AsyncBrowserSession(Firefox133, proxy="http://127.0.0.1:7890") as s:
    resp = await s.get("https://example.com")

The proxy tunnel is implemented as an HTTP CONNECT connection at the TCP level, so TLS fingerprinting applies end-to-end through the tunnel.


Session API

Constructor parameters

BrowserSession(
    profile,              # built-in constant or BrowserProfile object
    *,
    proxy=None,           # "http://[user:pass@]host:port"
    verify=True,          # set False to skip SSL verification
    ca_bundle=None,       # path to CA bundle; auto-detects certifi when None
)
# AsyncBrowserSession takes the same parameters

Request methods

# GET
resp = s.get(url, headers={...}, params={...})

# POST — form data or JSON
resp = s.post(url, data=b"...", headers={...})
resp = s.post(url, json={"key": "value"})

# Generic
resp = s.request("PUT", url, headers={...}, json={...})

# Async versions — same signature, add `await`
resp = await s.get(url)
resp = await s.post(url, json={...})

Response object

Compatible with requests.Response style:

resp.status_code    # int
resp.text           # str (auto-decoded)
resp.content        # bytes
resp.headers        # dict[str, str]
resp.json()         # parsed JSON → dict / list
resp.ok             # True when status < 400
resp.raise_for_status()   # raises on 4xx/5xx
resp.url            # final URL after redirects

Response bodies are automatically decompressed (gzip, deflate, br, zstd).

Cookies

# Persist cookies manually
s.update_cookies({"token": "abc123"})

# Cookies from Set-Cookie response headers are automatically
# stored in the session and sent on subsequent requests.

Adding Custom Browser Profiles

Capture a fingerprint from a real browser using tls.peet.ws/api/all, then convert it:

# Save output from tls.peet.ws as chrome136.json, then:
python tools/tls_peet_to_profile.py chrome136.json -n chrome136_windows --install

The --install flag writes the profile directly to rqsession/rust_session/profiles/builtin/.
You can also load profiles at runtime without rebuilding:

from rqsession.rust_session import BrowserSession, load_custom, load_profile_json
from rqsession._rust_core import load_profile

# From profiles/custom/<name>.json
s = BrowserSession(load_custom("my_browser"))

# From a JSON string
s = BrowserSession(load_profile_json('{"name": "...", "tls": {...}, ...}'))

# From an arbitrary file path
s = BrowserSession(load_profile("/path/to/profile.json"))

# List available profiles
from rqsession.rust_session import list_builtin, list_custom
print(list_builtin())   # ['chrome120_windows', 'firefox133_windows', ...]
print(list_custom())    # ['my_browser', ...]

Windows asyncio note

Python 3.8+ on Windows uses ProactorEventLoop by default. If you see event-loop errors, switch to SelectorEventLoop before asyncio.run():

import asyncio, sys

if sys.platform == "win32":
    asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())

asyncio.run(main())

Legacy layers

Earlier versions of this library included RequestSession and EnhancedRequestSession. These layers are still available for backward compatibility:

from rqsession import RequestSession          # basic requests.Session wrapper
from rqsession import EnhancedRequestSession  # requests.Session wrapper with browser headers

For new projects, use BrowserSession / AsyncBrowserSession instead — they are faster, require no external process, and provide more accurate fingerprinting.


License

Apache 2.0 — see LICENSE.

Project details


Download files

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

Source Distribution

rqsession-0.4.6.tar.gz (275.4 kB view details)

Uploaded Source

Built Distributions

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

rqsession-0.4.6-cp38-abi3-win_amd64.whl (2.1 MB view details)

Uploaded CPython 3.8+Windows x86-64

rqsession-0.4.6-cp38-abi3-manylinux_2_28_x86_64.whl (2.2 MB view details)

Uploaded CPython 3.8+manylinux: glibc 2.28+ x86-64

rqsession-0.4.6-cp38-abi3-manylinux_2_28_aarch64.whl (2.1 MB view details)

Uploaded CPython 3.8+manylinux: glibc 2.28+ ARM64

File details

Details for the file rqsession-0.4.6.tar.gz.

File metadata

  • Download URL: rqsession-0.4.6.tar.gz
  • Upload date:
  • Size: 275.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.14.0

File hashes

Hashes for rqsession-0.4.6.tar.gz
Algorithm Hash digest
SHA256 ebd6ee3ba96e1ce1b9e97c83d1a99434f3bac08967f0fc45e08acb46bfb765d4
MD5 208c95dd9749ef49ee69f719fe098814
BLAKE2b-256 7cdcca86f3bd494125df1a67bb95326baf7e0f643616101b0122c3325bab55a7

See more details on using hashes here.

File details

Details for the file rqsession-0.4.6-cp38-abi3-win_amd64.whl.

File metadata

  • Download URL: rqsession-0.4.6-cp38-abi3-win_amd64.whl
  • Upload date:
  • Size: 2.1 MB
  • Tags: CPython 3.8+, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.14.0

File hashes

Hashes for rqsession-0.4.6-cp38-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 f76d380aac7f757a42a68a950841e56df48260a3a69a81774f3744503da663eb
MD5 d02b3c3b3a2f3d7af7d6398cbbe21a35
BLAKE2b-256 f203f879e53d830d9a6f2568a7dd9287c51735e31b47bd9d6f5ee5b62c5a6750

See more details on using hashes here.

File details

Details for the file rqsession-0.4.6-cp38-abi3-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for rqsession-0.4.6-cp38-abi3-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 619094208f532726bd2c7012a290abba0b54d39e760261eefe7f6c9a9f9f0524
MD5 9171751fb945a3f171624dd949d8cbd7
BLAKE2b-256 c8c6d26748b4fc39fe7112fe54132bf9e3d02ff7a6e2590627075113b5007d9d

See more details on using hashes here.

File details

Details for the file rqsession-0.4.6-cp38-abi3-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for rqsession-0.4.6-cp38-abi3-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 eca6c6c1d5ce4f9e6276cd4b2b26549e9548ae2027bbd4286edea874683c4462
MD5 166ff73d7f174aeef64b043692856c22
BLAKE2b-256 4b02266e532edf88a6b42fe4ba41dcb2ce69b232d10dfc776a5a3c160c278457

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