TSP torrent search API

One file, run as a Cloudflare Worker, that searches 10 public torrent indexes at once and answers in TSP, the Torrent Search Protocol. Free tier is enough. No account here, no build step.

1Take your key

Generated in this page, in your browser. Nothing is sent anywhere; reload and you get a different one.

Save it. It is what your client sends; the Worker's own page shows it too.

2Deploy it

With a Cloudflare account: one click

Deploy to Cloudflare opens dash.cloudflare.com, a free account is enough
  1. Sign in, or make an account. Cloudflare shows you the Worker it is about to create: this file, your key already in it.
  2. Deploy.
  3. Open the Worker's URL. It shows its address, its key, and a search you can click.

That link is the one the Workers Playground's own Deploy button makes, with this file inside it. Your key travels in the part after #, which a browser keeps to itself and never sends to a server; Cloudflare's page reads it there, exactly as it would from a paste.

By hand: paste

This is worker.js with your key already in it, about 80 KiB of readable JavaScript, no dependencies.

  1. Go to Workers & Pages → Create → Worker, name it, Deploy.
  2. Edit code, select everything in the editor, paste over it, Deploy again.
  3. Open the Worker's URL. It shows its address, its key, and a search you can click.

Whichever way, that is all. The Worker holds no secrets beyond the key, keeps nothing, and stores nothing: each request is asked, merged and forgotten. Its page shows the key to anyone who opens the URL, so the address is the secret; if you would rather it did not, set TSP_SHOW_KEY=0 and it shows the key only when the URL carries it.

3Use it

https://your-worker.workers.dev/api/v1/search?q=ubuntu&apikey=…

What it answers

{ "query": "ubuntu", "count": 87, "torrents": [ { "name": "…", "infohash": "…", "magnet": "magnet:?xt=urn:btih:…", "size_bytes": 6343219200, "seeders": 165, "leechers": 12, "category": "software", "sources": ["knaben", "piratebay"] } ], "engines": ["knaben", "piratebay", "…"] }

Other routes

/api/v1/indexerswhat it can search, and what is on
/api/v1/healthwhich catalogue it is running, no key needed
/api/v1/try?d=…run a descriptor that is not in the catalogue yet
Settings, if you want them
TSP_APIKEYthe key. The deploy form sets it; a pasted file has it baked in; this overrides either
TSP_SHOW_KEY0 to show the key only to a request that already carries it
TSP_INDEXESsearch only these, by id, comma separated; this also turns on anything switched off
TSP_NSFW0 to leave adult indexes out; they are searched by default
TSP_BROWSE0 to answer an empty query with nothing instead of browsing
TSP_LIMITmost rows per index (default 100)
TSP_TIMEOUTseconds to wait on one index (default 8)
TSP_FEED_URLa catalogue of your own
TSP_FEED0 to pin the compiled catalogue and never refetch
TSP_ALSOsearch these too, by id, even where the catalogue has them off; unlike TSP_INDEXES it does not freeze the list
TSP_CACHEseconds a merged answer is kept and paged from (default 600); 0 for none. Only a custom domain has a working cache; on workers.dev every search is fresh

Set them under Settings → Variables and Secrets. Each one takes effect on the next request, and they survive a rebuild. The same file also runs as a service for strangers, with keys it signs and hands out itself; the README's "Hosting it for others" says how.

What it searches

10 indexes are on by default, out of 14 this project describes. The list comes from prajwalch/TorrentSearch, which tracks 43 sites, read at 2d718a34a7e1.

AnimeToshojsonanime
Dmhyrssanime, books, games
Eztvjsonseries
Knabenjsonanime, apps, books
ThePirateBayjsonapps, books, games
Rutorhtmlanime, apps, books
Sukebei adultrssporn
TorrentDownloadsrssanime, apps, books
TorrentsCSVjsonother
Ytsjsonmovies

A deployed Worker refetches this list hourly, so indexes that are fixed, added or retired reach it without you doing anything. What is compiled into the file is only what it falls back to when the feed cannot be reached.