1 Overview
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 bech32-encoded text formats that give each kind of value its own readable prefix.
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.
These formats exist for humans: 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 NIP-01. The core protocol still runs on hex and raw bytes.
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.
2 Bare Keys and IDs
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.
| Prefix | Encodes | Raw size |
|---|---|---|
| npub | a public key | 32 bytes |
| nsec | a private key | 32 bytes |
| note | an event id | 32 bytes |
-- hex pubkey -- 3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d -- same key, npub form -- npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6
Bare bech32 forms never go inside a signed event or a NIP-05 JSON response. An npub key MUST NOT appear in a NIP-01 event or a NIP-05 response. Only lowercase hex is valid there.
A client should still accept a key typed as hex or as npub. Convert whichever form arrives into hex internally, right away.
3 Shareable Identifiers with TLV
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 TLV items: Type, Length, Value.
Each TLV item has a 1-byte type (T, a number 0-255), a 1-byte length (L, a number 0-255), and then exactly L bytes of value (V). Items are packed back to back until the payload ends.
| Prefix | Points to | Status |
|---|---|---|
| nprofile | a nostr profile | draft |
| nevent | a nostr event | draft |
| naddr | a nostr addressable event coordinate | draft |
| nrelay | a nostr relay | deprecated |
nrelay is deprecated as of 2024. Do not encode new nrelay strings. A relay URL can travel instead as a relay TLV item (type 1) inside nprofile, nevent, or naddr.
TLV Type Registry
Four TLV types are standardized. The same type number means something different depending on which prefix carries it:
| Type | Name | In nprofile | In nevent | In naddr |
|---|---|---|---|---|
| 0 | special | 32-byte profile public key | 32-byte event id | the identifier - the event's d tag value. Empty string for a normal (non-addressable) replaceable event. |
| 1 | relay | optional relay URL, ascii, may repeat | optional relay URL, ascii, may repeat | optional relay URL, ascii, may repeat |
| 2 | author | not used | optional 32-byte author pubkey | required 32-byte author pubkey |
| 3 | kind | not used | optional kind, 32-bit unsigned integer, big-endian | required kind, 32-bit unsigned integer, big-endian |
Type 1 (relay) 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.
The source spec names naddr's type-0 payload only "the identifier (the d tag)"; it does not spell out that this makes an naddr without an author (type 2) or kind (type 3) ambiguous to decode, even though both are marked required for naddr in the same table. The source also gives no encoding example for nevent, naddr, or the deprecated nrelay - only npub, nsec, and nprofile have worked examples - and it never states why nrelay was deprecated.
4 Usage Rules
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 NIP-01.
| Use them for | Never use them for |
|---|---|
| Showing a key or id on screen | An event's id, pubkey, or a p/e/a tag value |
| QR codes | A REQ filter, such as authors, ids, #e, or #p |
| Copy-paste and manual sharing | Any field that NIP-01 defines as hex |
| User input fields (a client converts to hex right away) | A NIP-05 JSON response |
nostr: links, see NIP-21 | - |
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.
5 Worked Examples
These pairs are the reference examples from the spec. Use them to check that an implementation encodes and decodes correctly.
npub10elfcs4fr0l0r8af98jlmgdh9c8tcxjvz9qkw038js35mp4dma8qzvjptg decodes to hex pubkey 7e7e9c42a91bfef19fa929e5fda1b72e0ebc1a4c1141673e2794234d86addf4e
nsec1vl029mgpspedva04g90vltkh6fvh240zqtv9k0t9af8935ke9laqsnlfe5 decodes to hex private key 67dea2ed018072d675f5415ecfaed7d2597555e202d85b3d65ea4e58d2d92ffa
nprofile1qqsrhuxx8l9ex335q7he0f09aej04zpazpl0ne2cgukyawd24mayt8gpp4mhxue69uhhytnc9e3k7mgpz4mhxue69uhkg6nzv9ejuumpv34kytnrdaksjlyr9p decodes into a TLV list: pubkey (type 0): 3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d relay (type 1): wss://r.x.com relay (type 1): wss://djbas.sadkb.com
nprofile prefix.6 Version History
Notable changes to NIP-19, newest first:
- 20262026-03Added the 5000-character size recommendation for bech32-formatted strings. (#2264, hodlbod)
- 20252025-06Finished renaming "parameterized replaceable event" to "addressable event" throughout the text. (#1948, #1418)
- 20242024-07Deprecated
nrelay. - 20232023-08Defined how to encode a normal (non-addressable) replaceable event as
naddr: leave the identifier empty. - 20232023-04Clarified that unrecognized TLV types must be ignored, not rejected; documented the optional
kindTLV onnevent. - 20232023-03Documented the optional author pubkey TLV on
nevent. - 20232023-02The addressable-event identifier took its final shape: renamed
nreftonitemtonaddr, its tag fromitoa, and added thekindTLV. - 20232023-01Added TLV-encoded shareable identifiers:
nprofile,nevent, and relay entities (nrelay). (#196, Semisol) - 20222022-12Added worked examples and clarified the NIP's purpose.
- Origin2022-12-16fiatjaf published NIP-19: bech32-encoding of keys, ids, and other information. (#57)
Original Proposal - Credits
| Author | fiatjaf |
| First commit | 2022-12-16 — “add NIP-19: bech32-encoding of stuff. (#57)” |
| PR | #57 on GitHub |
| Status | draft - optional |
| Source | 19.md on GitHub - full change history |