Skip to main content

lothc logo

lothc

PyPI CI CodSpeed codecov Python versions License

Lord Of The Http Clients — a typed HTTP client for Python, built on pyreqwest (an awesome Rust-backed HTTP client), with first-class optional support for pydantic and msgspec as both decode and encode targets.

Installing

uv add 'lothc[pydantic,msgspec]'

(Any subset of the extras works — the base package alone gets you bytes/dict support.)

Quickstart

from lothc import HTTPClient
from pydantic import BaseModel


class Pokemon(BaseModel):
    id: int
    name: str


async with HTTPClient(base_url="https://pokeapi.co/api/v2/") as client:
    response = await client.get("pokemon/pikachu", into=Pokemon)
    print(response.status, response.data)  # 200 id=25 name='pikachu'

Why?

Why was lothc built, and why should you use it?

pyreqwest is a genuinely excellent HTTP client for Python, fast because the heavy lifting happens in Rust, not pure Python. But its API is a builder pattern (client.get(path).build() before you can even .send() it), unfamiliar to anyone coming from requests/httpx/niquests, where a call is just client.get(url, params=..., headers=...). lothc wraps pyreqwest with exactly that familiar shape, so you get pyreqwest's speed without giving up the ergonomics Python HTTP users already expect.

The other reason: Python's most popular third-party HTTP clients (httpx, aiohttp, niquests) all have first-class JSON support: call .json() and get back a dict. But in order for a Python project to be end-to-end type-safe, data crossing I/O boundaries must be validated, and if invalid, handled accordingly (raise an error) — a plain dict does neither. Closing that gap is exactly what lothc is designed for.

The original idea was to make lothc backend-agnostic: httpx, aiohttp, niquests, and pyreqwest all interchangeable underneath the same typed lothc interface, so switching backends never meant switching your call sites. However, in the author's opinion there's currently no compelling reason not to just use pyreqwest, so pyreqwest is the only backend implemented today, but, if there's demand for an httpx/aiohttp/niquests backend, the author is happy to consider adding one.

Fast

HTTP client throughput race — lothc and pyreqwest finish in well under a fifth of a second, other libraries take much longer

Benchmarked with perf.py against a tiny Rust-based static JSON server, 10,000 requests at concurrency 100 — including lothc's fully-typed decode targets (into= a msgspec Struct or a pydantic BaseModel), not just raw bytes or an untyped dict. The object handed back from those runs isn't just parsed JSON — it's a real, constructed, field-validated instance of your own type, and that validation cost is included in the numbers, not benchmarked around. Decoding into a real msgspec Struct even edged out the unvalidated dict path in this run. Full numbers: docs/benchmarks.md.

Highlights

Pass into to any lothc call and get back a real, constructed, field-validated pydantic BaseModel or msgspec Struct, instead of the plain dict .json() leaves you to validate yourself. Any type expression works, so into=list[Pokemon] decodes a top-level array. See Benchmarks for what that costs (usually nothing).

Two clients, one API HTTPClient (async) and SyncHTTPClient (sync) — identical surface, both backed by pyreqwest.
Every verb get, post, put, patch, delete, head, download (each returning a Response: .data, .status, .headers) — see Verbs.
Typed params, headers & forms A BaseModel/Struct for query params or headers (with None-field omission), or a body sent urlencoded (data=) or as a real multipart form (form=).
Precise static types Every verb is paired @overloads, not a cast-laden generic — your editor knows the exact return type.
SSE & streaming Spec-compliant SSE — automatic reconnect with Last-Event-ID, server retry: honored, typed decode (discriminated unions included) — plus raw or NDJSON-typed stream_get/stream_post — see SSE / Streaming.
Retries with real backoff max_retries/retry_methods, a genuine pyreqwest middleware hook, Retry-After-aware — see Retries.
Authentication Static bearer_token, a per-request-refreshed bearer_auth, basic_auth, or default_headers for anything else — plus a ready-made OAuth 2 client-credentials provider (OAuthProvider: mint, leeway-based renewal, refresh-then-mint fallback, optional on-disk token cache) — see Authentication.
Cookies, redirects, proxy cookie_store, follow_redirects/max_redirects, proxy= — see Networking.
A real error hierarchy HTTPTransportError/HTTPTimeoutError/HTTPConnectionError for no response, HTTPResponseError for 4xx/5xx — see Error handling.
Everything optional pydantic, msgspec — works with neither, either, or both installed.

Development

See CLAUDE.md and style-guide.md for architecture notes and the (non-obvious in places) design conventions this codebase relies on.

task deps-sync    # install
task test         # run tests
task check        # lint + format-check + typecheck (what CI runs)

License

lothc is MIT. It's built on pyreqwest (Apache-2.0), which is built on the Rust crate reqwest (MIT or Apache-2.0). Thanks to both.

Metadata

Release files for lothc 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for lothc 0.2.1
File Size Uploaded Provenance
lothc-0.2.1.tar.gz 85.3 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for lothc 0.2.1
File Interpreter ABI Platform
lothc-0.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 168.7 kB

Release files / lothc-0.2.1.tar.gz

Download URL lothc-0.2.1.tar.gz
Size 85.3 kB
Tags Source
SHA-256 checksum
How to use checksums
da7f0f1f61802cd51c4057df249b5f5e6c9c7c81520e63703c98b0f6a5be4f58
BLAKE2b-256 checksum
How to use checksums
3fe57717fa500bc75bef97526ac231f117a20cce0b504b984acd008576dbb06d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","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 / lothc-0.2.1-py3-none-any.whl

Download URL lothc-0.2.1-py3-none-any.whl
Size 83.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8717a9b097b5d22c4ca2b829c4b1fed36f7027eb5da5469648ec25936ddf7c8d
BLAKE2b-256 checksum
How to use checksums
c9c09300155ad0cbfed5fd10409559c28adfcfcaa481a33ef6caf1789e6836a8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","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}

Security for lothc 0.2.1

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page