Skip to main content

lothc logo

lothc

PyPI CI 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.build(base_url="https://pokeapi.co/api/v2/") as client:
    pikachu = await client.get("pokemon/pikachu", response_data_type=Pokemon)
    print(pikachu)  # 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 (response_data_type= 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 response_data_type 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. 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/get_result, post, put, patch, delete, head, download — see Verbs.
Typed params, headers & forms A BaseModel/Struct for query params or headers (with None-field omission), or a real multipart body via 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, or default_headers for anything else — 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)

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

lothc-0.0.12.tar.gz (34.8 kB view details)

Uploaded Source

Built Distribution

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

lothc-0.0.12-py3-none-any.whl (32.5 kB view details)

Uploaded Python 3

File details

Details for the file lothc-0.0.12.tar.gz.

File metadata

  • Download URL: lothc-0.0.12.tar.gz
  • Upload date:
  • Size: 34.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.9 {"installer":{"name":"uv","version":"0.12.9","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}

File hashes

Hashes for lothc-0.0.12.tar.gz
Algorithm Hash digest
SHA256 7eea6c05f5431b1af30654e8ef2f80aafea1ab79f2c0ccec86d83f3a31adb9ed
MD5 9a54ac1ab51c65bbfe65b273089eec3e
BLAKE2b-256 4e01950f705758bc94037cf3c36b1fc6f547c54f5bbf4b93bb1a1e49fe2c62cb

See more details on using hashes here.

File details

Details for the file lothc-0.0.12-py3-none-any.whl.

File metadata

  • Download URL: lothc-0.0.12-py3-none-any.whl
  • Upload date:
  • Size: 32.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.9 {"installer":{"name":"uv","version":"0.12.9","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}

File hashes

Hashes for lothc-0.0.12-py3-none-any.whl
Algorithm Hash digest
SHA256 cf3a4de78bd57c986dd564a831c40cebdcf48ca7c1202a6a4d66a56264702f18
MD5 442ee071582bedbd7f6122b669f803c0
BLAKE2b-256 9929e835fc87bf269e2b4d64b3a0a141c343f4846d0e029d6d695132beb6ed4d

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.0.12 This release

2 files

0.0.11

2 files

0.0.10

2 files

0.0.9

2 files

0.0.8

2 files

0.0.7

2 files

0.0.6

2 files

0.0.5

2 files

0.0.4

2 files

0.0.3

2 files

0.0.2

2 files

0.0.1

2 files

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