Short answer
Build a blocklist from your own moderation history, not a giant downloaded list. Match whole words by default, add the spelling variants you've actually seen, keep an allow list for innocent words that contain blocked ones, split entries into reject and hold, and test the whole list against real posts before every change goes live.
Key takeaways
- Your own queue is a better source than any generic list.
- Whole-word matching prevents most false positives.
- Context-dependent words belong on a hold list, not a reject list.
- An allow list fixes recurring false positives without weakening the block list.
- Re-test after every change; small edits have side effects.
Where should the words come from?
From the posts you've already had to remove: your hidden replies, deleted comments and rejected wall posts.
Go through the last few months of moderation. Write down every word or phrase that made you remove something. Group them: slurs and abuse, spam phrases, scam phrases, topic-specific risks. That list, perhaps 40 entries, will outperform a 2,000-word download because it reflects your actual audience.
Why does whole-word matching matter?
Because matching inside words is the single biggest cause of false positives, a problem old enough to have a name.
The "Scunthorpe problem" is named after an English town whose residents ran into filters in the 1990s because of the letters inside its name. Today it looks like a hashtag for #Classof2026 being hidden, or a comment about a "cocktail" going to trash. Match whole words by default. When you need a word's variants, add them explicitly or use a prefix like scam*, which catches "scammer" and "scams" but still requires the word to start there.
How do I cover variants without overblocking?
Let the matcher handle mechanical variants (case, accents, repeated letters, look-alike characters) and list real variants by hand.
| Variant | Handle with |
|---|---|
| Case and accents | Automatic in the filter tester and rule builder |
| Look-alikes: 4 for a, 0 for o, @ for a | "Look-alike characters" option |
| Stretched: freeee | "Stretched letters" option |
| Spaced: f r e e, f.r.e.e | "Spaced-out letters" option |
| Slang and new spellings | Add them as their own lines when you see them |
| Plurals and endings | A prefix entry like word* |
Many platforms, including X's muted words and WordPress's lists, don't do the clever matching. For those, use the filter tester to find the variants in real text, then list them explicitly.
What goes on the allow list?
Innocent words that keep getting caught: place names, names of people and products, and common words containing a blocked one.
The allow list wins over the block list in the same spot of text. If "class" is blocked and "classic" is allowed, the word "classic" passes and "class" alone is still caught. Add to the allow list every time you correct a false positive, and it will grow into a record of your community's vocabulary.
Reject or hold?
Reject only what is unacceptable in every context, and hold everything that depends on context.
"Kill" is in "you killed it". "Crypto" is in news. Your competitor's name is in fair comparisons. These go on a hold list so a person decides. Slurs, scam phrases and spam phrases go on the reject list. The rule builder keeps the two separate and exports each to the right place.
How do I keep the list healthy?
Review it monthly, test every change against a saved sample of real posts, and remove entries nobody can justify.
Keep a text file of 50 to 100 real posts, good and bad, as a test set. After every list change, paste the list and the test set into the filter tester. If a good post starts getting flagged, you'll know which change caused it.
- Every entry traces back to a real removal
- Whole-word matching unless there's a reason
- Context-dependent words on hold, not reject
- Allow list updated after each false positive
- Test set re-run after each change
Common questions
Should I download a big profanity list from the internet?
It can be a useful reference, but don't paste it in wholesale. Big lists are full of words that are harmless in your context and miss the spam phrases you actually get. Pick from them, and test what you pick.
How long should my list be?
As short as it can be while still catching what you see. Many accounts work well with 30 to 100 entries. A long list is hard to review, and nobody can explain why entry 412 is there.
How do I handle other languages?
Add entries in each language your community uses, ideally chosen by a native speaker on your team. Accent-insensitive matching helps with spelling, but slang and insults don't translate word for word.