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.21.0
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.21.0.tar.gz | 38.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| httpware-0.21.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 87.6 kB
Release files / httpware-0.21.0.tar.gz
| Download URL | httpware-0.21.0.tar.gz |
|---|---|
| Size | 38.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
26b4e32e41975f3dbf95e6f1c6e9144780b942cb8c7775c15df380096f81877d
|
|
BLAKE2b-256 checksum How to use checksums |
4f30ef66da977c8b2f8262bc8e71808ab0770235fb0cec342b214fb31cc5cf9e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","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.21.0-py3-none-any.whl
| Download URL | httpware-0.21.0-py3-none-any.whl |
|---|---|
| Size | 49.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
09ea7b0bec98875e632def660c852259b41d59a415e75e6a1b931410bc84f3f7
|
|
BLAKE2b-256 checksum How to use checksums |
3231a3ee471d52f4b0f88ee4415ae91a569138ccc2ac230d4f1eaae2acdb7f3b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","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}
|