Profanity filters for comments: how they work

Profanity filters work 2 ways: banned-word lists or ML classifiers. CommentCamp, $0 for site owners, builds in a moderation queue so a person decides. Lists like LDNOOBW's 403 English entries mask, hold or delete matching comments but block innocent words like Scunthorpe and miss creative spellings, while classifiers score meaning, so hold matches rather than delete them.

LDNOOBW language lists
28
English list entries
403
obscenity npm downloads
616,817 a week
Perspective API sunset
After Dec 31, 2026

What a profanity filter does

A profanity filter checks text against a set of rules, before or right after it goes live. When something matches, it does one of three things: masks the word (for example, with asterisks), holds the comment for a moderator or rejects it.

Where a word appears matters too. You might block slurs in usernames outright but only hold comments for a quick human check. Write those choices into your community guidelines so readers know the rules the filter enforces.

Word lists vs machine learning classifiers

Word lists are the classic approach: a list of banned terms plus pattern matching. They're fast, free and predictable, but they only catch what's on the list.

  • The LDNOOBW list ("List of Dirty, Naughty, Obscene, and Otherwise Bad Words"), first published by Shutterstock, has 28 language lists; the English one has 403 entries. It's licensed CC-BY-4.0 and has 3,477 GitHub stars, but its last commit was July 13, 2020.
  • On npm, bad-words had 306,391 weekly downloads for October 22-28, 2026. It's a plain word list plus regular expressions that replaces matches with asterisks by default and lets you add or remove words.

Machine learning classifiers score the text instead of matching strings. Python's profanity-check uses a linear SVM model "trained on 200k human-labeled samples" and no word list at all; alt-profanity-check, a maintained drop-in replacement, released version 1.9.1 on September 14, 2026.

Classifiers handle wording a list never anticipated. The trade-off: you have to pick a score threshold, and you can't fix a bad call by deleting one line from a list.

The Scunthorpe problem: false positives

Matching strings inside words blocks innocent text. Wikipedia calls this the Scunthorpe problem: "the unintentional blocking of online content by a spam filter, search engine or wordfilter because the text contains a string (or substring) of letters that appear to have an obscene or otherwise unacceptable meaning."

The name comes from an April 1996 incident in which AOL's filter stopped residents of Scunthorpe, England, from creating accounts, reported in The RISKS Digest (volume 18, issue 7, April 25, 1996). Residents of Penistone in South Yorkshire have had emails blocked for the same reason.

Find-and-replace filters make it worse. Swap "ass" for "butt" and "classic" becomes "clbuttic", "classroom" becomes "clbuttroom" and "assassinate" becomes "buttbuttinate".

WordPress has the same issue: its settings screen warns that its word boxes match inside words, so "press" will match "WordPress". The standard fix, in Wikipedia's words, is "creating a whitelist of known false positives."

Handling false positives: hold, don't delete

Substring rules and classifiers both misfire, so auto-deleting will cost you real comments. The safer pattern for comment moderation is to hold anything uncertain in a queue.

CommentCamp, the free comment system we're building for independent publishers, bloggers and WordPress sites, comes with automated spam filtering and a moderation queue, so comments can wait for a person's review instead of being deleted. It's $0 for site owners and in private early access: join the waitlist for an email invite as rollout expands.

WordPress gives you two boxes in its Discussion settings:

  • Comment Moderation holds a comment in the queue when its content, author name, URL, email, IP address or user agent contains a listed word. One word or IP per line.
  • Disallowed Comment Keys sends matches straight to the Trash. WordPress 5.5, released August 11, 2020, renamed the box from Comment Blocklist.

If you'd rather mask than block, the Content Censor plugin (600 active installs, updated October 5, 2026) replaces configured words when WordPress displays content and comments, and leaves the originals unchanged in the database.

Tip: Only put strings that never appear in normal conversation in Disallowed Comment Keys. Everything else goes in Comment Moderation, so a false positive costs you a click, not a comment.

How people get around filters

Anyone who has had to deal with trolls knows a determined commenter can beat a basic list in seconds. The common tricks:

  • Symbol swaps, like "$#it"
  • Repeated or stretched letters
  • Extra characters inserted between letters
  • Leetspeak and Unicode look-alike characters
  • Phonetic spellings, like "phok yu"

Some tools are built for exactly this:

  • obscenity (npm): 616,817 downloads in the same week, the most of the packages we checked. One pattern catches variants such as stretched letters and Unicode look-alikes, leetspeak decoding can be switched off and whitelisted phrases (its example is "pen is") prevent false positives.
  • better-profanity (Python): generates leetspeak spellings from its word list, though its last release, 0.7.0, came out on November 2, 2020.
  • Sightengine: a rule-based text moderation API designed to catch all of the tricks above, in 18 languages.

Context and reclaimed words

No word list knows intent. The same word can be an insult, a quote, a lyric or a joke between friends, and some groups reclaim words that are slurs elsewhere. A list treats every use the same.

Moderation APIs score meaning rather than spelling, but check what each one flags:

  • OpenAI's moderation endpoint (omni-moderation-latest) is free and scores 13 categories, such as harassment, hate, sexual and violence, from 0 to 1. None of the 13 is plain swearing.
  • Azure AI Content Safety rates hate, sexual, violence and self-harm on a 0 to 7 scale. Specific words go in custom blocklists of up to 10,000 terms.
  • Google Cloud Natural Language text moderation has 16 categories, including Profanity, Insult and Toxic.

That split can work in your favor: let casual swearing through and send harassment and hate to review.

Note: Google's free Perspective API, which has a PROFANITY attribute in 7 languages, is shutting down. Google says it stays active until December 31, 2026 and ends after 2026, so don't build anything new on it.

Profanity filter options compared

Prices are as of October 2026.

Approach Catches Misses Cost
WordPress Comment Moderation keys Listed strings in content, name, URL, email, IP or user agent Disguised spellings; matches inside longer words Free, built in
WordPress Disallowed Comment Keys The same strings The same, and false positives go to Trash Free, built in
Word list (LDNOOBW, bad-words) Words on the list Spellings not on the list; context Free, open source
Obfuscation-aware library (obscenity) Stretched letters, look-alikes, leetspeak Variants its patterns don't cover; context Free, open source
Moderation API (OpenAI, Google Cloud, Azure) Harassment, hate, insults, toxicity Plain swearing on OpenAI; specific words on Azure without a blocklist OpenAI free; Google 50,000 units/month free; Azure 5,000 records/month free, then $0.375 per 1,000
Sightengine Symbols, inserted characters, leetspeak, Unicode tricks, phonetic spellings Context that needs a human 2,000 operations/month free; Starter $29/month for 10,000
Human moderation queue Context, sarcasm, reclaimed words, false positives Speed, since comments wait for review Moderator time

Frequently asked questions

What is the Scunthorpe problem?

It's when a filter blocks innocent text because it contains a string of letters that spells an offensive word. It's named after an April 1996 incident in which AOL's filter stopped residents of Scunthorpe, England, from creating accounts. The usual fix is a list of known false positives that the filter allows.

What is the best npm package for filtering profanity?

By weekly downloads for October 22 to 28, 2026, obscenity leads with 616,817, followed by bad-words at 306,391 and @2toad/profanity at 148,661. obscenity catches stretched letters, Unicode look-alikes and leetspeak and supports whitelisted phrases, while bad-words is a simpler word list with regular expressions.

Does the OpenAI moderation API detect swear words?

Not as a category. OpenAI's free omni-moderation-latest model scores 13 categories, such as harassment, hate, sexual and violence, from 0 to 1, but plain swearing isn't one of them. For profanity specifically, Google Cloud Natural Language text moderation has a Profanity category, and Sightengine targets disguised swear words.

Is Google's Perspective API shutting down?

Yes. Google says the free Perspective API is ending after 2026 and stays active until December 31, 2026. It has a PROFANITY attribute in 7 languages. For new projects, consider Google Cloud Natural Language text moderation, which has a Profanity category and 50,000 free units a month, or OpenAI's free moderation endpoint.

How do I filter bad words in WordPress comments?

Open the Discussion settings screen. Words in Comment Moderation hold matching comments in the moderation queue, while words in Disallowed Comment Keys send them to the Trash. Both match inside words, so press matches WordPress. Keep Disallowed Comment Keys for strings that never appear in normal text.

Sources

  1. en.wikipedia.org/wiki/Scunthorpe_problem
  2. catless.ncl.ac.uk/Risks/18.07.html
  3. github.com/LDNOOBW/List-of-Dirty-Naughty-Obscene-and-Otherwis...
  4. github.com/jo3-l/obscenity
  5. github.com/web-mech/badwords
  6. pypi.org/project/alt-profanity-check
  7. wordpress.org/documentation/article/settings-discussion-screen
  8. wordpress.org/plugins/wp-content-filter
  9. developers.openai.com/api/docs/guides/moderation
  10. learn.microsoft.com/en-us/azure/ai-services/content-safety/ho...
  11. azure.microsoft.com/en-us/pricing/details/content-safety
  12. cloud.google.com/products/natural-language/pricing
  13. perspectiveapi.com
  14. sightengine.com/pricing

Prices and plan limits checked on October 30, 2026.