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-19 - Bech32-Encoded Entities — Nostr Instruction Manual</title>7<meta name="description" content="NIP-19: bech32-encoded entities. npub, nsec, note, and the TLV-based nprofile, nevent, naddr identifiers for display, input, and sharing.">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 19 - Encoding</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="19">19</div>48 <div class="titles">49 <div class="kicker">Nostr Implementation Possibility - Hex № 19</div>50 <h1>Bech32-Encoded Entities</h1>51 <p class="sub">Checksummed, human-friendly text formats for keys, ids, and shareable pointers. For display, input, and sharing only - never for the wire.</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>A raw Nostr key or event id is a 32-byte value shown as 64 hex characters. A public key, a private key, and an event id all look the same: a long string of hex digits. This NIP defines <strong>bech32</strong>-encoded text formats that give each kind of value its own readable prefix.</p>60 <p>Bech32 is a checksummed text encoding. A typo in a bech32 string almost always fails the checksum, so a client can reject a bad paste instead of silently using the wrong key. NIP-19 uses the classic bech32 checksum, not the newer bech32m variant used by some other systems.</p>61 <p>These formats exist for <strong>humans</strong>: showing a key on screen, printing a QR code, copying and pasting, typing an id into a search box, or sharing a link. They are not part of the core protocol described in <a href="01.html">NIP-01</a>. The core protocol still runs on hex and raw bytes.</p>6263 <div class="box hint">64 <span class="tag">Hint!</span>65 <p>Store keys and ids as hex or binary inside your app. Encode to bech32 only at the last moment, when you show a value to a user or accept one from a user. Convert back to hex immediately on input.</p>66 </div>6768 <h2 class="bar" id="spec"><span class="num">2</span> Bare Keys and IDs</h2>69 <p>Three entities are 32-byte values with no extra metadata. Each gets its own bech32 prefix so a client, and a human, can tell them apart at a glance.</p>7071 <div class="tscroll"><table class="ref">72 <caption>Bare bech32 prefixes</caption>73 <tr><th>Prefix</th><th>Encodes</th><th>Raw size</th></tr>74 <tr><td class="btn">npub</td><td>a public key</td><td>32 bytes</td></tr>75 <tr><td class="btn">nsec</td><td>a private key</td><td>32 bytes</td></tr>76 <tr><td class="btn">note</td><td>an event id</td><td>32 bytes</td></tr>77 </table></div>7879 <div class="crt">80 <div class="titlebar">Example - hex public key to npub</div>81<pre><span class="c">-- hex pubkey --</span>82<span class="s">3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d</span>8384<span class="c">-- same key, npub form --</span>85<span class="s">npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6</span></pre>86 </div>8788 <div class="box warn">89 <span class="tag">Warning!</span>90 <p>Bare bech32 forms never go inside a signed event or a <a href="05.html">NIP-05</a> JSON response. An <code>npub</code> key MUST NOT appear in a NIP-01 event or a NIP-05 response. Only lowercase hex is valid there.</p>91 </div>92 <p>A client should still accept a key typed as hex or as <code>npub</code>. Convert whichever form arrives into hex internally, right away.</p>9394 <h2 class="bar" id="tlv"><span class="num">3</span> Shareable Identifiers with TLV</h2>95 <p>Sharing a profile or an event often means more than the bare key or id. An app may want to attach relay hints, an author, or a kind, so another app can find and display the entity faster. For this, NIP-19 defines a second family of prefixes whose payload is a binary-encoded list of <strong>TLV</strong> items: Type, Length, Value.</p>96 <p>Each TLV item has a 1-byte type (<code>T</code>, a number 0-255), a 1-byte length (<code>L</code>, a number 0-255), and then exactly <code>L</code> bytes of value (<code>V</code>). Items are packed back to back until the payload ends.</p>9798 <figure class="diagram">99 <div class="frame">100 <svg viewBox="0 0 560 150" role="img" aria-label="TLV byte layout: one byte type, one byte length, then L bytes of value, repeated for each item in the stream">101 <text class="d-actor-label" x="10" y="18">TLV item anatomy (repeats until the payload ends)</text>102 <rect x="10" y="34" width="46" height="46" rx="4" fill="#f26a00"/>103 <text class="d-label" x="33" y="62" text-anchor="middle" fill="#fff">T</text>104 <rect x="60" y="34" width="46" height="46" rx="4" fill="#2e5f9e"/>105 <text class="d-label" x="83" y="62" text-anchor="middle" fill="#fff">L</text>106 <rect x="110" y="34" width="150" height="46" rx="4" fill="#7d8794"/>107 <text class="d-label" x="185" y="62" text-anchor="middle" fill="#fff">V</text>108 <text class="d-note" x="33" y="96" text-anchor="middle">1 byte</text>109 <text class="d-note" x="83" y="96" text-anchor="middle">1 byte</text>110 <text class="d-note" x="185" y="96" text-anchor="middle">L bytes</text>111 <text class="d-note" x="33" y="110" text-anchor="middle">type 0-3</text>112 <text class="d-note" x="83" y="110" text-anchor="middle">length of V</text>113 <text class="d-note" x="185" y="110" text-anchor="middle">the value itself</text>114 <path class="d-wire" d="M270,57 L300,57" stroke-dasharray="3 4"/>115 <text class="d-actor-label" x="380" y="61" text-anchor="middle">next TLV item ...</text>116 <rect x="440" y="34" width="30" height="46" rx="3" fill="#e9e4d3" stroke="#7d8794" stroke-dasharray="3 3"/>117 <rect x="472" y="34" width="30" height="46" rx="3" fill="#e9e4d3" stroke="#7d8794" stroke-dasharray="3 3"/>118 <rect x="504" y="34" width="46" height="46" rx="3" fill="#e9e4d3" stroke="#7d8794" stroke-dasharray="3 3"/>119 </svg>120 </div>121 <figcaption>Fig. 19-1 — <b>TLV item anatomy.</b> Type and length are always 1 byte each. The value's size is whatever length says.</figcaption>122 </figure>123124 <div class="tscroll"><table class="ref">125 <caption>TLV-based shareable prefixes</caption>126 <tr><th>Prefix</th><th>Points to</th><th>Status</th></tr>127 <tr><td class="btn">nprofile</td><td>a nostr profile</td><td><span class="chip draft">draft</span></td></tr>128 <tr><td class="btn">nevent</td><td>a nostr event</td><td><span class="chip draft">draft</span></td></tr>129 <tr><td class="btn">naddr</td><td>a nostr <em>addressable event</em> coordinate</td><td><span class="chip draft">draft</span></td></tr>130 <tr><td class="btn">nrelay</td><td>a nostr relay</td><td><span class="chip unrecommended">deprecated</span></td></tr>131 </table></div>132133 <div class="box danger">134 <span class="tag">Deprecated</span>135 <p><code>nrelay</code> is deprecated as of 2024. Do not encode new <code>nrelay</code> strings. A relay URL can travel instead as a <code>relay</code> TLV item (type 1) inside <code>nprofile</code>, <code>nevent</code>, or <code>naddr</code>.</p>136 </div>137138 <h3>TLV Type Registry</h3>139 <p>Four TLV types are standardized. The same type number means something different depending on which prefix carries it:</p>140 <div class="tscroll"><table class="ref">141 <caption>TLV types 0-3</caption>142 <tr><th>Type</th><th>Name</th><th>In nprofile</th><th>In nevent</th><th>In naddr</th></tr>143 <tr><td class="btn">0</td><td>special</td><td>32-byte profile public key</td><td>32-byte event id</td><td>the identifier - the event's <code>d</code> tag value. Empty string for a normal (non-addressable) replaceable event.</td></tr>144 <tr><td class="btn">1</td><td>relay</td><td>optional relay URL, ascii, may repeat</td><td>optional relay URL, ascii, may repeat</td><td>optional relay URL, ascii, may repeat</td></tr>145 <tr><td class="btn">2</td><td>author</td><td>not used</td><td>optional 32-byte author pubkey</td><td>required 32-byte author pubkey</td></tr>146 <tr><td class="btn">3</td><td>kind</td><td>not used</td><td>optional kind, 32-bit unsigned integer, big-endian</td><td>required kind, 32-bit unsigned integer, big-endian</td></tr>147 </table></div>148 <p>Type 1 (<code>relay</code>) may appear more than once in the same payload; each occurrence is one more relay hint. A decoder that meets a TLV type it does not recognize or support must ignore that item, not raise an error. This keeps old decoders working when a future NIP adds new TLV types.</p>149150 <div class="box tech">151 <span class="tag">Tech Note</span>152 <p>The source spec names <code>naddr</code>'s type-0 payload only "the identifier (the <code>d</code> tag)"; it does not spell out that this makes an <code>naddr</code> without an author (type 2) or kind (type 3) ambiguous to decode, even though both are marked required for <code>naddr</code> in the same table. The source also gives no encoding example for <code>nevent</code>, <code>naddr</code>, or the deprecated <code>nrelay</code> - only <code>npub</code>, <code>nsec</code>, and <code>nprofile</code> have worked examples - and it never states why <code>nrelay</code> was deprecated.</p>153 </div>154155 <h2 class="bar"><span class="num">4</span> Usage Rules</h2>156 <p>Bech32 entities live at the edge of an app, where a human reads or types a value. They never travel inside the protocol messages defined in <a href="01.html">NIP-01</a>.</p>157158 <div class="tscroll"><table class="ref">159 <caption>Where bech32 entities belong</caption>160 <tr><th>Use them for</th><th>Never use them for</th></tr>161 <tr><td>Showing a key or id on screen</td><td>An event's <code>id</code>, <code>pubkey</code>, or a <code>p</code>/<code>e</code>/<code>a</code> tag value</td></tr>162 <tr><td>QR codes</td><td>A <code>REQ</code> filter, such as <code>authors</code>, <code>ids</code>, <code>#e</code>, or <code>#p</code></td></tr>163 <tr><td>Copy-paste and manual sharing</td><td>Any field that NIP-01 defines as hex</td></tr>164 <tr><td>User input fields (a client converts to hex right away)</td><td>A NIP-05 JSON response</td></tr>165 <tr><td><code>nostr:</code> links, see <a href="21.html">NIP-21</a></td><td>-</td></tr>166 </table></div>167168 <figure class="diagram">169 <div class="frame">170 <svg viewBox="0 0 560 210" role="img" aria-label="Hex and binary stay inside events, tags, and filters; bech32 only crosses the boundary to displays, QR codes, clipboards, and nostr colon links, never straight into a relay">171 <rect class="d-actor" x="20" y="20" width="180" height="60" rx="8"/>172 <text class="d-actor-label" x="110" y="45" text-anchor="middle">Event - Tags</text>173 <text class="d-actor-label" x="110" y="63" text-anchor="middle">Filters (NIP-01)</text>174 <text class="d-note" x="110" y="95" text-anchor="middle">hex / binary only</text>175 <rect class="d-actor" x="360" y="20" width="180" height="60" rx="8"/>176 <text class="d-actor-label" x="450" y="45" text-anchor="middle">Display - QR - clipboard</text>177 <text class="d-actor-label" x="450" y="63" text-anchor="middle">nostr: links</text>178 <text class="d-note" x="450" y="95" text-anchor="middle">bech32 (npub, nevent, ...)</text>179 <path class="d-msg blue" d="M205,42 L355,42"/>180 <text class="d-label" x="280" y="35" text-anchor="middle">encode</text>181 <path class="d-msg" d="M355,60 L205,60"/>182 <text class="d-label" x="280" y="78" text-anchor="middle">decode on input</text>183 <rect class="d-actor" x="200" y="150" width="160" height="46" rx="8"/>184 <text class="d-actor-label" x="280" y="178" text-anchor="middle">Relay (WebSocket wire)</text>185 <path class="d-wire" d="M450,80 L450,120 L290,150" stroke="#c0392b" stroke-width="2.5" stroke-dasharray="5 4"/>186 <text x="430" y="125" font-family="var(--f-mono)" font-size="20" fill="#c0392b" text-anchor="middle">✕</text>187 <text class="d-note" x="450" y="140" text-anchor="middle" fill="#c0392b">bech32 direct to relay - never</text>188 <path class="d-wire" d="M110,80 L110,150" stroke="#2c7a3f" stroke-width="2.5"/>189 <text class="d-note" x="130" y="118" fill="#2c7a3f">hex on the wire - always</text>190 </svg>191 </div>192 <figcaption>Fig. 19-2 — <b>The usage boundary.</b> Bech32 forms cross to and from the human edge. Only hex and binary reach the relay.</figcaption>193 </figure>194195 <div class="box warn">196 <span class="tag">Warning!</span>197 <p>Keep bech32-formatted strings at or under 5000 characters. A very long string is a sign of too many relay hints, or a malformed payload.</p>198 </div>199200 <h2 class="bar" id="examples"><span class="num">5</span> Worked Examples</h2>201 <p>These pairs are the reference examples from the spec. Use them to check that an implementation encodes and decodes correctly.</p>202203 <div class="crt">204 <div class="titlebar">Example - npub (bare public key)</div>205<pre><span class="s">npub10elfcs4fr0l0r8af98jlmgdh9c8tcxjvz9qkw038js35mp4dma8qzvjptg</span>206<span class="c">decodes to hex pubkey</span>207<span class="s">7e7e9c42a91bfef19fa929e5fda1b72e0ebc1a4c1141673e2794234d86addf4e</span></pre>208 </div>209210 <div class="crt">211 <div class="titlebar">Example - nsec (bare private key)</div>212<pre><span class="s">nsec1vl029mgpspedva04g90vltkh6fvh240zqtv9k0t9af8935ke9laqsnlfe5</span>213<span class="c">decodes to hex private key</span>214<span class="s">67dea2ed018072d675f5415ecfaed7d2597555e202d85b3d65ea4e58d2d92ffa</span></pre>215 </div>216217 <div class="crt">218 <div class="titlebar">Example - nprofile (TLV-encoded profile)</div>219<pre><span class="s">nprofile1qqsrhuxx8l9ex335q7he0f09aej04zpazpl0ne2cgukyawd24mayt8gpp4mhxue69uhhytnc9e3k7mgpz4mhxue69uhkg6nzv9ejuumpv34kytnrdaksjlyr9p</span>220221<span class="c">decodes into a TLV list:</span>222<span class="k">pubkey</span> (type 0): <span class="s">3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d</span>223<span class="k">relay</span> (type 1): <span class="s">wss://r.x.com</span>224<span class="k">relay</span> (type 1): <span class="s">wss://djbas.sadkb.com</span></pre>225 </div>226227 <figure class="diagram">228 <div class="frame">229 <svg viewBox="0 0 560 160" role="img" aria-label="The three TLV items inside this nprofile: a special type-0 pubkey of 32 bytes, then two type-1 relay items of 13 and 21 bytes">230 <rect x="10" y="10" width="70" height="30" rx="4" fill="#f26a00"/>231 <text class="d-label" x="45" y="30" text-anchor="middle" fill="#fff">T=00 L=20</text>232 <text class="d-note" x="330" y="30">special - pubkey, 32 bytes: 3bf0c63f…aefa459d</text>233 <rect x="10" y="52" width="70" height="30" rx="4" fill="#2e5f9e"/>234 <text class="d-label" x="45" y="72" text-anchor="middle" fill="#fff">T=01 L=0d</text>235 <text class="d-note" x="330" y="72">relay - 13 bytes ascii: wss://r.x.com</text>236 <rect x="10" y="94" width="70" height="30" rx="4" fill="#2e5f9e"/>237 <text class="d-label" x="45" y="114" text-anchor="middle" fill="#fff">T=01 L=15</text>238 <text class="d-note" x="330" y="114">relay - 21 bytes ascii: wss://djbas.sadkb.com</text>239 <text class="d-note" x="10" y="146">Lengths above are hex: 0x20 = 32, 0x0d = 13, 0x15 = 21.</text>240 </svg>241 </div>242 <figcaption>Fig. 19-3 — <b>The nprofile example, byte by byte.</b> Three TLV items concatenated, then bech32-encoded with the <code>nprofile</code> prefix.</figcaption>243 </figure>244245 <h2 class="bar" id="history"><span class="num">6</span> Version History</h2>246 <p>Notable changes to NIP-19, newest first:</p>247 <ul class="patchnotes">248 <li><span class="ver">2026</span><span class="when">2026-03</span>Added the 5000-character size recommendation for bech32-formatted strings. (#2264, hodlbod)</li>249 <li class="minor"><span class="ver">2025</span><span class="when">2025-06</span>Finished renaming "parameterized replaceable event" to "addressable event" throughout the text. (#1948, #1418)</li>250 <li><span class="ver">2024</span><span class="when">2024-07</span>Deprecated <code>nrelay</code>.</li>251 <li><span class="ver">2023</span><span class="when">2023-08</span>Defined how to encode a normal (non-addressable) replaceable event as <code>naddr</code>: leave the identifier empty.</li>252 <li class="minor"><span class="ver">2023</span><span class="when">2023-04</span>Clarified that unrecognized TLV types must be ignored, not rejected; documented the optional <code>kind</code> TLV on <code>nevent</code>.</li>253 <li class="minor"><span class="ver">2023</span><span class="when">2023-03</span>Documented the optional author pubkey TLV on <code>nevent</code>.</li>254 <li><span class="ver">2023</span><span class="when">2023-02</span>The addressable-event identifier took its final shape: renamed <code>nref</code> to <code>nitem</code> to <code>naddr</code>, its tag from <code>i</code> to <code>a</code>, and added the <code>kind</code> TLV.</li>255 <li><span class="ver">2023</span><span class="when">2023-01</span>Added TLV-encoded shareable identifiers: <code>nprofile</code>, <code>nevent</code>, and relay entities (<code>nrelay</code>). (#196, Semisol)</li>256 <li class="minor"><span class="ver">2022</span><span class="when">2022-12</span>Added worked examples and clarified the NIP's purpose.</li>257 <li><span class="ver">Origin</span><span class="when">2022-12-16</span>fiatjaf published NIP-19: bech32-encoding of keys, ids, and other information. (#57)</li>258 </ul>259260 <div class="credits">261 <h3 class="cardhead">Original Proposal - Credits</h3>262 <table>263 <tr><td>Author</td><td>fiatjaf</td></tr>264 <tr><td>First commit</td><td>2022-12-16 — “add NIP-19: bech32-encoding of stuff. (#57)”</td></tr>265 <tr><td>PR</td><td><a href="https://github.com/nostr-protocol/nips/pull/57">#57 on GitHub</a></td></tr>266 <tr><td>Status</td><td>draft - optional</td></tr>267 <tr><td>Source</td><td><a href="https://github.com/nostr-protocol/nips/blob/master/19.md">19.md on GitHub</a> - <a href="https://github.com/nostr-protocol/nips/commits/master/19.md">full change history</a></td></tr>268 </table>269 </div>270271 <h2 class="bar"><span class="num">7</span> See Also</h2>272 <ul>273 <li><a href="01.html">NIP-01</a> — defines the hex <code>id</code>, <code>pubkey</code>, and tag fields that these bech32 forms encode and never replace.</li>274 <li><a href="21.html">NIP-21</a> — the <code>nostr:</code> URI scheme, the main place a bech32 entity is carried inside a clickable link.</li>275 <li><a href="27.html">NIP-27</a> — how a client renders an <code>nprofile</code> or <code>nevent</code> mention inline inside note text.</li>276 </ul>277 </div>278279 <aside>280 <div class="cartridge">281 <div class="inner">282 <h3 class="cardhead">Spec Card</h3>283 <div class="lights"><span class="led on"></span><span class="led on"></span><span class="led on"></span></div>284 <dl>285 <dt>Status</dt><dd><span class="chip draft">draft</span><span class="chip optional">optional</span></dd>286 <dt>Defines</dt><dd>npub - nsec - note - nprofile - nevent - naddr - nrelay (deprecated) - TLV types 0-3</dd>287 <dt>Kind(s)</dt><dd>n/a — a text encoding, not an event kind</dd>288 <dt>Requires</dt><dd><a href="01.html">NIP-01</a> — the hex keys and ids being encoded</dd>289 <dt>Transport</dt><dd>bech32 text strings - display and input only, never the wire</dd>290 <dt>Crypto</dt><dd>same secp256k1 keys/ids as NIP-01 - classic bech32 checksum (not bech32m)</dd>291 <dt>First commit</dt><dd>2022-12-16</dd>292 <dt>Last updated</dt><dd>2026-03-12</dd>293 </dl>294 </div>295 </div>296 </aside>297 </main>298299 <nav class="navbtns">300 <a href="18.html">◀ NIP-18: Reposts</a>301 <a href="20.html">NIP-20: Command Results ▶</a>302 </nav>303304 <footer class="pagefoot">305 <a href="../index.html">Nostr Protocol Manual</a>306 <span class="pageno">NIP 19 / F4</span>307 </footer>308</div>309310<script src="../assets/webmcp.js" defer></script>311</body>312</html>