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 Typed SSE 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.9.tar.gz (25.4 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.9-py3-none-any.whl (23.3 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for lothc-0.0.9.tar.gz
Algorithm Hash digest
SHA256 22204f34e23ddb0d22e92224fb5495c2687870f357f0204f95bfa9b423fbaf4c
MD5 956d9b847b2a652b7c75dc79779b688c
BLAKE2b-256 4f422859a3bd17a8764e9b6f9d4c574c5f93988381312b69d1a4779228fbcde9

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for lothc-0.0.9-py3-none-any.whl
Algorithm Hash digest
SHA256 f4feeaca2079852591129a7723572df5c13856d96173ac264191abfb303fc939
MD5 6acde072052c685340de9829baa8c29f
BLAKE2b-256 8b84e7e905005355d30fb65681dc2ceefc4e5282c77ba978c52cbe2a5dcda7c5

See more details on using hashes here.

Release history Release notifications | RSS feed

0.0.12

2 files

0.0.11

2 files

0.0.10

2 files

This release

0.0.9 This release

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