ProtoX GateKeeper is a small, opinionated Python library that enforces fail-closed Tor routing for HTTP(S) traffic.
The goal is simple:
If Tor is not active and verified, nothing runs.
GateKeeper is designed to be fire-and-forget: create a client once, then perform network operations with a hard guarantee that traffic exits through the Tor network.
- A Tor-verified HTTP client
- A thin wrapper around
requests.Sessionwith safe helpers - Fail-closed by default (no silent clearnet fallback)
- Observable (exit IP, optional geo info)
- Suitable for scripts, tooling, and automation
- ❌ A Tor controller
- ❌ A crawler or scanner
- ❌ An anonymization silver bullet
- ❌ A replacement for Tor Browser
GateKeeper enforces transport routing only. You are still responsible for what you do with it.
- A locally running Tor client
- SOCKS proxy enabled (default:
127.0.0.1:9150)
On Windows this usually means Tor Browser running in the background.
pip install protox-gatekeeperpip install -e .(Recommended while developing or testing.)
import logging
from protox_gatekeeper import GateKeeper
logging.basicConfig(
level=logging.INFO,
format='[%(levelname)s] %(name)s - %(message)s'
)
gk = GateKeeper(geo=True)
gk.download(
"https://httpbin.org/bytes/1024",
"downloads/test.bin"
)[INFO] gatekeeper.core - Tor verified: 89.xxx.xxx.xxx -> 185.xxx.xxx.xxx
[INFO] gatekeeper.core - Tor exit location: Brandenburg, DE
[INFO] gatekeeper.core - [Tor 185.xxx.xxx.xxx] downloading https://httpbin.org/bytes/1024 -> downloads/test.bin
This confirms:
- clearnet IP was measured
- Tor routing was verified
- all traffic used the Tor exit shown
GateKeeper can also be used as a Tor-verified HTTP client:
with GateKeeper() as gk:
response = gk.get("https://httpbin.org/ip")
print(response.json())All requests are guaranteed to use the verified Tor session.
gk = GateKeeper(
socks_port=9150,
geo=False
)Parameters:
socks_port(int) – Tor SOCKS port (default:9150)geo(bool) – Enable best-effort Tor exit geolocation (optional)
Raises RuntimeError if Tor routing cannot be verified.
Performs an arbitrary HTTP request through the verified Tor session.
This is a thin passthrough to requests.Session.request, with enforced Tor routing and logging.
r = gk.request(
"GET",
"https://httpbin.org/ip",
timeout=10
)
print(r.json())method– HTTP verb (GET, POST, PUT, DELETE, ...)url– Target URL**kwargs– Forwarded directly torequests
This is the core execution path used internally by helper methods like get() and post().
Downloads a resource through the verified Tor session.
gk.download(url, target_path)url– HTTP(S) URLtarget_path– Full local file path (directories created automatically)
Downloads a resource through the verified Tor session.
gk.download(url, target_path)url– HTTP(S) URLtarget_path– Full local file path (directories created automatically)
Performs a Tor-verified HTTP GET request.
response = gk.get(url, timeout=10)Returns a standard requests.Response.
Performs a Tor-verified HTTP POST request.
response = gk.post(url, json={"key": "value"})Returns a standard requests.Response.
- Fail closed: no Tor → no execution
- Single verification point (during construction)
- No global state
- No logging configuration inside the library
- Session reuse without re-verification
Logging is emitted by the library, but configured by the application.
GateKeeper uses standard Python logging:
import logging
logging.basicConfig(level=logging.INFO)The library does not call logging.basicConfig() internally.
- Tor exit IPs may rotate over time
- Geo information is best-effort and may be unavailable (rate-limits, CAPTCHAs)
- GateKeeper guarantees routing, not anonymity
All request methods forward arguments directly to requests. If you need to interact with legacy systems that have expired or self-signed certificates, you may disable TLS verification per request:
r = gk.request(
"GET",
"https://legacy.example.com",
verify=False
)Or for downloads:
gk.download(url, "file.bin", verify=False)Disabling certificate verification reduces transport security and should only be used when necessary.
MIT License
- Version: v0.2.4
- Phase 2 in progress
- API intentionally minimal
Future versions may add optional features such as:
- circuit rotation
- ControlPort support
- higher-level request helpers
Without breaking the core contract.