1 Overview
A client needs a way to know who a user follows. NIP-02 defines one kind 3 event for this job: the follow list.
The follow list holds one p tag for each followed profile. A user publishes a new follow list every time their follows change. The newest kind-3 event replaces every older one from the same pubkey, because kind 3 is a replaceable kind under NIP-01.
Clients use the follow list to build a feed, back up a social graph, suggest new profiles to follow, share known relays, and build local "petname" tables. This NIP is marked final and optional: its wire format will not change, but a client does not have to implement it.
NIP-02 was formerly named "Contact List and Petnames" and its kind-3 event was called a "contact list". Both names now mean the same event. See §6 History.
2 The Follow List Event
A follow list is an event with "kind": 3. It contains one p tag for every followed or known profile. The content field is not used; by convention, clients set it to an empty string.
["p", <32-byte hex pubkey>, <main relay URL, or "" >, <petname, or "" >]
| Position | Field | Rule |
|---|---|---|
| 0 | tag name | Always the literal string "p". |
| 1 | pubkey | The 32-byte hex public key of the followed profile. Required. |
| 2 | relay URL | A relay where events from that key can be found. Set to an empty string if not needed. |
| 3 | petname | A local nickname for that profile. Set to an empty string, or leave it out, if not needed. |
{
"kind": 3,
"tags": [
["p", "91cf9..4e5ca", "wss://alicerelay.com/", "alice"],
["p", "14aeb..8dad4", "wss://bobrelay.com/nostr", "bob"],
["p", "612ae..e610f", "ws://carolrelay.com/ws", "carol"]
],
"content": "",
// id, pubkey, created_at, sig — see NIP-01
}
3 Replacing and Updating a Follow List
Every new follow list overwrites the past ones. A published follow list must contain the full set of follows, not just the change. Relays and clients should delete past follow lists as soon as they receive a new one, because kind 3 is a replaceable kind: a relay keeps only the latest event for each pubkey + kind pair.
When a user adds new follows to an existing list, clients should append the new p tags to the end of the list. This keeps the list in chronological order, oldest follow first.
4 Uses
Follow list backup
A relay may store events for a long time. A user can rely on their kind-3 event to back up their follow list. They can recover the list on a new device by fetching it from any relay that has it.
Profile discovery and context augmentation
A client may read a kind-3 event to show which profiles a user follows. A client may also compare follow lists between users, and suggest new profiles to follow based on shared follows. A client may show this data in other contexts too.
Relay sharing
A client may publish a follow list where each p tag names a good relay for that followed profile. Other clients can read these relay URLs and update their own relay lists. This spreads relay knowledge between clients and increases censorship resistance.
Petname scheme
A client can use follow lists from other users to build a local petname table. A petname is a local nickname a user picks for a pubkey. This removes the need for a single global human-readable name.
Petnames chain together. If your follow list names a pubkey "erin", and erin's own follow list names another pubkey "david", a client may show that second pubkey as "david.erin" to you. One more hop gives "frank.david.erin".
-- your follow list -- ["p", "21df6d143fb96c2ec9d63726bf9edc71", "", "erin"] -- erin's follow list -- ["p", "a8bb3d884d5d90b413d9891fe4c4e46d", "", "david"] -- david's follow list -- ["p", "f57f54057d2a7af0efecc8b0b66f5708", "", "frank"] -- your client shows -- 21df6d14… → "erin" a8bb3d88… → "david.erin" f57f5405… → "frank.david.erin"
The source spec defines a pubkey as a "32-byte hex key" (64 hex characters). The petname-scheme example pubkeys, such as 21df6d143fb96c2ec9d63726bf9edc71, are only 32 hex characters (16 bytes) and are not truncated with an ellipsis like the earlier example keys. They cannot be real pubkeys as written. Treat them as illustrative placeholders only, not as a literal wire example.
5 Worked Example
The session below shows Bob publishing a follow list, then Alice fetching it. Orange lines go to the relay. Blue lines come from the relay.
-- Bob publishes his follow list -- → ["EVENT", {"id":"7c2f19ab…","pubkey":"14aeb..8dad4","created_at":1749762600, "kind":3, "tags":[ ["p","91cf9..4e5ca","wss://alicerelay.com/","alice"], ["p","612ae..e610f","ws://carolrelay.com/ws","carol"] ], "content":"","sig":"9a31dd42…"}] ← ["OK", "7c2f19ab…", true, ""] -- Alice requests Bob's follow list -- → ["REQ", "bob-follows", {"kinds":[3], "authors":["14aeb..8dad4"]}] ← ["EVENT", "bob-follows", {"id":"7c2f19ab…", "kind":3, "tags":[…], "content":"", …}] ← ["EOSE", "bob-follows"] → ["CLOSE", "bob-follows"] -- later, Bob adds one more follow and republishes -- → ["EVENT", {"id":"c04e88de…","pubkey":"14aeb..8dad4","created_at":1749849000, "kind":3, "tags":[ ["p","91cf9..4e5ca","wss://alicerelay.com/","alice"], ["p","612ae..e610f","ws://carolrelay.com/ws","carol"], ["p","f57f540..5708","","frank"] ], "content":"","sig":"2be671fa…"}] ← ["OK", "c04e88de…", true, ""] -- the relay now discards the 7c2f19ab… event; c04e88de… is Bob's only follow list --
6 Version History
NIP-02 has kept the same kind-3 wire format since 2022. Changes have been renames and clarifications. Notable changes, newest first:
- 20262026-06Cosmetic: the example code fence label changed from
jsonctoyaml; no wire-format change. - 20242024-01Clarified that clients should append new follows to the end of the list, keeping chronological order.
- 20242024-02 - 2024-09Reworded the content rule to "not used" (from "can be anything, ignored"); minor JSON-comment formatting.
- 20232023-12Renamed the NIP from "Contact List and Petnames" to "Follow List"; the kind-3 event is now called a follow list, not a contact list.
- 20232023-11Removed all per-NIP author bylines repository-wide, including
author:fiatjafandauthor:arcbtcon this page. - 20232023-01 - 2023-03Typo fixes: spelling of "censorship-resistance" and a missing closing brace in the example event.
- 20222022-11Status changed from
drafttofinal: the wire format was declared stable. - 20222022-06Disallowed
nullplaceholders in tag entries. Relay URL and petname must be an empty string, notnull, when absent. - Origin2022-05-01fiatjaf published the spec as "Contact List and Petnames", co-credited with arcbtc, in the migration to the
nostr-protocol/nipsrepository.
Original Proposal - Credits
| Author | fiatjaf (co-credited with arcbtc in the original byline) |
| First commit | 2022-05-01 — "migrate nips from main nostr repo." |
| Status | final - optional — stable wire format, implementation not required |
| Source | 02.md on GitHub - full change history |
7 See Also
- NIP-01 — defines the event object, the
ptag's basic form, and the replaceable-kind rule that this NIP depends on. - NIP-51 — generic lists. Follow lists are a fixed, single-purpose case of the more general list format.
- NIP-65 — a dedicated relay list event, a more structured alternative to the relay-sharing use of the
ptag here. - NIP-19 — bech32
npubencoding for the raw hex pubkeys stored inptags. - NIP-24 — extra profile metadata a client can show alongside a followed pubkey.