Torrent / BitTorrent DHT corpus search & crawl statistics avatar

Torrent / BitTorrent DHT corpus search & crawl statistics

Pricing

from $1.00 / 1,000 results

Go to Apify Store
Torrent / BitTorrent DHT corpus search & crawl statistics

Torrent / BitTorrent DHT corpus search & crawl statistics

Search a live BitTorrent DHT metadata corpus and see how fast it is growing. Two endpoints: /search with category filters and relevance ranking, and /stats with a per-minute capture rate you can verify. No endpoint or key needed — the corpus is crawled and hosted by this Actor's operator.

Pricing

from $1.00 / 1,000 results

Rating

0.0

(0)

Developer

Raul Sota

Raul Sota

Maintained by Community

Actor stats

0

Bookmarked

3

Total users

3

Monthly active users

6 days ago

Last modified

Share

fast-tracker — BitTorrent DHT corpus search & live crawl statistics

Search a BitTorrent DHT metadata corpus that is being collected right now, and see for yourself how fast it is growing.

You need nothing but a query. No endpoint, no key, no infrastructure — the corpus is crawled and hosted by this Actor's operator.

/searchfull-text search across the corpus, with category filters and four orderings
/statshow fast the corpus is actually growing, measured so you can check it

Two ways to use it

Run it. Pick an action, fill in a query, get an Apify dataset. Export to JSON, CSV or Excel like any other Actor.

Call it. The Actor also runs as an HTTP service, so you can query it from your own code with your Apify token:

curl -H "Authorization: Bearer $APIFY_TOKEN" \
"https://OPERATOR--fast-tracker.apify.actor/search?q=ubuntu&category=software&sort=relevance&limit=10"
curl -H "Authorization: Bearer $APIFY_TOKEN" \
"https://OPERATOR--fast-tracker.apify.actor/stats?window_minutes=30"

Both hit the same corpus and return the same records.


ParameterValues
qfree text, ≤200 chars. Separators are normalised, so ubuntu 24 04 matches ubuntu-24.04-desktop-amd64.iso
categoryvideo audio software archive document image — see the note below
sortseeders (default) newest relevance size
year resolutione.g. 2024, 1080p
min_seedersinteger; falls back to the DHT peer count where the tracker scrape has not run
limit offset1–200 (default 50), 0–100000

Each record carries infohash, name, size_bytes, files, category, seeders, leechers, dht_peers, first_seen, magnet, and — where the parser has reached them — year, resolution, codec, season, episode.

Categories describe file content, not intent

Worth reading before you use the filter, because it is exact and a wrong guess returns nothing rather than less:

categorywhat lands there
archive.iso .zip .rar .7z .tar .gzincluding Linux and game disc images
software.exe .msi .dmg .apk .deb .rpm .bin — installers and packages
video.mp4 .mkv .avi .mov
audio.mp3 .flac .wav
document.pdf .epub .mobi .doc
image.jpg .png .gif

A record is filed by whichever category holds the most bytes, so a release with a large video file and a small readme is video.

The one that catches people: searching ubuntu under software returns nothing, because the ISO is an archive. Leave the category unset unless you know which side of that line your target falls on.

This is a crawl, not a catalogue

Worth setting expectations before your first query. The corpus is built by sampling the DHT and fetching metadata for what it finds, so its contents are whatever peers happened to be sharing when the crawler looked. It is not seeded from any site's index and it is not curated.

Practically: broad terms work well, a specific title may genuinely be absent, and an empty result is a real answer rather than an error. Run the Crawl statistics action to see how large the corpus is and what categories it actually holds.

About the orderings

seeders, newest and size are the corpus server's own orderings. The request is forwarded and its response is returned untouched.

relevance is different, and worth understanding before you rely on it. The underlying API has no relevance ranking: its full-text index is never asked to score matches, and its fast index ranks by seeder count fixed at build time. The three orderings it actually implements are seeders, size and capture time.

So relevance is computed by this Actor. It pulls a candidate window in the API's own best-first order and re-ranks it on a transparent score — how much of your query the name contains (0.60), whether those words appear together and in order (0.20), how early the match starts (0.10), how much of the name is the match so packs sink (0.05), and seeders as a tiebreak only (0.05).

That means relevance re-ranks candidates, not the whole corpus. A record this score would love, sitting outside the candidate window, will not appear. The X-Relevance-Candidates and X-Relevance-Exhaustive response headers tell you which situation you are in. Ranking changes the order of records and nothing else — no injected score field, no annotation.


/stats — meant to be checked, not believed

Any dataset can claim to be fresh. The claim is only worth something if you can arrive at the number yourself, so nothing in this report is taken from server-side reporting. Two independent measurements:

1. Count the records. Walk the search API backwards through capture time and bucket every record into whole UTC minutes by its first_seen field. The rate is the count divided by the window — and the report ships the count, the window, the pages fetched and the records examined, so you can check the division rather than trust it.

2. Watch the counter move. Read the corpus row count before the walk and again after it. If the corpus were a static dump, or the rate a stored constant, that delta would be zero while the histogram claimed otherwise.

The two agreeing is the actual claim. Either alone is a number in a JSON file.

Three details decide whether the figure is honest, and each is a named behaviour rather than a footnote:

  • The minute in progress is excluded. Counting a partial minute as a whole one biases every rate downwards, by a random amount depending on when the run started.
  • Records are deduplicated by infohash. The corpus is being written to while it is read; offset paging re-serves rows when new records land ahead of the cursor.
  • A truncated walk shortens the window instead of extrapolating. If the page budget runs out, the half-counted minute is dropped from both the count and the divisor, and the result says complete: false.

Sample output

{
"type": "fast-tracker-crawl-report",
"generated_at": "2026-08-07T04:15:00.412Z",
"instance_id": "4824992f720bacee",
"corpus": {
"torrents": 213727,
"searchable": 213727,
"tracker_scraped": 201668,
"tracker_scraped_pct": 94.4,
"newest_capture": "2026-08-07 04:14:59",
"newest_capture_age_seconds": 31,
"by_category": { "video": 138603, "audio": 41205, "software": 18844 }
},
"capture_rate": {
"window_start": "2026-08-07T03:15:00.000Z",
"window_end": "2026-08-07T04:15:00.000Z",
"window_minutes": 60,
"captured": 8855,
"per_minute": 147.6,
"per_hour": 8856,
"per_day_projected": 212544,
"complete": true,
"per_minute_series": [
{ "minute": "2026-08-07T03:15Z", "captured": 149 },
{ "minute": "2026-08-07T03:16Z", "captured": 143 }
// ... one entry per minute in the window, zeroes included
],
"method": {
"derivation": "every returned record bucketed by first_seen into whole UTC minutes; captured / window_minutes",
"excludes_minute_in_progress": true,
"deduplicated_by": "infohash"
},
"accounting": {
"pages_fetched": 45, "page_size": 200, "records_examined": 8912,
"records_counted": 8855, "duplicates_skipped": 57, "truncated": false
}
},
"cross_check": {
"torrents_before": 213727, "torrents_after": 213802,
"delta": 75, "elapsed_seconds": 31.2,
"per_minute": 144.2, "confidence": "good"
}
}

Written to the dataset and to the key-value store under CRAWL_STATS and OUTPUT.

The cross-check needs a measurable interval to mean anything. Under ten seconds the crawler's batch-commit boundaries dominate and the figure is noise, which is what confidence reports. Set Cross-check dwell to 60 seconds or more if you intend to quote it.

Over HTTP, /stats is computed at most once per cache interval and shared between concurrent callers. Without that, the endpoint would be an amplifier pointed at the machine doing the crawling.


What this Actor does not expose

The corpus host is infrastructure, not part of the product, and it stays out of everything this Actor produces.

Never written to a dataset, the key-value store, an HTTP response or a run log: the corpus endpoint's URL, hostname, IP or port; its API key; filesystem paths; software versions; crawler tuning; any peer or DHT address.

  • Credentials are not input fields. They live in the operator's environment, so there is no form field a caller can set — which also means there is no way to point this Actor at a host of your choosing and have it fetch that instead.
  • The key travels in a header, never a query string.
  • Reports identify the source only by instance_id, a SHA-256 prefix of the origin. Two reports from the same corpus share an id; the id leads nowhere.
  • Every string reaching a log line, error response or failure message passes a redactor first. Network errors quote the host they failed to reach, and that is the leak that actually happens.
  • Corpus statistics are copied field by field from an allow-list, so a future server release cannot start publishing something host-shaped by accident.

The test suite asserts this end to end: after a full run, no file the Actor writes contains the endpoint, its host, or the key.


Limits

Paging depthoffset is capped at 100000, so about 100200 records are reachable for any one query. Narrow the query rather than paging deeper.
Page size200 records.
Relevance costOne relevance request becomes several upstream requests — one per 200 candidates.
Statistics costThe rate is counted from real records, so a 60-minute window is roughly 45 requests. Over HTTP the window is capped at 60 minutes and defaults to 10.
FreshnessSearch responses are cached for 30s upstream. year and resolution are only populated for records the parser has reached.

Responsible use

This Actor searches an index of public BitTorrent DHT metadata: infohashes, names, sizes and swarm counts. It does not host, transfer or distribute any content, and it does not resolve to any file.

A DHT crawl indexes whatever it finds, which includes material that is illegal to possess in most jurisdictions. The corpus operator is responsible for filtering what their instance collects and serves; if you build on this output, you are responsible for what you do with it. Results are metadata records about swarms that exist, not an endorsement of any of them, and nothing here is a recommendation to download anything.

Background on the collection method and its obligations: fast-tracker and its NOTICE.md.


Not affiliated

with any torrent site, tracker, or index. The corpus is collected directly from the BitTorrent DHT by the operator's own crawler.

MIT licensed.