Chapter 36 - Moderation
36
Nostr Implementation Possibility - Hex № 36

Sensitive Content / Content Warning

One tag that tells clients: hide this content behind a warning until the reader chooses to see it.

1 Overview

Some events carry content that not every reader wants to see at once. Nudity, violence, spoilers, or graphic news are common cases. This NIP gives authors a standard way to flag such an event.

The author adds one tag to the event: content-warning. The tag says that the content needs approval by the reader before a client shows it. A client can hide the content until the user acts on it. The tag works on any event kind.

The flag comes from the author, not from a relay or a moderator. It is a courtesy signal, not access control. The content itself stays in plain view inside the event.

Hint!

A content warning helps your own reach. Readers who dislike surprises can still follow you. Their clients blur the sensitive posts and show everything else as normal.

Event content-warning Client hides content Reader taps "Show" Shown full view
Fig. 36-1 — The reveal flow. The client hides flagged content until the reader approves it.

2 The content-warning Tag

The tag name is content-warning. The tag takes one optional value: a human-readable reason for the warning. This NIP defines no fixed reason vocabulary.

Tag format - content-warning
["content-warning", <optional reason>]
Tag reference
PositionValueRule
content-warningtag nameMarks the event as sensitive. The reader must approve the content before a client shows it.
reasonstringOptional. A free-text reason, for example nudity or graphic violence. Clients can show it on the warning screen.
Tech Note

content-warning is not a single-letter tag, so relays do not index it under NIP-01 rules. You cannot filter on it with a #content-warning key. For queryable warnings, use the NIP-32 labels in §3 and filter on #l or #L.

3 Labels with NIP-32

The l and L tags defined in NIP-32 may also be used on the same event. Use them with the content-warning namespace or with another namespace. Labels add two things that the bare tag lacks:

  • Qualification. A label states a precise category from a named vocabulary, for example NS-nud from the social.nos.ontology namespace.
  • Querying. l and L are single-letter tags. Relays index them, so clients can filter with #l and #L.
Label tags on a flagged event
["L", "content-warning"]            namespace declaration
["l", <reason>, "content-warning"]  label in that namespace
["L", "social.nos.ontology"]        another vocabulary
["l", "NS-nud", "social.nos.ontology"]

Labels do not replace the content-warning tag. Keep the tag on the event so simple clients still hide the content.

4 Worked Example

The event below is a kind-1 text note with a hashtag. The author flags it as sensitive, gives a reason, and adds NIP-32 labels in two namespaces.

Flagged kind-1 note
{
  "id": <event-id>,
  "pubkey": <pub-key>,
  "created_at": 1000000000,
  "kind": 1,
  "tags": [
    ["t", "hastag"],
    ["L", "content-warning"],
    ["l", "reason", "content-warning"],
    ["L", "social.nos.ontology"],
    ["l", "NS-nud", "social.nos.ontology"],
    ["content-warning", <optional reason>]
  ],
  "content": "sensitive content with #hastag\n"
}

The session below shows the tag in use. The client publishes a flagged note. A reader's client receives it and hides the content behind the reason text.

Session transcript - wss://relay.example.com
-- author publishes a flagged note --
→ ["EVENT", {"id":"7f3a21cd90…","pubkey":"a49cc31b…","created_at":1700000000,
     "kind":1,"tags":[["content-warning","nudity"],
     ["L","content-warning"],["l","nudity","content-warning"]],
     "content":"beach photo dump","sig":"9c14ffa2…"}]
← ["OK", "7f3a21cd90…", true, ""]

-- a reader's client can query by indexed label --
→ ["REQ", "cw", {"kinds":[1], "#L":["content-warning"]}]
← ["EVENT", "cw", {"id":"7f3a21cd90…", …}]
← ["EOSE", "cw"]
-- the client renders: [ Sensitive content: nudity — Show anyway? ] --
Tech Note

The source example places the literal placeholder "reason" as the l label value in the content-warning namespace. It also omits the sig field that NIP-01 requires. Treat both as documentation shorthand, not as a valid event.

5 Version History

NIP-36 is a short and stable spec. Notable changes, newest first:

  • 20232023-11Reformatted the JSON example and removed the author list, as in all NIPs.
  • 20232023-06Jonathan Staab added the NIP-32 label option: l and L tags qualify the warning and make it queryable.
  • Origin2022-12Fernando López Guevara proposed the content-warning tag in PR #82.

Original Proposal - Credits

AuthorFernando López Guevara
First commit2022-12-01 — “NIP-36 - sensitive content / content-warning” - PR #82
Statusdraft optional
Source36.md on GitHub - full change history

6 See Also

  • NIP-01 — the event and tag model this NIP builds on; single-letter tag indexing.
  • NIP-32 — the l and L labeling system used to qualify and query warnings.
  • NIP-56 — reporting: how other users flag content, instead of the author.