1 Overview
A user often wants to mention another user, or point to another event, inside the text of a note. NIP-08 defines how a client records that mention so any other client can read it.
The technique has two parts. The writing client adds a p tag or an e tag to the event's tags array. It then writes a placeholder, #[index], into content at the point of the mention. The number index points at the matching tag.
This NIP applies to text_note events, kind 1, and to any other kind whose content holds readable text. It does not define a new kind, tag name, or message type of its own. It only defines a notation.
NIP-08 is unrecommended. Use NIP-27, Text Note References, for all new work. NIP-27 replaces the numeric #[index] placeholder with a self-describing nostr: URI, so the reference still works even if a tag is reordered or dropped. Read this chapter to understand old events, not to build new features.
2 Writing a Mention
A client that lets a user create tagged mentions must follow two rules, in order.
| Step | Requirement | Rule |
|---|---|---|
| 1. Detect | MUST | Show an autocomplete component, or something like it, when the user starts a mention (for example by typing @) or presses a button for it. A client may instead use any other method that unambiguously tells a mention apart from normal text. |
| 2. Encode | MUST | Add the mentioned pubkey or event ID to tags, using tag name p for a user or e for an event. Then replace the mention text in content with #[index], where index is the 0-based position of that tag inside the tags array. |
"content": "gm #[0], nice job on #[1]" "tags": [ ["p", "27866e9d854c78ae625b867eefdfa9580434bc3e675be08d2acb526610d96fbe"], ["e", "7b2e3a1f9c6d8508e6f9a1e6b8b6f4c1c1d1e59b0f6e6b1a4f7c9a2e1b3d4c5e"] ]
Here #[0] points at tags[0], the p tag, a mention of that user. #[1] points at tags[1], the e tag, a mention of that event.
The source text never names e explicitly for event mentions. It only says "the same process applies for mentioning event IDs." The tag name e is implied by NIP-01 convention and by the later rule that only e and p tags are valid mention targets. The phrase "or a tag otherwise declared to support this notation" is also left undefined: no other NIP registers itself against NIP-08 this way.
3 Reading a Mention
A client that receives an event with #[index] placeholders in content can look up each index in tags and show something richer than raw text.
| Case | Requirement | Rule |
|---|---|---|
| Valid index | CAN | Search and replace #[index] with the pubkey or event ID from the matching tag. The client may add context, such as a link to the user or a preview of the mentioned event. |
| Invalid index | MUST NOT | When index is outside the range of tags, or the tag it points at is not e, not p, and not otherwise declared to support this notation, the client must not replace or augment it. It must display #[index] as plain text. |
Reading support is optional. A client with no interest in rich mentions can always show the raw #[index] text and still be a correct NIP-08 client.
4 Worked Example
Alice mentions Bob in a text note. Her client adds a p tag and writes #[0] in place of Bob's name. Carol's client then resolves it back to a link. Orange lines go to the relay. Blue lines come from the relay.
-- Alice's client turns "@bob" into a p tag plus a placeholder -- → ["EVENT", {"id":"a41c9e…","pubkey":"a1b2c3…","created_at":1749762600, "kind":1,"tags":[["p","27866e9d854c78ae625b867eefdfa9580434bc3e675be08d2acb526610d96fbe"]], "content":"gm #[0], see you at the meetup","sig":"e8551d85…"}] ← ["OK", "a41c9e…", true, ""] -- Carol's client fetches the note -- → ["REQ", "feed", {"kinds":[1], "limit":10}] ← ["EVENT", "feed", {"id":"a41c9e…","kind":1, "tags":[["p","27866e9d854c78ae625b867eefdfa9580434bc3e675be08d2acb526610d96fbe"]], "content":"gm #[0], see you at the meetup", …}] ← ["EOSE", "feed"] -- Carol's client resolves #[0] against tags[0] -- -- index 0 is in range and points at a p tag: replace and link -- -- displayed text: "gm @bob, see you at the meetup" -- a malformed note, for comparison -- -- content: "check #[3] out", tags has only 1 entry -- -- index 3 is out of range: display "#[3]" as plain text, no link --
5 Version History
NIP-08 is final and deprecated; no further spec changes are expected. Notable changes, newest first:
- 20232023-11Removed the
author:tags from every NIP, including this one'sfiatjafandscsibugcredits. - 20232023-04Turned the deprecation warning's plain-text mention of NIP-27 into a link.
- 20232023-03-25Added the
unrecommendedtag alongsidefinal, formalizing the deprecation. - 20232023-03-22Changed the warning wording from "discouraged" to "deprecated".
- 20232023-03-21Added the warning banner at the top of the document, pointing to the new NIP-27.
- 20232023-03-05Added the MUST NOT rule: clients must not resolve or augment a
#[index]that is out of range or points at an unsupported tag. - 20222022-11Marked
final: no further spec changes expected. - Origin2022-05Migrated into the
nostr-protocol/nipsrepository, authored by fiatjaf and scsibug.
Original Proposal - Credits
| Author | fiatjaf (co-authored with scsibug) |
| First commit | 2022-05-01 — "migrate nips from main nostr repo." |
| Status | final - unrecommended - optional — deprecated in favor of NIP-27 |
| Source | 08.md on GitHub - full change history |
6 See Also
- NIP-27 — Text Note References. The recommended replacement, using
nostr:URIs instead of numeric placeholders. - NIP-01 — base event format,
tagsarray, and thee/ptags this notation depends on. - NIP-10 — text notes and reply threading, the main home of the
etag inkind:1notes. - NIP-19 — bech32
npub/noteencodings used to display the pubkeys and event IDs a mention resolves to. - NIP-21 — the
nostr:URI scheme that NIP-27 mentions use in place of#[index].