Typed, resilient HTTP clients for Python, sync and async.
Why httpware
- A 4xx or 5xx response raises an exception named after its status, such as
NotFoundErrorfor 404 orRateLimitedErrorfor 429. All of them subclasshttpware.StatusError, so you never callraise_for_status(). response_model=Userdecodes the body into your pydantic or msgspec type. If no installed decoder handles the type, the call fails before the request is sent.- Retry with a retry budget, bulkhead, circuit breaker, and timeout ship as middleware you compose per client.
httpware is a thin layer over httpx2: requests and responses are plain
httpx2.Request and httpx2.Response objects.
Status: Pre-1.0. Public API is subject to change between minor releases until v1.0.
Install
pip install httpware # core only, no decoder
pip install httpware[pydantic] # PydanticDecoder: BaseModel, dataclasses, primitives, generics
pip install httpware[msgspec] # MsgspecDecoder: Struct, dataclasses, primitives, generics
pip install httpware[pydantic,msgspec] # both; BaseModel goes to pydantic, Struct to msgspec
pip install httpware[otel] # OpenTelemetry span events
pip install httpware[all] # pydantic, msgspec, and otel
Quickstart
A typed GET against a live API (needs pip install httpware[pydantic]):
import asyncio
from httpware import AsyncClient
from pydantic import BaseModel
class User(BaseModel):
id: int
name: str
async def main() -> None:
async with AsyncClient(base_url="https://jsonplaceholder.typicode.com") as client:
user = await client.get("/users/1", response_model=User)
print(user.name) # Leanne Graham
asyncio.run(main())
The sync Client works the same way: use Client instead of AsyncClient, and drop await and async with. A 4xx/5xx response raises a typed StatusError; a malformed body raises DecodeError. Both subclass httpware.ClientError.
Documentation
Full guides live at httpware.modern-python.org:
- Quickstart: first requests, client options, streaming.
- Resilience: retry and retry budget, bulkhead, circuit breaker, timeout.
- Errors: the exception tree and how to catch it.
- Decoders: typed response bodies and custom decoders.
- Middleware: writing your own (auth, tracing, request IDs).
- Observability: logger and event names, OpenTelemetry wiring.
- Testing: injecting
httpx2.MockTransport. - Recipes: DI wiring, phase decorators, Link header pagination.
🗒️ Release notes · 📦 PyPI · 📝 License
Part of modern-python
Browse the full list of templates and libraries in
modern-python; the org profile has the categorized index.
Metadata
Release files for httpware 0.20.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 | |
|---|---|---|---|
| httpware-0.20.1.tar.gz | 39.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| httpware-0.20.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 88.6 kB
Release files / httpware-0.20.1.tar.gz
| Download URL | httpware-0.20.1.tar.gz |
|---|---|
| Size | 39.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
074a2fac2f26bf54bca22ddf7d50831fba22259631a1112b5afc9c8ad2e7023d
|
|
BLAKE2b-256 checksum How to use checksums |
7e423eab814f14e80c32693636a6430ed08e6241abbe29f6c1c41cd5e6f43435
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.22 {"installer":{"name":"uv","version":"0.12.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / httpware-0.20.1-py3-none-any.whl
| Download URL | httpware-0.20.1-py3-none-any.whl |
|---|---|
| Size | 49.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4c5effb4112b74935eed9c2046ef2c11a3568c8464457ab66450e9f6435d852f
|
|
BLAKE2b-256 checksum How to use checksums |
965ca15f254f1ffb34533f1b892655eb3c5888d4b56fdc069402821ed1595b32
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.22 {"installer":{"name":"uv","version":"0.12.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|