punkreq
punkreq is an async HTTP client for Python, built on top of httpunk.
Warning: punkreq is in an early stage and still work in progress.
Note: punkreq was built with substantial help from LLMs, under human supervision.
In a nutshell
- Async only, with multiple runtime backends: import the client from the
module matching your runtime –
punkreq.asyncioorpunkreq.tonio - HTTP/1.1 and HTTP/2, negotiated via TLS ALPN by default; HTTP/2 prior
knowledge with
http1=False - Connection pooling with keep-alive (h1) and multiplexing (h2)
- Transparent response decompression: gzip and deflate everywhere, zstd on
Python 3.14+, brotli with the
punkreq[brotli]extra - Conservative automatic retries — only requests the server provably never processed (HTTP/2 graceful GOAWAY, refused streams, keep-alive races)
- Opt-in cookie jar, basic/bearer auth, multipart uploads
- HTTP proxies:
HTTP_PROXY/HTTPS_PROXY/NO_PROXYenvironment support, CONNECT tunneling for https destinations. - Zero runtime dependencies beyond httpunk
Installation
pip install punkreq
Quickstart
import asyncio
from punkreq.asyncio import Client
async def main():
async with Client(base_url="https://api.example.com") as client:
response = await client.post("/items", json={"name": "widget"})
response.raise_for_status()
print(await response.json())
asyncio.run(main())
One-off requests without managing a client:
from punkreq import asyncio as punkreq
response = await punkreq.get("https://www.example.com")
print(response.status_code, response.headers["content-type"])
Responses resolve as soon as the head arrives; the body is read on demand —
await response.read() / text() / json(), or streamed:
async with Client() as client:
response = await client.get("https://example.com/large.bin")
async for chunk in response.iter_bytes(chunk_size=65536):
...
Reading to the end releases the connection automatically. When you might stop early, use the request as a context manager so the response is always closed:
async with client.get("https://example.com/huge.ndjson") as response:
async for line in response.iter_lines():
if found(line):
break # the block exit closes the response and frees the connection
Configuration
import punkreq
from punkreq.asyncio import Client
client = Client(
base_url="https://api.example.com",
headers={"x-api-key": "..."},
auth=("user", "pass"), # or punkreq.BearerAuth("token")
cookies={}, # enables the cookie jar (off by default)
timeout=punkreq.Timeout(5.0, total=30.0), # no timeouts by default
limits=punkreq.Limits(max_connections=100),
proxy="http://proxy.internal:3128", # env vars honored by default
verify=True, # bool | CA bundle path | ssl.SSLContext
)
By default: redirects on (max 10), no timeouts, no cookie jar unless requested, HTTP/2 enabled, 90s keep-alive expiry, unlimited connections.
Timeout has four independent fields — total (a deadline for the whole
request, redirects included), connect, read and pool. There is no write
timeout: request bodies are written full-duplex from background tasks, so
total is the bound for slow uploads.
Backends
punkreq never asks for a backend at call sites — pick it by import:
from punkreq.asyncio import Client # asyncio, available everywhere
from punkreq.tonio import Client # tonio, free-threaded CPython >= 3.14 on Unix
License
punkreq is released under the BSD License.
Metadata
Release files for punkreq 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| punkreq-0.2.1.tar.gz | 68.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| punkreq-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 119.1 kB
Release files / punkreq-0.2.1.tar.gz
| Download URL | punkreq-0.2.1.tar.gz |
|---|---|
| Size | 68.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
81020a1f610a7f70696beb4a17a50087fe4e6a7a09476734298491bea4506491
|
|
BLAKE2b-256 checksum How to use checksums |
097b924e616ac50db04041f31164858fde2c522c7a450fb25297f650d9ee7e2c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.
Transparency logRelease files / punkreq-0.2.1-py3-none-any.whl
| Download URL | punkreq-0.2.1-py3-none-any.whl |
|---|---|
| Size | 50.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b0e8943b85668459ac7d90bd0f08f79fb5d395734bb5e926778704f42d4e2862
|
|
BLAKE2b-256 checksum How to use checksums |
84e70653595124083009a899289650ec95bf3aca02df7cbfe8d4d5adde7e3adf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.
Transparency log