Skip to main content

Send local HTTP requests with a byte-exact macOS Safari 26.5 network fingerprint (TLS/HTTP2/HPACK/headers).

Project description

never_safari (Python)

Send local HTTP requests with a byte-exact macOS Safari 26.5 network fingerprint — TLS ClientHello (JA3/JA4), HTTP/2 (SETTINGS/WINDOW_UPDATE/ pseudo-header order), HPACK (Huffman + dynamic table), request-header order, download flow-control cadence, and TLS-record framing — like curl_cffi, but for Safari. Built on a patched BoringSSL + a from-scratch HTTP/2 layer.

Install

pip install never_safari          # prebuilt wheels: macOS / Linux / Windows
# or from source (needs cmake, go, ninja, a C/C++ compiler):
pip install maturin && maturin develop -m crates/safari-py/Cargo.toml

Use — a requests-style API

import never_safari

# Session keeps cookies + a connection pool (like a browser). `Client` is an alias.
s = never_safari.Session()
r = s.get("https://tls.peet.ws/api/all", params={"pretty": "1"})
print(r.status_code, r.ok)
print(r.json()["tls"]["ja4"])       # t13d2013h2_a09f3c656075_7f0f34a4126d

# POST: json= takes a Python object; data= takes a dict (form) / str / bytes.
r = s.post("https://api.example.com/v1/items",
           json={"name": "x"},
           headers={"authorization": "Bearer TOKEN"})
r.raise_for_status()                # raises never_safari.HTTPError on 4xx/5xx

# Module-level, exactly like requests:
never_safari.get("https://example.com", params={"q": "1"})
never_safari.post("https://api.example.com", data={"k": "v"}, timeout=10)

# Session options
s = never_safari.Session(
    ios=False,            # iOS Safari 26 profile (no post-quantum MLKEM768)
    verify=True,          # TLS cert verification (like requests)
    proxies={"https": "http://user:pass@host:8080"},
    multiplex=True,       # browser-style: concurrent requests share one connection
    timeout=30.0, connect_timeout=10.0, max_redirects=10,
)

Matches requests' surface:

  • Verbs: get/post/put/patch/delete/head/options/request — on the Session and at module level.
  • Request kwargs: params=, data= (dict → form / str / bytes), json= (any object), headers=, cookies=, referer=.
  • Response: .status_code (.status alias), .ok, .reason, .headers, .content, .text, .json(), .url, .resumed, .cookies, .raise_for_status().
  • Cookies (dict-like, like curl_cffi / httpx): s.cookies["k"], s.cookies.get("k", domain=…, path=…), .get_dict(domain=…, path=…), .set("k", "v", domain=…, path=…), .delete("k", domain=…, path=…), .clear(domain=…, path=…), .update(), .keys()/.values()/.items(), "k" in s.cookies, dict(s.cookies); r.cookies for what a response set.
  • never_safari.HTTPError, Session (alias of Client).

The network call releases the GIL, so many Python threads can crawl concurrently.

Async — AsyncSession (like curl_cffi)

import asyncio, never_safari

async def main():
    async with never_safari.AsyncSession() as s:      # max_workers= bounds concurrency
        r = await s.get("https://example.com", params={"q": "1"})
        r = await s.post(url, json={"a": 1})
        results = await asyncio.gather(*[s.get(u) for u in urls])   # runs concurrently

asyncio.run(main())

Same verbs, kwargs, Response and .cookies as the sync Session; every verb is a coroutine. It runs the (GIL-releasing) sync core in a bounded thread pool, so requests run genuinely in parallel. AsyncClient is an alias.

See the project README for the full fingerprint details and scope.

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_safari-0.3.1-cp39-abi3-win_amd64.whl (1.4 MB view details)

Uploaded CPython 3.9+Windows x86-64

never_safari-0.3.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.5 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ x86-64

never_safari-0.3.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.4 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ ARM64

never_safari-0.3.1-cp39-abi3-macosx_11_0_arm64.whl (1.3 MB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

never_safari-0.3.1-cp39-abi3-macosx_10_12_x86_64.whl (1.4 MB view details)

Uploaded CPython 3.9+macOS 10.12+ x86-64

File details

Details for the file never_safari-0.3.1-cp39-abi3-win_amd64.whl.

File metadata

  • Download URL: never_safari-0.3.1-cp39-abi3-win_amd64.whl
  • Upload date:
  • Size: 1.4 MB
  • Tags: CPython 3.9+, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.11

File hashes

Hashes for never_safari-0.3.1-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 f44df5603ec2e86132b88808309116e7d2dc8cc959c5dbd8bcb7c017c0a06597
MD5 841b655f0e16efc7cf3a1728a9ea4bf6
BLAKE2b-256 2d2144b471c6211a086ee10dec897fa7cf02f473bdee8782ab613d28466dc314

See more details on using hashes here.

File details

Details for the file never_safari-0.3.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for never_safari-0.3.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 e03f160d7e7d1950054b00fa17c5fab9594477d02f51a5b13569a73e9b90b916
MD5 919de49eb6377df67ad861fc834773f0
BLAKE2b-256 6a4f17bd222c6330d93d9f1f86609a80f2e9b63892e6d5621c168d0f70be1627

See more details on using hashes here.

File details

Details for the file never_safari-0.3.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for never_safari-0.3.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 986e573ff902ece7abd3bac9e0c491bd7fd3f3928ba4433a91b24abafd1de973
MD5 3fd7b18646e6ec4ac5143df399c2d468
BLAKE2b-256 905c7db2cfe7f03f7455b2af3c1dc62bedf8ec3d76c951273203aee39bab63b2

See more details on using hashes here.

File details

Details for the file never_safari-0.3.1-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for never_safari-0.3.1-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 0b2b4d33c328d6b6046733c7fd389c87aa9cdd5b4bec7b58811d888ab7c3b27d
MD5 833d06a6bc50f3876713caf0220e69b1
BLAKE2b-256 ddcf647f4d2d21f7183b1cfd5e7b8d0ce1dd263006a9ef2b5109a5e03fd14b80

See more details on using hashes here.

File details

Details for the file never_safari-0.3.1-cp39-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for never_safari-0.3.1-cp39-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 cfc6f6a71cbb19db709eff6c004d706853f963cfde899a06216834a7feb751b1
MD5 5114534ce83d2818f27421877a82d909
BLAKE2b-256 9eadc966a77481a813825768ac7cac8ac83aa99c39ad5508933d5085b0ceb7c2

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