Skip to main content

HTTP client with TLS fingerprint control, backed by azuretls-client. Installed as `pyhttpz`, imported as `httpz`.

Project description

httpz logo

httpz

An HTTP client for Python with first-class TLS fingerprint control.

PyPI Python versions License Discord

📖 Documentation  ·  Examples  ·  Presets  ·  Benchmarks  ·  Discord


Most Python HTTP clients let you set headers. httpz lets you set the TLS handshake itself — hand it a JA3 string and the ClientHello on the wire is rewritten to match it, byte for byte. Same goes for the HTTP/2 (Akamai) fingerprint. And since the API is shaped like httpx, porting existing code is usually just a change of import.

The short version: pass impersonate="chrome131" and your request looks like Chrome — its TLS fingerprint, its HTTP/2 fingerprint, its User-Agent, and the exact headers it sends, in the order it sends them. Not just a spoofed User-Agent string.

Under the hood it wraps azuretls-client (Go) as a shared library, so there's a real, battle-tested TLS engine behind the Pythonic surface.

import httpz

with httpz.Client(
    ja3="771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,0-23-65281-10-11-35-16-5-13-18-51-45-43-27-17513,29-23-24,0",
    browser="chrome",
) as client:
    r = client.get("https://tls.peet.ws/api/all")
    print(r.json())   # the JA3 you set is the JA3 the server sees

Why httpz

The existing options — curl_cffi, tls_client, patched pycurl — mostly hand you a fixed menu of browser presets, or some low-level knob arrangement that breaks the next time you upgrade. httpz takes the other approach: give it any JA3 string and it just works. No preset enum to wait on, no rebuild step, no urllib3 fork to maintain — ja3="..." on the constructor and you're done.

And it's still a normal HTTP client underneath. Sync and async, sessions with cookie jars, proxies (http / https / socks5), HTTP/2, and an httpx-shaped request/response API. You don't give up the everyday conveniences to get the fingerprinting.


Features

TLS fingerprint control

  • Custom JA3 — supply any JA3 fingerprint string and httpz reproduces the exact ClientHello (cipher suites, extensions, elliptic curves, point formats) at the TLS layer.
  • Custom HTTP/2 (Akamai) fingerprint — set SETTINGS, WINDOW_UPDATE, header pseudo-header ordering, and priority frames via a single Akamai-format string.
  • Browser presetschrome, firefox, safari, edge, opera, ios for one-line spoofing without writing a JA3 by hand.
  • impersonate="..." — 170 pre-canned browser presets covering Chrome, Firefox, Safari, Edge and Opera (see Impersonate presets below). Each preset also sends that browser's real default request headers (client hints, Accept, Sec-Fetch-*, …), so the request matches a browser at the HTTP layer too — not just the TLS/HTTP2 handshake.
  • Apply at runtimeclient.apply_ja3(...) and client.apply_h2_fingerprint(...) reconfigure a live session without rebuilding it.
client = httpz.Client(browser=httpz.CHROME)
client.apply_ja3("771,4865-...", browser="chrome")
client.apply_h2_fingerprint("1:65536;2:0;4:6291456;6:262144|15663105|0|m,s,a,p")

Impersonate presets

impersonate="chrome131" is a one-shot shorthand that sets JA3 + Akamai (H2) fingerprint + User-Agent + browser navigator all at once:

with httpz.Client(impersonate="chrome131") as c:
    r = c.get("https://tls.peet.ws/api/all")
    print(r.json()["tls"]["ja3_hash"])  # matches the chrome131 profile exactly

# Some versions ship more than one distinct on-the-wire profile (e.g. a
# different TLS extension order). They live under sibling names like
# `chrome131`, `chrome_131` and `chrome131a` — each a real, distinct handshake.
with httpz.Client(impersonate="chrome_131") as c:
    ...

# Any explicit kwarg overrides the preset
with httpz.Client(impersonate="chrome131", user_agent="MyBot/1.0") as c:
    ...

170 unique browser profiles (219 names total once aliases are counted — names like safari17_0 and safari_17.0 resolve to the same canonical profile because the bytes-on-the-wire are identical).

Browser default headers

A real Chrome request isn't just a TLS handshake — it also carries a recognizable set of HTTP headers (sec-ch-ua, Accept, Sec-Fetch-*, Accept-Language, priority, …). A request with a perfect JA3 but none of those headers is still easy to flag as non-browser.

So whenever a browser navigator is active (impersonate= or browser=), httpz automatically sends that browser's default headers, with values derived from the preset (e.g. the sec-ch-ua version and Accept-Encoding track the Chrome version; the platform/mobile hints track the User-Agent):

with httpz.Client(impersonate="chrome146") as c:
    c.get("https://tls.peet.ws/api/all")
# sends sec-ch-ua / sec-ch-ua-mobile / sec-ch-ua-platform /
# upgrade-insecure-requests / accept / sec-fetch-* /
# accept-encoding / accept-language / priority — like real Chrome

The headers (including User-Agent) are emitted in each browser's natural order — e.g. Chrome/Edge/Opera place user-agent right after upgrade-insecure-requests, while Firefox and Safari lead with it — so the on-the-wire header order matches a real browser, not just the header set.

Anything you pass in headers= overrides a default per key (keeping the browser's header order); extra headers are appended. To send only the headers you specify, pass browser_headers=False:

# Override one default, add one of your own — the rest of Chrome's headers stay
httpz.Client(impersonate="chrome146", headers={"accept-language": "fr-FR,fr;q=0.9"})

# Opt out entirely
httpz.Client(impersonate="chrome146", browser_headers=False)

Firefox and Safari presets send their own (client-hint-free) header sets accordingly.

Every profile you can impersonate

All 170 profiles, grouped by browser — click to expand
Chrome (78)

chrome99, chrome99_android, chrome100, chrome101, chrome104, chrome106a, chrome107, chrome107a, chrome108a, chrome109a, chrome110, chrome110a, chrome114a, chrome116, chrome116a, chrome117a, chrome118a, chrome119, chrome119a, chrome120, chrome120a, chrome123, chrome123a, chrome124, chrome124a, chrome126a, chrome127a, chrome128a, chrome129a, chrome130a, chrome131, chrome131_android, chrome131a, chrome132, chrome133a, chrome133b, chrome134, chrome135, chrome136, chrome136a, chrome137, chrome138, chrome139, chrome140, chrome141, chrome142, chrome142a, chrome143, chrome144, chrome145, chrome145a, chrome146, chrome146a, chrome147, chrome148, chrome_100, chrome_101, chrome_104, chrome_105, chrome_106, chrome_107, chrome_108, chrome_109, chrome_114, chrome_116, chrome_117, chrome_118, chrome_119, chrome_120, chrome_123, chrome_124, chrome_126, chrome_127, chrome_128, chrome_129, chrome_130, chrome_131, chrome_133

Firefox (20)

firefox133, firefox135, firefox136, firefox139, firefox142, firefox143, firefox144, firefox145, firefox146, firefox147, firefox148, firefox149, firefox151, firefox_109, firefox_117, firefox_128, firefoxandroid135, firefoxprivate135, firefoxprivate136, tor145

Safari (34)

safari26, safari153, safari155, safari170, safari172_ios, safari180, safari180_ios, safari183, safari184, safari184_ios, safari185, safari260, safari260_ios, safari261, safari262, safari1831, safari2601, safari_15.3, safari_15.5, safari_15.6.1, safari_16, safari_16.5, safari_17.2.1, safari_17.4.1, safari_17.5, safari_18.2, safari_ios_16.5, safari_ios_17.4.1, safari_ios_18.1.1, safari_ipad_18, safariios26, safariios262, safariipad26, safariipad262

Edge (23)

edge99, edge101, edge122a, edge127a, edge131a, edge134, edge135, edge136, edge137, edge138, edge139, edge140, edge141, edge142, edge143, edge144, edge145, edge146, edge147, edge_101, edge_122, edge_127, edge_131

Opera (15)

opera116, opera117, opera118, opera119, opera120, opera121, opera122, opera123, opera124, opera125, opera126, opera127, opera128, opera129, opera130

How name lookup works

Names are normalized before lookup, so all of these resolve to the same profile: chrome131, chrome_131, Chrome131, CHROME131 (after normalization that strips underscores/dots and lowercases). When a browser version has more than one distinct handshake on the wire, each variant keeps its own name (a sibling suffix like _131 or 131a) so every unique profile stays reachable.

List everything at runtime:

import httpz
print(httpz.list_impersonate_targets())          # every resolvable name
print(httpz.resolve_impersonate("chrome131"))    # full preset dict

Refreshing the presets

The presets are embedded directly in httpz/presets.py (as a Python dict, so compiled/bundled builds pick them up automatically — no separate data file to include) and are generated by scripts/scrape_fingerprints.py.

# Full rebuild from all sources (drops manual entries):
pip install -U curl_cffi primp wreq
python scripts/scrape_fingerprints.py

# Or add ONLY new profiles from one source on top of the current presets,
# skipping any whose fingerprint already exists (keeps manual entries):
python scripts/scrape_fingerprints.py --augment --only wreq

The scraper enumerates every impersonate target each library exposes, makes a real request through that library to https://tls.peet.ws/api/all, captures the JA3 + Akamai fingerprint + User-Agent the server saw, dedupes any names that produce byte-identical handshakes, and regenerates httpz/presets.py with the result embedded as a Python dict. In --augment mode a freshly scraped profile is added only when its (ja3, h2_fingerprint, user_agent) isn't already present; duplicates are skipped so nothing is stored twice. Manually-added profiles (the source: "manual" entries) are preserved by --augment but dropped by a full rebuild — keep a backup if you've curated any.

A note on TLS extension 41 (pre_shared_key)

If you paste in a JA3 captured from a live browser session that includes extension 41 at the end of the extension list, strip it before saving the preset. TLS 1.3 pre_shared_key is only valid in a ClientHello when accompanied by real session-resumption material — without it the server rejects the handshake. curl_cffi/utls/azuretls all drop it on the way out, so the resulting JA3 on the wire never contains 41. The dedupe step in scripts/scrape_fingerprints.py doesn't strip extensions — you'd do that by hand when adding a manual preset.

Sync and async clients

  • httpz.Client — blocking, with-context safe, modeled after httpx.Client.
  • httpz.AsyncClientasync with-context safe, mirrors httpx.AsyncClient. Runs the FFI bridge calls in a thread pool so it never blocks the event loop.
# Sync
with httpz.Client() as c:
    r = c.get("https://example.com")

# Async
async with httpz.AsyncClient() as c:
    r = await c.get("https://example.com")

Module-level shortcuts

httpz.get, httpz.post, httpz.put, httpz.patch, httpz.delete, httpz.head, httpz.options — for one-off calls that build, use, and dispose of a client in one line.

Request features

  • HTTP methods: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS.
  • JSON bodies: client.post(url, json={...}) — automatic serialization and Content-Type.
  • Form bodies: client.post(url, data={...}) — URL-encoded with the right Content-Type.
  • Raw bytes: client.post(url, content=b"...") for arbitrary payloads.
  • Query params: client.get(url, params={"q": "x"}) — merged with any existing query string.
  • Headers: defaults set on the client, plus per-request overrides; case-insensitive multi-dict.
  • Cookies: a Cookies jar that auto-syncs with Set-Cookie responses and re-sends on subsequent requests.
  • Redirects: follow_redirects and max_redirects per request.
  • Timeouts: client-default or per-request (timeout=... in seconds).
  • TLS verify toggle: verify=False for self-signed certs in dev.

Sessions, proxies, and networking

  • Proxy support: proxy="http://...", "https://...", or "socks5://...". Settable at construction or via set_proxy(...) / clear_proxy().
  • Cookie persistence within the session (managed by the Go-side jar).
  • HTTP/2 by default when the server negotiates it.
  • User-Agent override at the client level.

Response API

A response object modeled after httpx.Response:

  • r.status_code, r.ok, r.is_success
  • r.text, r.content (bytes), r.json()
  • r.headers (Headers multi-dict), r.cookies (Cookies)
  • r.url, r.http_version
  • r.raise_for_status()

Exceptions

A small, structured exception tree rooted at HTTPZError:

TransportError, BridgeError, TimeoutError, ProxyError, TooManyRedirects, ConnectionError, HTTPStatusError.


Quick examples

# 1. Browser-emulated GET (using a pre-canned impersonate preset)
with httpz.Client(impersonate="chrome131") as c:
    r = c.get("https://tls.peet.ws/api/all")
    print(r.json()["tls"]["ja3_hash"])

# 2. POST JSON through a SOCKS5 proxy
with httpz.Client(proxy="socks5://user:pass@127.0.0.1:1080") as c:
    r = c.post("https://api.example.com/v1/items", json={"name": "x"})
    r.raise_for_status()

# 3. Custom JA3 + custom H2 fingerprint
with httpz.Client(
    ja3="771,4865-4867-...",
    h2_fingerprint="1:65536;...|15663105|0|m,s,a,p",
    browser="chrome",
) as c:
    print(c.get("https://example.com").status_code)

# 4. Async, with cookie persistence
async with httpz.AsyncClient() as c:
    await c.get("https://httpbin.org/cookies/set?session=abc")
    r = await c.get("https://httpbin.org/cookies")
    assert r.json()["cookies"]["session"] == "abc"

Benchmarks

The benchmarks/ directory compares httpz against httpx, requests, curl_cffi, primp, and aiohttp across four scenarios. Run it yourself with python benchmarks/run_all.py. The numbers below were measured against httpbin.org (which rate-limits aggressively — expect noise, especially in the long tails).

Sequential GETs — 50 requests, one client

Library Total (s) req/s mean (ms) p95 (ms) errors
requests 11.64 4.3 232.8 236.6 0
curl_cffi 11.82 4.2 236.5 238.8 0
httpx 11.86 4.2 237.2 241.6 0
httpz_async 12.27 4.1 245.5 256.6 0
aiohttp 12.31 4.1 246.2 248.8 0
httpx_async 12.31 4.1 246.2 249.3 0
httpz 12.37 4.0 247.3 259.3 0
curl_cffi_async 12.56 4.0 251.1 256.2 0
primp 182.16 0.2 3643.3 15008.8 7

Steady-state, everything is network-bound and clusters within ~10ms of each other. httpz adds ~15ms over the fastest sync client per request — a tiny price for the FFI hop into Go.

Concurrent GETs — 50 requests, concurrency 10

Library Total (s) req/s mean (ms) p95 (ms) errors
curl_cffi_async 1.50 33.4 273.7 476.5 0
httpx_async 2.01 24.8 379.7 1001.9 0
aiohttp 2.02 24.8 376.3 1018.4 0
httpz (sync) 10.06 5.0 1952.3 3664.3 0
httpx (sync) 10.74 4.7 1867.4 3382.3 0
requests 22.77 2.2 3901.8 9821.8 0
httpz_async 31.97 1.3 4960.7 15007.1 10
primp 34.69 1.0 5756.2 15013.9 15
curl_cffi 35.26 1.4 5363.4 13200.7 1

Sync httpz beats sync httpx and is ~2.3× faster than requests under load. The native async clients (aiohttp, httpx_async, curl_cffi_async) win on throughput because their concurrency is in-process rather than thread-bounded. httpz_async ran into httpbin rate-limiting (10 timeouts) on this pass.

Cold-start — 10 iterations of (construct + 1 GET)

Library Total (s) req/s mean (ms) p95 (ms) errors
curl_cffi_async 7.25 1.4 725.3 754.1 0
httpz 11.17 0.9 1117.1 1596.7 0
aiohttp 12.21 0.8 1220.6 1863.9 0
httpx 20.05 0.5 2004.5 3619.5 0
requests 24.22 0.4 2421.5 3839.2 0
httpx_async 31.67 0.3 3166.9 10184.0 1
curl_cffi 33.41 0.3 3340.9 8017.2 0
primp 36.25 0.3 3625.5 9521.1 0
httpz_async 79.58 0.1 7957.9 15009.7 3

httpz comes in second only to curl_cffi_async for cold-start cost — better than httpx, requests, primp, and the sync curl_cffi. Useful if you spin up short-lived clients in a CLI or worker.

Sequential POST + JSON — 50 requests

Library Total (s) req/s mean (ms) p95 (ms) errors
primp 11.56 4.3 231.2 236.6 0
httpz_async 11.83 4.2 236.5 250.2 0
curl_cffi 11.87 4.2 237.5 247.8 0
httpx 12.18 4.1 243.6 247.6 0
httpz 12.22 4.1 244.3 253.1 0
httpx_async 12.64 4.0 252.8 256.9 0
requests 173.81 0.3 3476.1 15009.0 4
curl_cffi_async 181.52 0.2 3630.4 15009.0 6
aiohttp 202.47 0.2 4049.5 15616.0 5

httpz handles POST + JSON serialization within the same ~12s band as the other healthy clients. requests, aiohttp, and curl_cffi_async hit httpbin's POST rate limit hard on this pass.

Takeaways

  • Steady-state per-request overhead is essentially the network. All libraries that didn't get rate-limited finished within ~10 ms of each other per request.
  • Sync concurrency: httpz outperforms httpx and is roughly 2.3× faster than requests.
  • Cold-start: httpz is second only to curl_cffi_async, beating every other sync client and most async ones.
  • Async: aiohttp / httpx_async / curl_cffi_async are the throughput kings for non-fingerprinted workloads.

If you need TLS fingerprint control, httpz is competitive on every axis — and the only Python library where you can hand it any JA3 string with no setup ceremony.

To reproduce: python benchmarks/run_all.py (or, for stable numbers, point it at a local server with --url http://127.0.0.1:8000/).


Installation

pip install pyhttpz

The PyPI distribution name is pyhttpz (the bare httpz name was already taken on PyPI). The Python import name is unchanged — once installed, you still write import httpz.

The wheel ships with the prebuilt httpz_bridge shared library for Windows, Linux, and macOS.


API Reference

httpz.Client

A synchronous, session-scoped HTTP client with first-class TLS-fingerprint control. Modeled after httpx.Client so most existing httpx code ports over by changing the import.

Under the hood, every Client owns a session inside the Go-side azuretls-client runtime (reached via a thin CGO bridge). That session holds the TLS spec, HTTP/2 spec, cookie jar, default headers, proxy, and connection pool — so multiple requests through the same Client reuse connections and share cookie state, exactly like a requests.Session or httpx.Client. When you close the client (explicitly via .close(), by exiting a with block, or when it's garbage-collected) the Go-side session is torn down and its sockets are released.

Construction

httpz.Client(
    *,
    headers=None,           # default headers for every request
    cookies=None,           # initial cookie jar (dict or httpz.Cookies)
    proxy=None,             # "http://...", "https://...", or "socks5://..."
    ja3=None,               # JA3 fingerprint string (requires `browser`)
    h2_fingerprint=None,    # Akamai-format HTTP/2 fingerprint
    browser=None,           # "chrome" | "firefox" | "safari" | "edge" | "opera" | "ios"
    user_agent=None,        # overrides the navigator's default UA
    impersonate=None,       # one-shot preset (e.g. "chrome131") — sets ja3+h2+UA+browser
    timeout=None,           # default request timeout, seconds (float)
    max_redirects=10,       # global cap on redirect chain length
    verify=True,            # set False to skip TLS cert validation (dev only)
)
Argument Type What it does
headers dict | list | Headers Default headers merged into every request. Per-request headers= overrides on a key-by-key basis.
cookies dict | Cookies Pre-populated cookie jar. Cookies sent by the server are added automatically.
proxy str Upstream proxy. Schemes: http, https, socks5.
ja3 str JA3 client fingerprint — rewrites the TLS ClientHello to match. Requires browser=.
h2_fingerprint str Akamai HTTP/2 fingerprint — controls SETTINGS, WINDOW_UPDATE, pseudo-header order, and PRIORITY frames.
browser str Navigator family that backs the JA3/HTTP/2 stack. Module constants exist: httpz.CHROME, FIREFOX, SAFARI, EDGE, OPERA, IOS.
user_agent str Overrides the default User-Agent.
impersonate str Shorthand that resolves to a full preset (ja3 + h2_fingerprint + browser + user_agent). Any other explicit kwarg you pass still wins over the preset.
timeout float Default per-request timeout in seconds. Per-request timeout= overrides.
max_redirects int Maximum redirect-chain length before raising TooManyRedirects.
verify bool When False, TLS certificate verification is skipped. Useful for self-signed certs in development; never ship False to production.

Lifecycle

  • Use as a context manager (with httpz.Client() as c:) — the session is closed on exit.
  • Or call .close() explicitly. After .close() any further request raises HTTPZError("Client is closed").
  • A __del__ finalizer attempts a best-effort cleanup if you forget — don't rely on it.

HTTP methods

All return a httpz.Response.

Method Signature
client.request(method, url, **kw) Full-featured request — every other method is sugar over this.
client.get(url, **kw) GET.
client.post(url, **kw) POST.
client.put(url, **kw) PUT.
client.patch(url, **kw) PATCH.
client.delete(url, **kw) DELETE.
client.head(url, **kw) HEAD.
client.options(url, **kw) OPTIONS.

Shared **kw for every method:

Keyword Type Meaning
headers dict | list | Headers Per-request headers (merged on top of client defaults; per-request keys win).
params dict[str, str] Query-string parameters; merged with any query string already on url.
json Any JSON-serialized into the body; sets Content-Type: application/json.
data dict | str | bytes Form data when dict (application/x-www-form-urlencoded); raw otherwise.
content bytes Raw request body for binary payloads.
timeout float Override the client-default timeout for this call only.
follow_redirects bool Defaults to True. Set False to surface 3xx responses directly.
max_redirects int Per-request redirect cap.

Configuration methods

Reconfigure a live session without rebuilding it. Useful when rotating fingerprints or proxies between requests.

Method Purpose
client.apply_ja3(ja3, browser) Replace the active JA3 fingerprint.
client.apply_h2_fingerprint(fp) Replace the active HTTP/2 fingerprint.
client.set_proxy(url) Route subsequent requests through a new proxy.
client.clear_proxy() Stop using a proxy.

Attributes

  • client.headers — mutable Headers instance for the client's default headers (case-insensitive multi-dict).
  • client.cookies — the session Cookies jar. Read after a response to inspect what the server set; mutate to inject your own.

Example — everything together

import httpz

with httpz.Client(
    impersonate="chrome131",
    proxy="socks5://user:pass@127.0.0.1:1080",
    timeout=30.0,
    headers={"Accept-Language": "en-US,en;q=0.9"},
) as client:
    client.cookies["session"] = "abc123"
    r = client.get("https://api.example.com/me")
    r.raise_for_status()
    print(r.json())

    # Rotate the TLS fingerprint mid-session
    client.apply_ja3("771,4865-4867-...", browser="chrome")
    r2 = client.post("https://api.example.com/items", json={"name": "x"})

httpz.AsyncClient

The asyncio-friendly counterpart to Client. Mirrors httpx.AsyncClient — same API surface, every I/O method is an async def that you await.

AsyncClient is implemented as a thin async wrapper around Client: it constructs a sync Client internally, and every request hops into a worker thread via asyncio.to_thread so the blocking CGO call never stalls the event loop. The thread-pool hand-off means async throughput is bounded by asyncio's default thread pool size (typically min(32, os.cpu_count() + 4)) — fine for most workloads, but worth knowing if you're firing hundreds of concurrent requests. For raw event-loop-native concurrency on non-fingerprinted workloads, libraries like aiohttp or httpx_async will be faster (see the Benchmarks section).

Construction

Takes the exact same keyword arguments as Client (see the table above) — they're forwarded verbatim.

client = httpz.AsyncClient(
    impersonate="chrome131",
    proxy="http://127.0.0.1:8080",
    timeout=15.0,
)

Lifecycle

  • Use as an async context manager: async with httpz.AsyncClient() as c: — the session is closed on exit.
  • Or await client.close() explicitly.

HTTP methods

All async. All return a httpz.Response. Accept the same **kw as the sync client.

await client.request(method, url, **kw)
await client.get(url, **kw)
await client.post(url, **kw)
await client.put(url, **kw)
await client.patch(url, **kw)
await client.delete(url, **kw)
await client.head(url, **kw)
await client.options(url, **kw)

Configuration methods

await client.apply_ja3(ja3, browser)
await client.apply_h2_fingerprint(fp)
await client.set_proxy(url)
await client.clear_proxy()

Attributes

  • client.headers — shared with the underlying sync client.
  • client.cookies — shared with the underlying sync client.

Example

import asyncio
import httpz

async def main():
    async with httpz.AsyncClient(impersonate="chrome131") as client:
        # Fan out 20 concurrent requests
        urls = [f"https://httpbin.org/anything/{i}" for i in range(20)]
        responses = await asyncio.gather(*(client.get(u) for u in urls))
        for r in responses:
            print(r.status_code, r.url)

asyncio.run(main())

Credits

  • httpz is written and maintained by Shahzain345.
  • The async client design takes cues from aiohttp — credit to the aio-libs team for one of the best async HTTP libraries in any language; their work shaped how Python developers think about async HTTP.
  • The TLS engine is azuretls-client by Noooste — httpz would not exist without it.
  • API surface modeled after httpx.

License

MIT.

Copyright © 2026 Shahzain345. All rights reserved.

httpz is written and maintained by Shahzain345. See Credits for the upstream libraries it builds on.

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

pyhttpz-0.1.2.tar.gz (26.1 MB view details)

Uploaded Source

Built Distribution

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

pyhttpz-0.1.2-py3-none-any.whl (26.6 MB view details)

Uploaded Python 3

File details

Details for the file pyhttpz-0.1.2.tar.gz.

File metadata

  • Download URL: pyhttpz-0.1.2.tar.gz
  • Upload date:
  • Size: 26.1 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.5

File hashes

Hashes for pyhttpz-0.1.2.tar.gz
Algorithm Hash digest
SHA256 a54e3973067cd08b8dd62df9e353fade2b5ecd26d73aa3fbe5ab681e2da30f90
MD5 1a36b0ceefbb2b5b86bb459e382aee69
BLAKE2b-256 931e74dad3e37318c406f935d219030130f175caaa3d77772498de5ae532f46b

See more details on using hashes here.

File details

Details for the file pyhttpz-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: pyhttpz-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 26.6 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.5

File hashes

Hashes for pyhttpz-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 2a753676e106c227c5e846a2d7e2fb0d9c79aa638208710d94aa68e8e087c4fe
MD5 c355a54fe0ba402f41c1d1f0658884f0
BLAKE2b-256 0cc1d8ff2da2fed87cdb01677ca7f2a2b6358c694ccdc29d0904139dfc4c0b05

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