๐ง hypertor
Tor for Rust and Python. Make HTTP requests over the Tor network, and host onion services.
hypertor is a thin layer over two mature pieces of software:
arti, the Tor Project's Rust implementation of
Tor, and hyper, the HTTP stack reqwest is built on. It supplies the seam
between them and the ergonomics on top.
It implements no Tor protocol and no HTTP protocol of its own. That is the point: cryptography and protocol handling belong in the projects that specialise in them.
No Tor daemon required โ no tor, no Tor Browser, no torsocks.
๐ Documentation ยท API reference ยท Changelog
use TorClient;
async
Install
Rust 1.91 or later; Python 3.10 or later. Wheels ship for Linux, macOS and Windows on x86-64 and arm64, so the Python package needs no Rust toolchain.
What it does
TorClient |
HTTP/1.1 and HTTP/2 over Tor, with real connection pooling |
OnionService |
Host a .onion service; hands you the raw inbound streams |
OnionApp |
A small routed HTTP framework on top of OnionService |
SocksProxy |
A local SOCKS5 front-end, so any program can use Tor |
TorWebSocket |
WebSocket over Tor, splittable for concurrent read and write |
| Feature | Default | Adds |
|---|---|---|
client |
โ | TorClient and the HTTP client stack |
rustls |
โ | TLS via rustls โ one fingerprint on every platform |
native-tls |
TLS via the OS stack (leaks your platform; see the docs) | |
server |
OnionService, OnionApp |
|
socks |
SocksProxy |
|
ws |
TorWebSocket |
|
pow |
Equi-X proof of work โ pulls in LGPL-3.0 crates | |
static-sqlite |
Link SQLite statically (useful on Windows) |
full is everything except pow, so a default build stays permissively licensed. There is no
python feature: the bindings are a separate, unpublished crate, so a Rust dependency on hypertor
never pulls in pyo3.
Exactly one TLS backend is required โ Tor's own link protocol is TLS, so even a server-only
build needs one. If you set default-features = false, put rustls (or native-tls) back.
0.4 is a hard cut from 0.2.2 with no migration shim; the changelog is the migration guide.
Why not just wire arti and hyper together yourself
Connection pooling that actually pools. The Tor connector plugs into hyper's pooling client, so a warm circuit is reused across requests. Building a circuit costs seconds; a request on an established one costs a few hundred milliseconds.
Circuit isolation as a first-class concept. Decide explicitly which of your activities may be linked. Each isolation group gets its own connection pool and its own TLS session store โ sharing the latter would let a server link exactly the requests the circuits kept apart.
Bodies that stream in both directions. Upload from a file and download to one without holding either in memory. Decompression is incremental, so the size limit bounds a decompression bomb rather than discovering one.
Onion services that do not stand out. A hosted service answers only BEGIN streams on the
virtual ports it publishes โ behaving differently is itself a fingerprint.
Security at a glance
The Security page explains the threat model and its limits. In brief, the design protects against:
| DNS leaking your destinations | Hostnames are always resolved by the exit relay, never locally |
| A client falling back to system DNS | The SOCKS proxy speaks Tor's RESOLVE / RESOLVE_PTR |
| Credentials replayed to another host | Stripped on any cross-origin redirect |
A .onion redirecting you to clearnet |
Refused unless explicitly allowed |
| TLS tickets relinking isolated circuits | One session store per isolation group |
| Recorded traffic decrypted later | X25519MLKEM768 post-quantum key exchange |
| Hostnames leaking into your logs | Scrubbed from Error output by default |
| Decompression bombs | Decoded incrementally and abandoned at the limit |
| Clock-skew correlation of a service | No Date, Server or X-Powered-By header |
| Matching a service to its clearnet host | ETag is keyed per process; no Last-Modified |
| Path traversal in static files | Paths are canonicalised and confined to the root |
| Slowloris against your service | Header read deadline and a connection cap |
| Guard discovery | VanguardMode, wired to arti |
What no library can protect against. hypertor is not an anonymity system in its own right. Tor protects the network path. It cannot protect you from an application that logs in with your real identity, from timing patterns in your own traffic, or from a compromised machine. Read the Tor Project's guidance before relying on this for anything that matters.
Development
The HTTP framework is tested end to end over an in-memory pipe โ a real hyper client against a real
OnionApp โ so routing, framing, keep-alive, HTTP/2 and the body limits are covered on every commit
rather than only when someone runs the live tests.
Repository layout
Cargo.toml the published crate, and the workspace root
src/ the library
examples/ tests/ benches/
bindings/python/ the Python bindings โ Rust crate, Python package, tests,
examples and pyproject.toml, all in one place
site/ the documentation site (Zola)
The bindings are a separate, unpublished crate that uses hypertor through its public API. That keeps pyo3 out of every Rust user's dependency graph, and means anything the bindings cannot reach is a gap in the Rust API rather than something to paper over.
Disclaimer
Provided for research and educational use. No anonymity guarantee: your operational security, threat model and usage patterns matter more than any library. Not affiliated with, endorsed by, or sponsored by the Tor Project. You are responsible for complying with the law where you are.
License
MIT. See LICENSE.