Chapter 35 - Media
35
Nostr Implementation Possibility - Hex № 35

Torrents

A torrent index on relays: kind 2003 carries the info hash, file list, and trackers that a client needs to build a magnet link.

1 Overview

BitTorrent indexes are usually websites. A website can go down or get seized. This NIP moves the index to Nostr. It defines kind 2003, a torrent index event.

A kind-2003 event holds just enough information to search for content and to construct a magnet link. No torrent files exist on Nostr. The relay stores only metadata. Download traffic stays in the BitTorrent swarm.

The NIP also defines kind 2004, a comment on a torrent event. Both kinds sit in the regular event range of NIP-01, so relays store all of them.

Hint!

A magnet link has the form magnet:?xt=urn:btih:HASH. The hash is the V1 BitTorrent info hash. That single value identifies the torrent in the swarm. Everything else in the event is search metadata.

Publisher client Relay Searcher client Swarm BitTorrent kind 2003 REQ / EVENT magnet:?xt=…
Fig. 35-1 — Index on Nostr, data in the swarm. The relay never sees torrent content, only the metadata event.

2 The Torrent Event (Kind 2003)

A torrent index event is a regular event with kind 2003. The content field holds a long, pre-formatted description. The tags hold the machine-readable index data:

Wire format - kind 2003 torrent event
{
  "kind": 2003,
  "content": <long description, pre-formatted>,
  "tags": [
    ["title", <torrent title>],
    ["x", <V1 BitTorrent info hash>],
    ["file", <file path>, <file size in bytes>],
    ["tracker", <tracker URL, optional>],
    ["i", <prefix>:<external reference>],
    ["t", <category label>]
  ]
}
Tag reference - kind 2003
TagValueRule
xV1 BitTorrent info hashThe hash from the magnet link magnet:?xt=urn:btih:HASH (BEP-53). Single-letter, so relays index it per NIP-01.
filefull file pathOne file entry inside the torrent, with its full path, for example info/example.txt. The second value is the file size in bytes. Repeat the tag for each file.
trackertracker URLOptional. A tracker to use for this torrent. Repeat the tag for each tracker.
titletorrent titleThe display name of the torrent.
iprefixed referenceA reference to an external database. See §3.
tcategory labelA general category such as movie, tv, HD, or UHD. You SHOULD include a few of these to make the torrent searchable by category.
Tech Note

The source spec is loose in two places. The title tag and the file-size value appear only in the example JSON, not in the tag list. And the example JSON in the source carries a trailing comma after the last tag, so it is not valid JSON as printed. The example in §5 fixes the comma.

3 External References: the i Tag

An i tag labels the content with a reference into an external database. The value is a prefix, then :, then the reference, for example ["i", "imdb:1234"]. The spec defines seven prefixes:

Tag prefixes for i tags
PrefixDatabaseRule
tcattext category pathA comma-separated category path, for example ["i", "tcat:video,movie,4k"]. It should match the newznab category in a best-effort way.
newznabnewznabThe numeric category ID from the newznab standard category list.
tmdbThe Movie DatabaseA themoviedb.org ID.
ttvdbTheTVDBA thetvdb.com ID.
imdbIMDBAn imdb.com ID.
malMyAnimeListA myanimelist.net ID.
anilistAniListAn anilist.co ID.

Second-level prefixes

Some databases hold several media types under one ID space. For those, include a second-level prefix that names the media type:

Second-level prefix mapping
tmdb:movie:693134   → themoviedb.org/movie/693134
ttvdb:movie:290272  → thetvdb.com/movies/dune-part-two
mal:anime:9253      → myanimelist.net/anime/9253
mal:manga:17517     → myanimelist.net/manga/17517
Warning!

The URL mapping is not always direct. The ttvdb example above maps to a slug, not to the raw ID. Full URL mapping is out of scope for this NIP. The table is only a guide, so implementers have enough information to map the URL if they wish.

Tech Note

The prefix intro in the source shows imdb:1234, but the full example uses imdb:tt15239678. The spec never states whether the IMDB reference carries the tt prefix. Implementations should accept both forms when searching.

4 Torrent Comments (Kind 2004)

A torrent comment is a kind 2004 event. It replies to a torrent event. It works exactly like a kind 1 text note. Follow NIP-10 for its e and p tagging.

kind 2003 torrent index kind 2004 comment ["e", <torrent id>] Threading rules come from NIP-10, the same as kind-1 replies.
Fig. 35-2 — Comment threading. A kind-2004 comment tags the torrent event it replies to.

5 Worked Example

A publisher indexes a 4K movie release. The event lists two files, two trackers, five external references, and two category labels:

Example - kind 2003 torrent index
{
  "kind": 2003,
  "content": "Dune: Part Two (2024) 2160p UHD remux.\nAudio: TrueHD 7.1.",
  "tags": [
    ["title", "Dune Part Two 2160p"],
    ["x", "2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c"],
    ["file", "Dune.Part.Two.2160p/movie.mkv", "58291736452"],
    ["file", "Dune.Part.Two.2160p/info/example.txt", "1024"],
    ["tracker", "udp://mytacker.com:1337"],
    ["tracker", "http://1337-tracker.net/announce"],
    ["i", "tcat:video,movie,4k"],
    ["i", "newznab:2045"],
    ["i", "imdb:tt15239678"],
    ["i", "tmdb:movie:693134"],
    ["i", "ttvdb:movie:290272"],
    ["t", "movie"],
    ["t", "4k"]
  ]
}

A searcher finds the event by category, reads the x tag, and builds the magnet link. The x, i, and t tags are single-letter, so NIP-01 relays index them for filter queries:

Session transcript - wss://relay.example.com
-- search 4k movies --
→ ["REQ", "tor", {"kinds":[2003], "#t":["4k"], "limit":20}]
← ["EVENT", "tor", {"kind":2003, "tags":[…,["x","2b3c4d5e…0b1c"],…], …}]
← ["EOSE", "tor"]

-- look up one torrent by info hash --
→ ["REQ", "hash", {"kinds":[2003], "#x":["2b3c4d5e…0b1c"]}]

-- client builds the magnet link from the x tag --
magnet:?xt=urn:btih:2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c
  &tr=udp://mytacker.com:1337&tr=http://1337-tracker.net/announce

-- a comment on the torrent (kind 2004, NIP-10 tags) --
→ ["EVENT", {"kind":2004, "content":"Seeding. Thanks!",
     "tags":[["e","<torrent event id>","","root"],["p","<publisher pubkey>"]], …}]
← ["OK", "<comment id>", true, ""]
Hint!

Working implementations to study: dtan.xyz (git.v0l.io/Kieran/dtan) and the torrents view in nostrudel.ninja (github.com/hzrd149/nostrudel).

6 Version History

The number 35 has lived two lives. The original NIP-35, "User Discovery", merged into NIP-05 in 2023. kieran reused the free number for Torrents in 2024. Notable changes, newest first:

  • 20242024-09Formatting cleanup: header styles and JSON formatting normalized across the repo.
  • 20242024-05Tag keys updated: the index tags reached their current names.
  • 20242024-04Added kind-2004 comments. The info hash moved to the single-letter x tag so relays index it, mirroring NIP-94.
  • 20242024-04-14kieran published the Torrents spec, reusing the vacant number 35.
  • 20232023-01The previous occupant of this number, "User Discovery", merged into NIP-05. The number became free.
  • Origin2022-11-19Michael Dilger created the file as NIP-35 "User Discovery" (#73) — an unrelated spec that only shares the number.
Tech Note

Git history for 35.md with rename detection drags in commits from "User Discovery" and from draft events (now NIP-37). Only commits from 2024-04-14 onward describe the Torrents spec. The manifest "created" date, 2022-11-19, is the file's first commit, not the Torrents spec's.

Original Proposal - Credits

Authorkieran (Torrents spec; the 2022 file origin is the unrelated "User Discovery" by Michael Dilger)
First commit2024-04-14 — “torrents” (file path dates to 2022-11-19)
Statusdraft - optional — implement it only if your client indexes torrents
Source35.md on GitHub - full change history

7 See Also

  • NIP-01 — the event format, regular-event storage, and the single-letter tag index used by x, i, and t queries.
  • NIP-10 — the e/p threading rules that kind-2004 comments follow.
  • NIP-94 — file metadata events; the model for the indexed x info-hash tag.
  • NIP-05 — where the original NIP-35, "User Discovery", lives now.