Search torrents from multiple websites via the CLI
Project description
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). |
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.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file torrent_hound-3.2.3.tar.gz.
File metadata
- Download URL: torrent_hound-3.2.3.tar.gz
- Upload date:
- Size: 173.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9fc7ef6c21c78da38bb0c3b39f6a059e7af7658510dfb2ca2d23cdeb2aca3ef4
|
|
| MD5 |
a5f90a93a2691f4b7f143a54c5e1d872
|
|
| BLAKE2b-256 |
3cc9770e10f4ba08443082028b3f9be12d5350dbb84d8c73a1a58552152c3bce
|
Provenance
The following attestation bundles were made for torrent_hound-3.2.3.tar.gz:
Publisher:
publish.yml on baddymaster/torrent-hound
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
torrent_hound-3.2.3.tar.gz -
Subject digest:
9fc7ef6c21c78da38bb0c3b39f6a059e7af7658510dfb2ca2d23cdeb2aca3ef4 - Sigstore transparency entry: 1429663534
- Sigstore integration time:
-
Permalink:
baddymaster/torrent-hound@1fdd5381ef7aa7d52e494055c91b36d3be497bdc -
Branch / Tag:
refs/tags/v3.2.3 - Owner: https://github.com/baddymaster
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@1fdd5381ef7aa7d52e494055c91b36d3be497bdc -
Trigger Event:
push
-
Statement type:
File details
Details for the file torrent_hound-3.2.3-py3-none-any.whl.
File metadata
- Download URL: torrent_hound-3.2.3-py3-none-any.whl
- Upload date:
- Size: 82.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
26e1e2dbaf1ebb40cbd9131863e69abcc48535bdc42f49275f83de0d38f457cc
|
|
| MD5 |
a7e24190e0382e8d4127ba5c2e53dbd2
|
|
| BLAKE2b-256 |
d4c8e2d079f055a9282c1837fc45d019d543c2b0838dec489902e271c70844c6
|
Provenance
The following attestation bundles were made for torrent_hound-3.2.3-py3-none-any.whl:
Publisher:
publish.yml on baddymaster/torrent-hound
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
torrent_hound-3.2.3-py3-none-any.whl -
Subject digest:
26e1e2dbaf1ebb40cbd9131863e69abcc48535bdc42f49275f83de0d38f457cc - Sigstore transparency entry: 1429663538
- Sigstore integration time:
-
Permalink:
baddymaster/torrent-hound@1fdd5381ef7aa7d52e494055c91b36d3be497bdc -
Branch / Tag:
refs/tags/v3.2.3 - Owner: https://github.com/baddymaster
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@1fdd5381ef7aa7d52e494055c91b36d3be497bdc -
Trigger Event:
push
-
Statement type: