12<html lang="en">3<head>4<meta charset="utf-8">5<meta name="viewport" content="width=device-width, initial-scale=1">6<title>NIP-94 - File Metadata — Nostr Instruction Manual</title>7<meta name="description" content="NIP-94: file metadata events. Kind 1063 describes a shared file with its URL, MIME type, hashes, and preview data so relays and clients can index files. Complete manual page.">8<link rel="preload" href="../assets/fonts/michroma-400-latin.woff2" as="font" type="font/woff2" crossorigin>9<link rel="preload" href="../assets/fonts/exo2-var-latin.woff2" as="font" type="font/woff2" crossorigin>10<link rel="preload" href="../assets/fonts/sairacondensed-600-latin.woff2" as="font" type="font/woff2" crossorigin>11<link rel="preload" href="../assets/fonts/sairacondensed-700-latin.woff2" as="font" type="font/woff2" crossorigin>12<link rel="preload" href="../assets/fonts/sairacondensed-500-latin.woff2" as="font" type="font/woff2" crossorigin>13<link rel="preload" href="../assets/fonts/sharetechmono-400-latin.woff2" as="font" type="font/woff2" crossorigin>14<link rel="preload" href="../assets/fonts/exo2-400i-latin.woff2" as="font" type="font/woff2" crossorigin>15<link rel="icon" href="../assets/favicon.svg" type="image/svg+xml">16<link rel="stylesheet" href="../assets/manual.css">17</head>18<body>1920<svg width="0" height="0" style="position:absolute">21 <defs>22 <marker id="arr" markerWidth="9" markerHeight="9" refX="7" refY="4.5" orient="auto">23 <path d="M1,1 L8,4.5 L1,8 Z" fill="#f26a00"/>24 </marker>25 <marker id="arrb" markerWidth="9" markerHeight="9" refX="7" refY="4.5" orient="auto">26 <path d="M1,1 L8,4.5 L1,8 Z" fill="#2e5f9e"/>27 </marker>28 </defs>29</svg>3031<div class="page">32 <span class="staple s1"></span><span class="staple s2"></span>3334 <header class="band">35 <a class="logo" href="../index.html">NOSTR<b>▸</b>PROTOCOL MANUAL</a>36 <span class="booklet-note">Chapter 94 - Media</span>37 </header>38 <nav class="tabs">39 <a href="../index.html">Contents</a>40 <a href="#overview" class="on">Overview</a>41 <a href="#spec">Spec</a>42 <a href="#examples">Examples</a>43 <a href="#history">History</a>44 </nav>4546 <div class="chapter">47 <div class="nipno" data-n="94">94</div>48 <div class="titles">49 <div class="kicker">Nostr Implementation Possibility - Hex № 94</div>50 <h1>File Metadata</h1>51 <p class="sub">One event kind that describes a shared file: where it lives, what it is, and how to verify it. The building block for filesharing clients.</p>52 </div>53 </div>5455 <main class="spread">56 <div class="main">5758 <h2 class="bar" id="overview"><span class="num">1</span> Overview</h2>59 <p>This NIP lets a user describe a file in a signed event. The event does not carry the file. It carries <strong>metadata</strong>: a download URL, a MIME type, hashes, and optional preview data.</p>60 <p>With this metadata, relays can filter and organize shared files in any way they choose. Clients can then build many kinds of filesharing experiences on top of the same events.</p>61 <p>The audience is narrow on purpose. "Social" clients that render <code>kind:1</code> notes (<a href="10.html">NIP-10</a>) are not expected to support this NIP. Longform clients that render <code>kind:30023</code> articles (<a href="23.html">NIP-23</a>) are not expected to support it either. For media attached inside notes, use the <code>imeta</code> tag from <a href="92.html">NIP-92</a> instead.</p>6263 <div class="box hint">64 <span class="tag">Hint!</span>65 <p>Think of a kind 1063 event as a library index card. The card names the book, the shelf, and a fingerprint of the book. The book itself sits somewhere else — on an HTTP server, or in a torrent swarm.</p>66 </div>6768 <figure class="diagram">69 <div class="frame">70 <svg viewBox="0 0 560 210" role="img" aria-label="Uploader stores a file on a file server and publishes a kind 1063 event to a relay; a filesharing client queries the relay and then downloads the file from the file server">71 <rect class="d-actor" x="10" y="80" width="110" height="50" rx="8"/>72 <text class="d-actor-label" x="65" y="109" text-anchor="middle">Uploader</text>73 <rect class="d-actor" x="225" y="20" width="110" height="44" rx="8"/>74 <text class="d-actor-label" x="280" y="47" text-anchor="middle">File server</text>75 <rect class="d-actor" x="225" y="146" width="110" height="44" rx="8"/>76 <text class="d-actor-label" x="280" y="173" text-anchor="middle">Relay</text>77 <rect class="d-actor" x="440" y="80" width="110" height="50" rx="8"/>78 <text class="d-actor-label" x="495" y="109" text-anchor="middle">Viewer</text>79 <path class="d-msg" d="M122,92 C170,78 180,58 223,46"/>80 <path class="d-msg d-flow" d="M122,118 C170,132 180,152 223,164"/>81 <path class="d-msg blue d-flow" d="M337,164 C380,152 390,132 438,118"/>82 <path class="d-msg blue" d="M337,46 C380,58 390,78 438,92"/>83 <text class="d-label" x="150" y="48" text-anchor="middle">upload file</text>84 <text class="d-label" x="150" y="182" text-anchor="middle">EVENT 1063</text>85 <text class="d-label" x="410" y="182" text-anchor="middle">REQ / EVENT</text>86 <text class="d-label" x="415" y="48" text-anchor="middle">GET url</text>87 <circle r="4" fill="#f26a00">88 <animateMotion dur="2.6s" repeatCount="indefinite" path="M122,118 C170,132 180,152 223,164"/>89 </circle>90 <circle r="4" fill="#2e5f9e">91 <animateMotion dur="2.6s" begin="1.3s" repeatCount="indefinite" path="M337,164 C380,152 390,132 438,118"/>92 </circle>93 </svg>94 </div>95 <figcaption>Fig. 94-1 — <b>Metadata and file travel apart.</b> The relay only sees the kind 1063 index card. The file server holds the bytes.</figcaption>96 </figure>9798 <h2 class="bar" id="spec"><span class="num">2</span> The Kind 1063 Event</h2>99 <p>This NIP defines one event kind: <strong>1063</strong>. It is a regular event, so relays store all of them (<a href="01.html">NIP-01</a>). The <code>content</code> field holds a description of the file content — a caption. All file data lives in tags:</p>100101 <div class="crt">102 <div class="titlebar">Event template - kind 1063</div>103<pre>{104 <span class="k">"kind"</span>: 1063,105 <span class="k">"tags"</span>: [106 [<span class="s">"url"</span>, <span class="c"><string with URI of file></span>],107 [<span class="s">"m"</span>, <span class="c"><MIME type></span>],108 [<span class="s">"x"</span>, <span class="c"><Hash SHA-256></span>],109 [<span class="s">"ox"</span>, <span class="c"><Hash SHA-256></span>],110 [<span class="s">"size"</span>, <span class="c"><size of file in bytes></span>],111 [<span class="s">"dim"</span>, <span class="c"><size of file in pixels></span>],112 [<span class="s">"magnet"</span>, <span class="c"><magnet URI></span>],113 [<span class="s">"i"</span>, <span class="c"><torrent infohash></span>],114 [<span class="s">"blurhash"</span>, <span class="c"><value></span>],115 [<span class="s">"thumb"</span>, <span class="c"><string with thumbnail URI></span>, <span class="c"><Hash SHA-256></span>],116 [<span class="s">"image"</span>, <span class="c"><string with preview URI></span>, <span class="c"><Hash SHA-256></span>],117 [<span class="s">"summary"</span>, <span class="c"><excerpt></span>],118 [<span class="s">"alt"</span>, <span class="c"><description></span>]119 ],120 <span class="k">"content"</span>: <span class="c">"<caption>"</span>,121 <span class="c">// other fields per NIP-01...</span>122}</pre>123 </div>124125 <h2 class="bar" id="tags"><span class="num">3</span> Tag Reference</h2>126 <p>The tag list below is the full set this NIP defines. The first four tags carry the core identity of the file. The rest are optional helpers for previews, transports, and accessibility.</p>127128 <div class="tscroll"><table class="ref">129 <caption>Kind 1063 tags</caption>130 <tr><th>Tag</th><th>Required</th><th>Value</th></tr>131 <tr><td class="btn">url</td><td>yes</td><td>The URL to download the file.</td></tr>132 <tr><td class="btn">m</td><td>yes</td><td>A string that indicates the data type of the file. Use the MIME types format. The value should be lowercase, for example <code>image/webp</code>.</td></tr>133 <tr><td class="btn">x</td><td>yes</td><td>The SHA-256 hash of the file, as a hex-encoded string.</td></tr>134 <tr><td class="btn">ox</td><td>yes</td><td>The SHA-256 hash of the <em>original</em> file, before any transformation done by the upload server. Hex-encoded string.</td></tr>135 <tr><td class="btn">size</td><td>optional</td><td>The size of the file in bytes.</td></tr>136 <tr><td class="btn">dim</td><td>optional</td><td>The size of the file in pixels, in the form <code><width>x<height></code>, for example <code>800x600</code>.</td></tr>137 <tr><td class="btn">magnet</td><td>optional</td><td>A URI to a magnet file.</td></tr>138 <tr><td class="btn">i</td><td>optional</td><td>The torrent infohash.</td></tr>139 <tr><td class="btn">blurhash</td><td>optional</td><td>The blurhash string. The client shows it while it loads the file.</td></tr>140 <tr><td class="btn">thumb</td><td>optional</td><td>The URL of a thumbnail with the same aspect ratio.</td></tr>141 <tr><td class="btn">image</td><td>optional</td><td>The URL of a preview image with the same dimensions.</td></tr>142 <tr><td class="btn">summary</td><td>optional</td><td>A text excerpt.</td></tr>143 <tr><td class="btn">alt</td><td>optional</td><td>A description for accessibility.</td></tr>144 <tr><td class="btn">fallback</td><td>optional</td><td>Zero or more fallback file sources, for the case when <code>url</code> fails. Add one <code>fallback</code> tag per source.</td></tr>145 <tr><td class="btn">service</td><td>optional</td><td>The service type that serves the file, for example <a href="96.html">NIP-96</a>.</td></tr>146 </table></div>147148 <div class="box tech">149 <span class="tag">Tech Note</span>150 <p>The source spec is inconsistent in two places. First, the tag list describes <code>thumb</code> and <code>image</code> as plain URLs, but the event template adds a second <code><Hash SHA-256></code> element to both tags without explaining it. Second, the event template omits the <code>fallback</code> and <code>service</code> tags, even though the tag list defines them. Treat the tag list as the complete reference.</p>151 </div>152153 <h3>Two hashes: x and ox</h3>154 <p>Upload servers often transform files. They may strip metadata, re-encode an image, or compress a video. The result has a new hash. This NIP keeps both fingerprints:</p>155 <ul>156 <li><code>x</code> — the hash of the file as it is served now. Use it to verify a download.</li>157 <li><code>ox</code> — the hash of the original file, before the server transformed it. Use it to match the file the uploader had.</li>158 </ul>159 <p>To verify a file: download it from <code>url</code>, hash the bytes with SHA-256, and compare with <code>x</code>. If the download fails, try each <code>fallback</code> source in turn.</p>160161 <figure class="diagram">162 <div class="frame">163 <svg viewBox="0 0 560 130" role="img" aria-label="Client downloads from url, hashes the bytes with sha256, and compares with the x tag; on failure it tries a fallback source">164 <rect class="d-actor" x="10" y="30" width="110" height="50" rx="8"/>165 <text class="d-actor-label" x="65" y="52" text-anchor="middle">GET url</text>166 <text class="d-note" x="65" y="69" text-anchor="middle">file bytes</text>167 <rect class="d-actor" x="180" y="30" width="100" height="50" rx="8"/>168 <text class="d-actor-label" x="230" y="52" text-anchor="middle">sha256</text>169 <text class="d-note" x="230" y="69" text-anchor="middle">digest</text>170 <rect class="d-actor" x="340" y="30" width="110" height="50" rx="8"/>171 <text class="d-actor-label" x="395" y="52" text-anchor="middle">compare</text>172 <text class="d-note" x="395" y="69" text-anchor="middle">== x tag?</text>173 <path class="d-msg d-flow" d="M122,55 L177,55"/>174 <path class="d-msg d-flow" d="M282,55 L337,55"/>175 <path class="d-msg blue" d="M395,82 C395,112 130,112 68,84"/>176 <text class="d-label" x="240" y="122" text-anchor="middle">on failure: retry with a fallback source</text>177 </svg>178 </div>179 <figcaption>Fig. 94-2 — <b>Verify, then trust.</b> The <code>x</code> hash proves the download matches the event. The <code>fallback</code> tags keep the file reachable.</figcaption>180 </figure>181182 <h2 class="bar" id="usecases"><span class="num">4</span> Suggested Use Cases</h2>183 <p>The spec suggests three applications for kind 1063 events:</p>184 <ul>185 <li>A relay that indexes shared files. For example, a relay that promotes torrents (see <a href="35.html">NIP-35</a>) through the <code>magnet</code> and <code>i</code> tags.</li>186 <li>A pinterest-like client. People share their portfolio and inspire others.</li>187 <li>A simple way to distribute configurations and software updates. The <code>x</code> hash gives integrity for free.</li>188 </ul>189190 <h2 class="bar" id="examples"><span class="num">5</span> Worked Example</h2>191 <p>Alice uploads a photo to a <a href="96.html">NIP-96</a> server. The server strips the EXIF data, so the served file has a new hash. Alice publishes this event:</p>192193 <div class="crt">194 <div class="titlebar">Example - kind 1063 file metadata event</div>195<pre>{196 <span class="k">"id"</span>: <span class="s">"7f3b2ac1e0…"</span>,197 <span class="k">"pubkey"</span>: <span class="s">"a1ce9f00b2…"</span>,198 <span class="k">"created_at"</span>: 1749821000,199 <span class="k">"kind"</span>: 1063,200 <span class="k">"tags"</span>: [201 [<span class="s">"url"</span>, <span class="s">"https://files.example.com/media/dune-sunset.webp"</span>],202 [<span class="s">"m"</span>, <span class="s">"image/webp"</span>],203 [<span class="s">"x"</span>, <span class="s">"3d84f2c9…served-file-hash…b7"</span>],204 [<span class="s">"ox"</span>, <span class="s">"91c0aa47…original-file-hash…e2"</span>],205 [<span class="s">"size"</span>, <span class="s">"482113"</span>],206 [<span class="s">"dim"</span>, <span class="s">"1600x900"</span>],207 [<span class="s">"blurhash"</span>, <span class="s">"LKO2?U%2Tw=w]~RBVZRi};RPxuwH"</span>],208 [<span class="s">"thumb"</span>, <span class="s">"https://files.example.com/thumb/dune-sunset.webp"</span>],209 [<span class="s">"image"</span>, <span class="s">"https://files.example.com/prev/dune-sunset.webp"</span>],210 [<span class="s">"summary"</span>, <span class="s">"Sunset over the dunes, June trip"</span>],211 [<span class="s">"alt"</span>, <span class="s">"Orange sun setting behind sand dunes"</span>],212 [<span class="s">"fallback"</span>, <span class="s">"https://mirror.example.org/dune-sunset.webp"</span>],213 [<span class="s">"service"</span>, <span class="s">"nip96"</span>]214 ],215 <span class="k">"content"</span>: <span class="s">"Sunset over the dunes. Shot on film."</span>,216 <span class="k">"sig"</span>: <span class="s">"c44e01f2…"</span>217}</pre>218 </div>219220 <p>A filesharing client finds the file by its hash. It queries the indexed <code>#x</code> tag, verifies the download, and renders the blurhash while it waits:</p>221222 <div class="crt">223 <div class="titlebar">Session transcript - wss://files-relay.example.com</div>224<pre><span class="c">-- find every event that describes this exact file --</span>225<span class="send">→ ["REQ", "find", {"kinds":[1063], "#x":["3d84f2c9…b7"]}]</span>226<span class="recv">← ["EVENT", "find", {"id":"7f3b2ac1e0…", "kind":1063, …}]</span>227<span class="recv">← ["EOSE", "find"]</span>228<span class="send">→ ["CLOSE", "find"]</span>229<span class="c">-- client: GET url, sha256(bytes) == x → render file --</span></pre>230 </div>231232 <h2 class="bar" id="history"><span class="num">6</span> Version History</h2>233 <p>NIP-94 grew from a two-tag draft into the shared vocabulary for file metadata on Nostr. Notable changes, newest first:</p>234 <ul class="patchnotes">235 <li><span class="ver">2024</span><span class="when">2024-01</span><a href="96.html">NIP-96</a> HTTP file storage integration landed. It defined the upload flow that fills these tags and the <code>ox</code> pre-transformation hash.</li>236 <li><span class="ver">2023</span><span class="when">2023-12</span>Removed the <code>aes-256-gcm</code> encryption tag; nobody used it. Encryption now goes through the <a href="44.html">NIP-44</a> scheme.</li>237 <li><span class="ver">2023</span><span class="when">2023-11</span>The <code>imeta</code> tag arrived (<a href="92.html">NIP-92</a>), carrying NIP-94 fields inside <code>kind:1</code> notes. <a href="71.html">NIP-71</a> video events reuse the same layout.</li>238 <li><span class="ver">2023</span><span class="when">2023-09</span>Big tag expansion: <code>thumb</code>, <code>image</code>, <code>summary</code>, <code>alt</code>, and <code>fallback</code> added. The original-file hash shipped after several revisions as <code>ox</code>.</li>239 <li class="minor"><span class="ver">2023</span><span class="when">2023-09</span>Clarified that <code>m</code> MIME values should be lowercase.</li>240 <li><span class="ver">2023</span><span class="when">2023-04</span>Added the <code>dim</code> tag, explained <code>blurhash</code>, and reworded the NIP to remove confusion.</li>241 <li><span class="ver">2023</span><span class="when">2023-03</span>Changed kind 1063 to a regular event and aligned the draft with other NIPs after review.</li>242 <li><span class="ver">Origin</span><span class="when">2023-03-09</span>frbittencourt created the draft as "NIP 94 and 95". The NIP-95 half (file storage on relays) was never merged.</li>243 </ul>244245 <div class="credits">246 <h3 class="cardhead">Original Proposal - Credits</h3>247 <table>248 <tr><td>Author</td><td>frbittencourt (Fernando Bittencourt)</td></tr>249 <tr><td>First commit</td><td>2023-03-09 — “create draft NIP 94 and 95”</td></tr>250 <tr><td>Status</td><td>draft - optional — only filesharing clients need it</td></tr>251 <tr><td>Source</td><td><a href="https://github.com/nostr-protocol/nips/blob/master/94.md">94.md on GitHub</a> - <a href="https://github.com/nostr-protocol/nips/commits/master/94.md">full change history</a></td></tr>252 </table>253 </div>254255 <h2 class="bar"><span class="num">7</span> See Also</h2>256 <ul>257 <li><a href="01.html">NIP-01</a> — the base event format and tag indexing that kind 1063 relies on.</li>258 <li><a href="96.html">NIP-96</a> — HTTP file storage servers; the natural upload counterpart, referenced by the <code>service</code> tag.</li>259 <li><a href="92.html">NIP-92</a> — the <code>imeta</code> tag; carries these same fields inline in notes, for social clients.</li>260 <li><a href="71.html">NIP-71</a> — video events; reuse the NIP-94 field vocabulary in <code>imeta</code> form.</li>261 <li><a href="35.html">NIP-35</a> — torrent events; the richer path for the <code>magnet</code> and <code>i</code> use case.</li>262 <li><a href="44.html">NIP-44</a> — the encryption scheme that replaced the removed <code>aes-256-gcm</code> tag.</li>263 </ul>264 </div>265266 <aside>267 <div class="cartridge">268 <div class="inner">269 <h3 class="cardhead">Spec Card</h3>270 <div class="lights"><span class="led on"></span><span class="led warn"></span><span class="led warn"></span></div>271 <dl>272 <dt>Status</dt><dd><span class="chip draft">draft</span><span class="chip optional">optional</span></dd>273 <dt>Defines</dt><dd>kind 1063 - url/m/x/ox tags - preview + fallback tags</dd>274 <dt>Kind(s)</dt><dd>1063 (regular)</dd>275 <dt>Requires</dt><dd><a href="01.html">NIP-01</a></dd>276 <dt>Pairs with</dt><dd><a href="96.html">NIP-96</a> uploads - <a href="92.html">NIP-92</a> imeta</dd>277 <dt>Crypto</dt><dd>SHA-256 file hashes</dd>278 <dt>First commit</dt><dd>2023-03-09</dd>279 <dt>Last updated</dt><dd>2026-06-13</dd>280 </dl>281 </div>282 </div>283 </aside>284 </main>285286 <nav class="navbtns">287 <a href="92.html">◀ NIP-92: Media Attachments Metadata (imeta)</a>288 <a href="96.html">NIP-96: HTTP File Storage Integration ▶</a>289 </nav>290291 <footer class="pagefoot">292 <a href="../index.html">Nostr Protocol Manual</a>293 <span class="pageno">NIP 94 / F4</span>294 </footer>295</div>296297<script src="../assets/webmcp.js" defer></script>298</body>299</html>