clone

every nostr nip as a chapter of an illustrated, early-2000s printed game manual

main
nip.guide / site / nips / 56.html
56.html 20.9K
1<!DOCTYPE html>2<html lang="en">3<head>4<meta charset="utf-8">5<meta name="viewport" content="width=device-width, initial-scale=1">6<title>NIP-56 - Reporting — Nostr Instruction Manual</title>7<meta name="description" content="NIP-56: reporting objectionable content. Kind 1984 report events, report types, target tags, and moderation guidance for clients and relays.">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 56 - Moderation</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="56">56</div>48 <div class="titles">49 <div class="kicker">Nostr Implementation Possibility - Hex № 56</div>50 <h1>Reporting</h1>51 <p class="sub">A signed flag on the wire: kind 1984 events let users report objectionable profiles, notes, and files — and let everyone else decide what to do about it.</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 <strong>report</strong> is a <code>kind 1984</code> event. It signals to users and relays that some referenced content is objectionable. The report names a target: a user, a note, or a file blob. It also names a reason, called the <strong>report type</strong>.</p>60 <p>The definition of objectionable is subjective. This NIP does not define it. Every agent on the network — users, apps, relays — may consume reports and act on them as it sees fit. A report is advice, not a command. No relay must delete anything. No client must hide anything.</p>61 <p>Reports are ordinary signed events. Anyone can publish one. Anyone can query them with a normal <a href="01.html">NIP-01</a> filter, for example <code>{"kinds":[1984],"#p":[&lt;pubkey&gt;]}</code>. This makes moderation data open and portable instead of locked inside one platform.</p>6263 <div class="box hint">64 <span class="tag">Hint!</span>65 <p>Why 1984? The kind number is a nod to Orwell. It sits in the regular event range, so relays store every report and clients can tally them over time.</p>66 </div>6768 <figure class="diagram">69 <div class="frame">70 <svg viewBox="0 0 560 190" role="img" aria-label="A reporter publishes a kind 1984 report to a relay; other clients and the relay admin read it and each decide their own action">71 <rect class="d-actor" x="10" y="70" width="110" height="50" rx="8"/>72 <text class="d-actor-label" x="65" y="94" text-anchor="middle">Reporter</text>73 <text class="d-note" x="65" y="111" text-anchor="middle">client</text>74 <rect class="d-actor" x="225" y="70" width="110" height="50" rx="8"/>75 <text class="d-actor-label" x="280" y="99" text-anchor="middle">Relay</text>76 <rect class="d-actor" x="440" y="20" width="110" height="44" rx="8"/>77 <text class="d-actor-label" x="495" y="41" text-anchor="middle">Friends'</text>78 <text class="d-note" x="495" y="56" text-anchor="middle">clients: blur / hide</text>79 <rect class="d-actor" x="440" y="126" width="110" height="44" rx="8"/>80 <text class="d-actor-label" x="495" y="147" text-anchor="middle">Admin</text>81 <text class="d-note" x="495" y="162" text-anchor="middle">manual takedown</text>82 <path class="d-msg d-flow" d="M122,95 L222,95"/>83 <text class="d-label" x="172" y="88" text-anchor="middle">kind 1984</text>84 <path class="d-msg blue d-flow" d="M337,84 C380,72 390,54 438,46"/>85 <path class="d-msg blue d-flow" d="M337,106 C380,118 390,136 438,144"/>86 <text class="d-label" x="392" y="40" text-anchor="middle">REQ #p / #e</text>87 <circle r="4" fill="#f26a00">88 <animateMotion dur="2.6s" repeatCount="indefinite" path="M122,95 L222,95"/>89 </circle>90 <circle r="4" fill="#2e5f9e">91 <animateMotion dur="2.6s" begin="1.3s" repeatCount="indefinite" path="M337,84 C380,72 390,54 438,46"/>92 </circle>93 </svg>94 </div>95 <figcaption>Fig. 56-1 — <b>Report flow.</b> One report, many independent readers. Each reader chooses its own response.</figcaption>96 </figure>9798 <h2 class="bar" id="spec"><span class="num">2</span> The Report Event</h2>99 <p>A report is a regular event with <code>kind</code> set to <code>1984</code>. The <code>content</code> field MAY carry additional information from the reporting entity, in free text. An empty <code>content</code> is valid. The tags carry the machine-readable part of the report.</p>100101 <div class="crt">102 <div class="titlebar">Wire format - kind 1984 report</div>103<pre>{104 <span class="k">"kind"</span>: 1984,105 <span class="k">"tags"</span>: [106 [<span class="s">"p"</span>, <span class="c">&lt;reported user's pubkey&gt;</span>, <span class="c">&lt;report type&gt;</span>],107 [<span class="s">"e"</span>, <span class="c">&lt;reported note id, if reporting a note&gt;</span>, <span class="c">&lt;report type&gt;</span>],108 [<span class="s">"x"</span>, <span class="c">&lt;reported blob hash, if reporting a file&gt;</span>, <span class="c">&lt;report type&gt;</span>]109 ],110 <span class="k">"content"</span>: <span class="c">&lt;optional free-text explanation&gt;</span>111 <span class="c">// other NIP-01 fields: id, pubkey, created_at, sig</span>112}</pre>113 </div>114115 <h2 class="bar" id="tags"><span class="num">3</span> Tags and Report Types</h2>116 <p>The tags identify the report target. The rules are:</p>117 <ul>118 <li>The report MUST include a <code>p</code> tag with the pubkey of the user you report.</li>119 <li>If you report a note, the report MUST also include an <code>e</code> tag with the note id.</li>120 <li>The tag that points at the reported target MUST carry a <strong>report type</strong> string as its 3rd entry. This applies to the <code>e</code>, <code>p</code>, or <code>x</code> tag being reported.</li>121 </ul>122123 <div class="tscroll"><table class="ref">124 <caption>Target tags</caption>125 <tr><th>Tag</th><th>Value</th><th>Rule</th></tr>126 <tr><td class="btn">p</td><td>pubkey of the reported user</td><td>Required in every report. Carries the report type when the profile itself is the target.</td></tr>127 <tr><td class="btn">e</td><td>id of the reported note</td><td>Required when a note is the target. Carries the report type in that case.</td></tr>128 <tr><td class="btn">x</td><td>info hash of the reported file blob</td><td>SHOULD hold the blob hash. When present, the client MUST also include an <code>e</code> tag with the id of the event that contains the blob.</td></tr>129 <tr><td class="btn">server</td><td>media server URL</td><td>Optional companion to <code>x</code>. Points to a media server that may host the reported blob.</td></tr>130 <tr><td class="btn">l</td><td>label value</td><td>MAY be used, as defined in <a href="32.html">NIP-32</a>, for further qualification and querying.</td></tr>131 <tr><td class="btn">L</td><td>label namespace</td><td>MAY be used, as defined in <a href="32.html">NIP-32</a>, together with <code>l</code>.</td></tr>132 </table></div>133134 <p>The report type is one of seven fixed strings:</p>135 <div class="tscroll"><table class="ref">136 <caption>Report types</caption>137 <tr><th>Type</th><th>Meaning</th></tr>138 <tr><td class="btn">nudity</td><td>Depictions of nudity, porn, and similar content.</td></tr>139 <tr><td class="btn">malware</td><td>Virus, trojan horse, worm, robot, spyware, adware, back door, ransomware, rootkit, kidnapper, and similar threats.</td></tr>140 <tr><td class="btn">profanity</td><td>Profanity, hateful speech, and similar content.</td></tr>141 <tr><td class="btn">illegal</td><td>Something that may be illegal in some jurisdiction.</td></tr>142 <tr><td class="btn">spam</td><td>Spam.</td></tr>143 <tr><td class="btn">impersonation</td><td>Someone pretends to be someone else.</td></tr>144 <tr><td class="btn">other</td><td>Reports that do not fit the categories above.</td></tr>145 </table></div>146147 <p>Some report types only make sense for profile reports. <code>impersonation</code> is the clear example: a note cannot impersonate, a profile can. Put such types on the <code>p</code> tag.</p>148149 <figure class="diagram">150 <div class="frame">151 <svg viewBox="0 0 560 170" role="img" aria-label="Three report shapes: a profile report uses a typed p tag, a note report adds a typed e tag, a blob report adds typed x and e tags plus an optional server tag">152 <rect class="d-actor" x="10" y="20" width="150" height="40" rx="8"/>153 <text class="d-actor-label" x="85" y="45" text-anchor="middle">Profile report</text>154 <rect class="d-actor" x="10" y="70" width="150" height="40" rx="8"/>155 <text class="d-actor-label" x="85" y="95" text-anchor="middle">Note report</text>156 <rect class="d-actor" x="10" y="120" width="150" height="40" rx="8"/>157 <text class="d-actor-label" x="85" y="145" text-anchor="middle">Blob report</text>158 <path class="d-msg" d="M162,40 L225,40"/>159 <path class="d-msg" d="M162,90 L225,90"/>160 <path class="d-msg" d="M162,140 L225,140"/>161 <text class="d-label" x="232" y="45">["p", pubkey, type]</text>162 <text class="d-label" x="232" y="87">["e", note id, type]</text>163 <text class="d-note" x="232" y="102">+ ["p", pubkey]</text>164 <text class="d-label" x="232" y="132">["x", blob hash, type]</text>165 <text class="d-note" x="232" y="147">+ ["e", carrier event id, type]</text>166 <text class="d-note" x="232" y="161">+ ["server", media URL] (optional)</text>167 </svg>168 </div>169 <figcaption>Fig. 56-2 — <b>Three report shapes.</b> The typed tag names the target. Every shape also carries a <code>p</code> tag for the user.</figcaption>170 </figure>171172 <div class="box tech">173 <span class="tag">Tech Note</span>174 <p>The spec says the report type "MUST be included as the 3rd entry to the <code>e</code>, <code>p</code> or <code>x</code> tag being reported". Yet its own note-report example carries a bare <code>["p", &lt;pubkey&gt;]</code> with no type, and the blob-report example types both <code>x</code> and <code>e</code>. Read the MUST as applying only to the tag that points at the reported target; treat types on companion tags as optional. Parsers should tolerate both forms. The <code>x</code> paragraph is also loose: it says the hash "SHOULD" be present but never defines the hash function; in practice it is the sha256 hash used by media NIPs.</p>175 </div>176177 <h2 class="bar" id="client"><span class="num">4</span> Client Behavior</h2>178 <p>Clients can use reports from friends to make moderation decisions, if they choose to. Reports become a web-of-trust signal: a report from a followed user carries more weight than a report from a stranger.</p>179 <p>Example policy: when 3 or more of your friends report a profile for <code>nudity</code>, the client can offer an option to blur photos from that account automatically. The threshold, the action, and the opt-in are all client decisions. This NIP mandates none of them.</p>180 <div class="box hint">181 <span class="tag">Hint!</span>182 <p>Combine reports with <a href="51.html">NIP-51</a> mute lists. Reports are public signals from others; mute lists are your own private or public block decisions. Together they cover most client-side moderation needs.</p>183 </div>184185 <h2 class="bar" id="relay"><span class="num">5</span> Relay Behavior</h2>186 <p>Relays should not perform automatic moderation from reports. Reports are cheap to publish, so bad actors can game any automatic rule. A wave of fake <code>spam</code> reports must not silence a real user.</p>187 <p>Human review works better. Relay admins can use reports from trusted moderators to take down illegal or explicit content when the relay does not allow such things. The trust decision stays with the admin, not with the raw report count.</p>188 <div class="box warn">189 <span class="tag">Warning!</span>190 <p>Never delete or block on report volume alone. Anyone can create thousands of keypairs and file thousands of reports. Weigh the reporter, not just the report.</p>191 </div>192193 <h2 class="bar" id="examples"><span class="num">6</span> Worked Examples</h2>194 <p>Four reports, one per target shape. Only <code>kind</code>, <code>tags</code>, and <code>content</code> are shown; the other <a href="01.html">NIP-01</a> fields (<code>id</code>, <code>pubkey</code>, <code>created_at</code>, <code>sig</code>) are present in real events.</p>195196 <div class="crt">197 <div class="titlebar">Report 1 - profile, with NIP-32 labels</div>198<pre>{199 <span class="k">"kind"</span>: 1984,200 <span class="k">"tags"</span>: [201 [<span class="s">"p"</span>, <span class="s">"&lt;pubkey&gt;"</span>, <span class="s">"nudity"</span>],202 [<span class="s">"L"</span>, <span class="s">"social.nos.ontology"</span>],203 [<span class="s">"l"</span>, <span class="s">"NS-nud"</span>, <span class="s">"social.nos.ontology"</span>]204 ],205 <span class="k">"content"</span>: <span class="s">""</span>206}</pre>207 </div>208209 <div class="crt">210 <div class="titlebar">Report 2 - a note</div>211<pre>{212 <span class="k">"kind"</span>: 1984,213 <span class="k">"tags"</span>: [214 [<span class="s">"e"</span>, <span class="s">"&lt;eventId&gt;"</span>, <span class="s">"illegal"</span>],215 [<span class="s">"p"</span>, <span class="s">"&lt;pubkey&gt;"</span>]216 ],217 <span class="k">"content"</span>: <span class="s">"He's insulting the king!"</span>218}</pre>219 </div>220221 <div class="crt">222 <div class="titlebar">Report 3 - impersonation (profile only)</div>223<pre>{224 <span class="k">"kind"</span>: 1984,225 <span class="k">"tags"</span>: [226 [<span class="s">"p"</span>, <span class="s">"&lt;impersonator pubkey&gt;"</span>, <span class="s">"impersonation"</span>]227 ],228 <span class="k">"content"</span>: <span class="s">"Profile is impersonating nostr:&lt;victim bech32 pubkey&gt;"</span>229}</pre>230 </div>231232 <div class="crt">233 <div class="titlebar">Report 4 - a file blob</div>234<pre>{235 <span class="k">"kind"</span>: 1984,236 <span class="k">"tags"</span>: [237 [<span class="s">"x"</span>, <span class="s">"&lt;blob hash&gt;"</span>, <span class="s">"malware"</span>],238 [<span class="s">"e"</span>, <span class="s">"&lt;event id which contains the blob on x tag&gt;"</span>, <span class="s">"malware"</span>],239 [<span class="s">"server"</span>, <span class="s">"https://you-may-find-the-blob-here.com/path-to-url.ext"</span>]240 ],241 <span class="k">"content"</span>: <span class="s">"This file contains malware software in it."</span>242}</pre>243 </div>244245 <p>To read reports about a user or a note, query the standard indexed-tag filters:</p>246 <div class="crt">247 <div class="titlebar">Session transcript - fetching reports</div>248<pre><span class="send">→ ["REQ", "mod", {"kinds":[1984], "#p":["&lt;pubkey&gt;"], "limit":100}]</span>249<span class="recv">← ["EVENT", "mod", {"kind":1984, "tags":[["p","&lt;pubkey&gt;","spam"]], …}]</span>250<span class="recv">← ["EVENT", "mod", {"kind":1984, "tags":[["p","&lt;pubkey&gt;","nudity"]], …}]</span>251<span class="recv">← ["EOSE", "mod"]</span>252<span class="send">→ ["CLOSE", "mod"]</span></pre>253 </div>254255 <h2 class="bar" id="history"><span class="num">7</span> Version History</h2>256 <p>NIP-56 has stayed small since 2023. The main additions are labels and blob reports. Notable changes, newest first:</p>257 <ul class="patchnotes">258 <li><span class="ver">2025</span><span class="when">2025-01</span>Added the <code>x</code> tag for reporting file blobs, with the companion <code>e</code> and <code>server</code> tags.</li>259 <li><span class="ver">2024</span><span class="when">2024-04</span>Added the <code>malware</code> report type and rewrote the intro: reports address users and relays, not only moderators.</li>260 <li><span class="ver">2023</span><span class="when">2023-07</span>Example content switched from deprecated <a href="08.html">NIP-08</a> indexed mentions to <a href="27.html">NIP-27</a> bech32 mentions.</li>261 <li><span class="ver">2023</span><span class="when">2023-06</span>Added optional <code>l</code>/<code>L</code> labeling per <a href="32.html">NIP-32</a>.</li>262 <li class="minor"><span class="ver">2023+</span><span class="when">2023-2026</span>Typo fixes, JSON reformatting, author-line removal, and code-fence cleanup.</li>263 <li><span class="ver">Origin</span><span class="when">2023-02</span>William Casarin published the first version: kind 1984 with typed <code>p</code>/<code>e</code> tags and six report types.</li>264 </ul>265266 <div class="credits">267 <h3 class="cardhead">Original Proposal - Credits</h3>268 <table>269 <tr><td>Author</td><td>William Casarin</td></tr>270 <tr><td>First commit</td><td>2023-02-07 — “NIP-56: Reporting” (<a href="https://github.com/nostr-protocol/nips/pull/205">PR #205</a>)</td></tr>271 <tr><td>Status</td><td>active - optional — clients and relays may ignore reports entirely</td></tr>272 <tr><td>Source</td><td><a href="https://github.com/nostr-protocol/nips/blob/master/56.md">56.md on GitHub</a> - <a href="https://github.com/nostr-protocol/nips/commits/master/56.md">full change history</a></td></tr>273 </table>274 </div>275276 <h2 class="bar"><span class="num">8</span> See Also</h2>277 <ul>278 <li><a href="01.html">NIP-01</a> — the base event format and the <code>e</code>/<code>p</code> tags that reports build on.</li>279 <li><a href="32.html">NIP-32</a> — the <code>l</code>/<code>L</code> labeling system for finer report qualification.</li>280 <li><a href="27.html">NIP-27</a> — bech32 mentions like the <code>nostr:</code> reference in the impersonation example.</li>281 <li><a href="51.html">NIP-51</a> — mute lists; the personal counterpart to public reports.</li>282 <li><a href="17.html">NIP-17</a> — private messages, for sensitive reports you do not want public.</li>283 </ul>284 </div>285286 <aside>287 <div class="cartridge">288 <div class="inner">289 <h3 class="cardhead">Spec Card</h3>290 <div class="lights"><span class="led on"></span><span class="led on"></span><span class="led on"></span></div>291 <dl>292 <dt>Status</dt><dd><span class="chip">optional</span></dd>293 <dt>Defines</dt><dd>report events - 7 report types - x/server tags</dd>294 <dt>Kind(s)</dt><dd>1984 (regular)</dd>295 <dt>Requires</dt><dd><a href="01.html">NIP-01</a>; optional <a href="32.html">NIP-32</a> labels</dd>296 <dt>Targets</dt><dd>profiles (p) - notes (e) - blobs (x)</dd>297 <dt>First commit</dt><dd>2023-02-07</dd>298 <dt>Last updated</dt><dd>2026-06-13</dd>299 </dl>300 </div>301 </div>302 </aside>303 </main>304305 <nav class="navbtns">306 <a href="55.html">◀ NIP-55: Android Signer Application</a>307 <a href="57.html">NIP-57: Lightning Zaps ▶</a>308 </nav>309310 <footer class="pagefoot">311 <a href="../index.html">Nostr Protocol Manual</a>312 <span class="pageno">NIP 56 / F4</span>313 </footer>314</div>315316<script src="../assets/webmcp.js" defer></script>317</body>318</html>