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.
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.
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:
{
"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 | Value | Rule |
|---|---|---|
| x | V1 BitTorrent info hash | The hash from the magnet link magnet:?xt=urn:btih:HASH (BEP-53). Single-letter, so relays index it per NIP-01. |
| file | full file path | One 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. |
| tracker | tracker URL | Optional. A tracker to use for this torrent. Repeat the tag for each tracker. |
| title | torrent title | The display name of the torrent. |
| i | prefixed reference | A reference to an external database. See §3. |
| t | category label | A general category such as movie, tv, HD, or UHD. You SHOULD include a few of these to make the torrent searchable by category. |
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:
| Prefix | Database | Rule |
|---|---|---|
| tcat | text category path | A comma-separated category path, for example ["i", "tcat:video,movie,4k"]. It should match the newznab category in a best-effort way. |
| newznab | newznab | The numeric category ID from the newznab standard category list. |
| tmdb | The Movie Database | A themoviedb.org ID. |
| ttvdb | TheTVDB | A thetvdb.com ID. |
| imdb | IMDB | An imdb.com ID. |
| mal | MyAnimeList | A myanimelist.net ID. |
| anilist | AniList | An 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:
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
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.
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.
5 Worked Example
A publisher indexes a 4K movie release. The event lists two files, two trackers, five external references, and two category labels:
{
"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:
-- 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, ""]
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
xtag 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.
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
| Author | kieran (Torrents spec; the 2022 file origin is the unrelated "User Discovery" by Michael Dilger) |
| First commit | 2024-04-14 — “torrents” (file path dates to 2022-11-19) |
| Status | draft - optional — implement it only if your client indexes torrents |
| Source | 35.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, andtqueries. - NIP-10 — the
e/pthreading rules that kind-2004 comments follow. - NIP-94 — file metadata events; the model for the indexed
xinfo-hash tag. - NIP-05 — where the original NIP-35, "User Discovery", lives now.