Torrent Hound
A terminal-first torrent search CLI. Type a query, get ranked results from multiple trackers in one live table, then act on a row with a single keystroke — copy magnet, open page, send to your default torrent client, or hand off to Real-Debrid.
$ torrent-hound ubuntu
3 sources · 23 results · 0.92s — 'ubuntu'
trail: TPB ✓ 10 (180ms) · YTS ✓ 8 (420ms · 1 retry) · EZTV ⚡ 5 cached 3m
selected: TPB · ubuntu-24.04.1-desktop-amd64.iso
┏━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━┳━━━━┳━━━━━━┓
┃ No ┃ Name ┃ Size ┃ S ┃ L ┃ S/L ┃
┡━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━╇━━━━╇━━━━━━┩
│ 1 │ ubuntu-24.04.1-desktop-amd64.iso │ 5.8 GB │ 40 │ 2 │ 20.0 │ ← amber
│ 2 │ Ubuntu 22.04 LTS │ 3.4 GB │ 32 │ 1 │ 32.0 │
│ … │ │ │ │ │ │
└────┴──────────────────────────────────────────────────────┴───────────┴────┴────┴──────┘
Magnet copied to clipboard
↑↓ move · ⏎/c copy · cs seedr · o open page · d download · r repeat · rd real-debrid · s search · / filter · q quit
Sources
| Source | Content | Method |
|---|---|---|
| The Pirate Bay | General | HTML scrape, mirror chain |
| YTS | Movies | JSON API, mirror chain |
| EZTV | TV shows | JSON API via IMDB lookup |
All sources are searched in parallel. Each source has a multi-mirror fallback chain — if one mirror is down, the next is tried automatically. Results are cached for the session (5-minute TTL).
Requirements
- Python 3.10+
- Runtime dependencies:
beautifulsoup4,requests,pyperclip,rich,platformdirs,tomli_w,argcomplete
Install
pipx install torrent-hound # recommended — isolated venv, on PATH
pip install torrent-hound # plain pip
Pre-built standalone binaries (no Python required) for Linux / macOS / Windows are on the Releases page.
From source:
git clone https://github.com/baddymaster/torrent-hound.git
cd torrent-hound
pip install -e ".[dev]" # installs deps + pytest + ruff
Shell completion
Tab-completion is provided by argcomplete.
Add one line to your shell config:
bash (~/.bashrc):
eval "$(torrent-hound --print-completion bash)"
zsh (~/.zshrc):
autoload -U compinit && compinit
eval "$(torrent-hound --print-completion zsh)"
Restart your shell, then torrent-hound --<TAB> cycles through flags.
Note: Completion only works when installed via
pip/pipx. The standalone binary doesn't expose the Python entry point that argcomplete hooks into.
Usage
torrent-hound ubuntu
Drops you into a single-screen TUI. Three header rows, results table below, mode-aware footer of keystroke hints at the bottom.
Header
- Top: rotating verb spinner (during fetch) → run summary
(
3 sources · 23 results · 0.92s — 'ubuntu') once results land. - Middle:
trail:line — per-source pip with mirror retry detail and inline timing. Persists above the table after fetch completes:trail: TPB ✓ 10 (180ms) · YTS ✓ 8 (420ms · 1 retry) · EZTV ⚡ 5 cached 3m - Bottom:
selected: <source> · <name>of the highlighted row.
Keystrokes
Navigation
| Key | Action |
|---|---|
↑ / ↓ |
Move selection (table scrolls when selection goes off-screen) |
? |
Show / hide the keystroke help overlay |
q |
Quit |
Acting on the highlighted row
| Key | Action |
|---|---|
c / ⏎ |
Copy magnet to clipboard |
cs |
Copy magnet and open Seedr.cc |
m |
Show the full magnet in an overlay panel (any key returns) |
v |
Show normalised metadata for this torrent in an overlay panel |
o |
Open the torrent page in your default browser |
d |
Hand the magnet to your default torrent client |
rd |
Real-Debrid: submit, fetch hoster links, dispatch via configured action |
cs and rd are chord commands — press the prefix (c or r) and the footer
shows the available extensions plus the standalone meaning. After ~1 second
without a follow-up, the standalone meaning fires (so c alone copies, r
alone repeats the last search).
Search & filter
| Key | Action |
|---|---|
/ |
Enter live filter mode — type to narrow visible results, arrows still nav |
s |
Enter new-search mode — type a new query, ⏎ to fetch |
r |
Repeat the current search (cached sources reused; failed sources retry) |
In filter mode, ⏎ accepts the filter and exits to the results table; Esc
clears it.
Scripting mode
torrent-hound --json ubuntu | jq '.tpb.results["0"].magnet'
torrent-hound --quiet ubuntu # plain Python repr to stdout
Either flag bypasses the TUI entirely and exits after printing.
Real-Debrid integration
Send the highlighted torrent to Real-Debrid and hand the resulting direct link to your download manager.
Setup
torrent-hound --configure-rd
Prompts for your API token (get one at real-debrid.com/apitoken) and the action to run against returned direct links, then writes them to a config file with restrictive permissions (0600 on the file, 0700 on the parent).
For ad-hoc use without saving anything:
export RD_TOKEN="..."
Action modes
| Mode | What happens with the direct link(s) |
|---|---|
clipboard |
(default) Copied to clipboard. Multiple links are joined with newlines. |
print |
Printed to stdout. |
browser |
Opened in your default browser (works without a separate download manager). |
downie |
Sent to Downie 4 via its downie:// URL scheme (macOS). |
folx |
Sent to Folx via its openinfolx3:// URL scheme (macOS). |
Convenience flags
torrent-hound --configure-rd # interactive setup (token + action)
torrent-hound --config-path # print the resolved config file path
torrent-hound --user-status # show RD account info (premium, expiration, points)
torrent-hound --revoke-rd-token # invalidate the current token on RD
Config file
Path:
- macOS:
~/Library/Application Support/torrent-hound/config.toml - Linux:
~/.config/torrent-hound/config.toml - Windows:
%APPDATA%\torrent-hound\config.toml
Managed by --configure-rd, but plain TOML if you ever want to edit directly:
[real_debrid]
token = "XXXXXXXXXXXXXXXXXXXXXXXXXXXX"
action = "downie"
Usage
After a search, navigate to a row, press rd. The TUI shows a spinner while
the worker submits to RD, waits for hoster links, and runs your configured
action. Multi-file torrents (season packs, multi-part archives) trigger an
in-app picker overlay:
| Key | Action |
|---|---|
↑ / ↓ |
Move cursor through file list |
space |
Toggle current row's checkbox |
a |
Toggle all (mark all / clear all) |
⏎ |
Confirm selection |
Esc |
Cancel the RD operation |
All files start marked, so confirming with ⏎ immediately is equivalent to
"all" in the legacy text picker. Outcome (success or error) lands as a toast
on the results screen — no terminal hand-off, no "press enter to return".
If RD is still processing (common for larger uncached torrents), the toast
asks you to run rd again — re-running picks up where it left off without
re-prompting the picker, since RD remembers the prior file selection.
Troubleshooting
Real-Debrid rejected the token— runtorrent-hound --configure-rd.- Connectivity errors (
DNS lookup failed,block page, geo-block) — your ISP / network / proxy is filtering the RD API. Try a VPN or DoH resolver (1.1.1.1,8.8.8.8). - Anything else —
torrent-hound --user-statusto check account state. Specific error messages reference RD's documentederror_codevalues.
Development
pip install -e ".[dev]"
pytest tests/
ruff check .
Tests run fully offline — parser fixtures are captured HTML, network calls
are mocked. The TUI is unit-tested at the read_key and handle_key layers
(see tests/test_tui.py); the rich.live event loop is manual-tested only.
Optional pre-commit hook (runs ruff + the test suite before every commit):
pre-commit install
Package layout
torrent_hound/
cli.py — argparse + main() entry point
tui.py — rich.live TUI (single-screen app)
state.py — shared mutable state (results, urls, should_exit)
cache.py — per-session result cache
config.py — TOML config + Real-Debrid setup commands
realdebrid.py — RD API client + the rd flow
ui.py — rich Console singleton + table builders + JSON output
sources/
__init__.py — _SOURCES registry + searchAllSites orchestrator
base.py — Source Protocol + shared helpers
tpb.py — The Pirate Bay
yts.py — YTS
eztv.py — EZTV
legacy_1337x.py — dormant; kept for re-enable when CF landscape changes
Adding a source
- Create
torrent_hound/sources/foo.py— implementsearchFoo(search_string, quiet_mode, limit, timeout, progress)returning a list of result dicts with keysname,link,seeders,leechers,size,ratio,magnet. Callprogress({"type": "mirror_attempt", "mirror": ...})etc. so the trail line lights up. - Register in
sources/__init__.py._SOURCES. - Add a parser test in
tests/test_foo_parser.py.
Troubleshooting
- SSL handshake errors: see these Stack Overflow answers for common fixes.
[PirateBay] Error : All known mirrors returned no results or were unreachable: every TPB domain in the fallback chain is blocked or down. Add a known-working mirror toTPB_DOMAINSintorrent_hound/sources/tpb.py.- Blocked by Cloudflare captcha: some sources serve a CF challenge that requires a real browser. 1337x is currently dormant for this reason.
- Arrow keys not working / ESC press doesn't cancel filter: your terminal
may be delivering escape sequences slowly. The TUI probes for 50ms after
\x1bto distinguish bare ESC from arrow keys; if your terminal is slower than that, bump_ESC_PROBE_SECONDSat the top oftorrent_hound/tui.py.
Disclaimer
This software is provided as-is, with no warranty of any kind. It is intended for discovering legally-distributable content and is not intended to be used for downloading, distributing, or facilitating access to copyrighted material without authorisation. You are responsible for complying with the laws of your jurisdiction.
License
AGPL-3.0 — see LICENSE.
Release files for torrent-hound 3.2.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| torrent_hound-3.2.4.tar.gz | 182.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| torrent_hound-3.2.4-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 268.3 kB
Release files / torrent_hound-3.2.4.tar.gz
| Download URL | torrent_hound-3.2.4.tar.gz |
|---|---|
| Size | 182.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f4bfd4756e5c20c95da62501c905c3edce20fdb20abe7a3f8f84897adee34b20
|
|
BLAKE2b-256 checksum How to use checksums |
514098b861f4e85460655ab081d625a131d18730d8d333f942d3b6202242f4f3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 24, 2026.
Transparency logRelease files / torrent_hound-3.2.4-py3-none-any.whl
| Download URL | torrent_hound-3.2.4-py3-none-any.whl |
|---|---|
| Size | 85.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0d58dc5630b33d0235fda0827ea73b6f683da6d93a463d5907638297935ab857
|
|
BLAKE2b-256 checksum How to use checksums |
f3d8caf3c4bd4f8b73da5d2d8bf781d40cc7e73a771408814f7aec570b5c7db0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 24, 2026.
Transparency log