Profanity
A multi-language profanity filter with full TypeScript support
Install / Use
/learn @2Toad/ProfanityREADME
Profanity 🧼
A multi-language profanity filter with full TypeScript support
Getting Started
Install the package
npm i @2toad/profanity
If you're using Node 11.x or older, you'll need to install Profanity 1.x
Usage
import { profanity, CensorType } from '@2toad/profanity';
// or
const { profanity, CensorType } = require('@2toad/profanity');
profanity.exists('I like big butts and I cannot lie');
// true
profanity.exists('I like big glutes and I cannot lie');
// false
profanity.censor('I like big butts (aka arses) and I cannot lie');
// I like big @#$%&! (aka @#$%&!) and I cannot lie
profanity.censor('I like big butts (aka arses) and I cannot lie', CensorType.FirstChar);
// I like big *utts (aka *rses) and I cannot lie
Options
Create an instance of the Profanity class to change the default options:
import { Profanity } from '@2toad/profanity';
const profanity = new Profanity({
languages: ['de'],
wholeWord: false,
grawlix: '*****',
grawlixChar: '$',
});
languages
By default, this is set to ['en'] (English). You can change the default to any supported language, including multiple languages:
const profanity = new Profanity({
languages: ['en', 'de'],
});
You can override this option by specifying the languages in exists or censor:
profanity.exists('Je suis un connard', ['fr']);
// true
profanity.censor('I like big butts and je suis un connard', CensorType.Word, ['en', 'de', 'fr']);
// I like big @#$%&! and je suis un @#$%&!
If no languages are specified in the method call, it will use the languages specified in the options.
wholeWord
By default, this is set to true so profanity only matches on whole words:
profanity.exists('Arsenic is poisonous but not profane');
// false
Setting this to false, results in partial word matches:
profanity.exists('Arsenic is poisonous but not profane');
// true (matched on arse)
Compound Words
Profanity detection works on parts of compound words, rather than treating hyphenated or underscore-separated words as indivisible.
When wholeWord is true, each portion of a compound word is analyzed for a match:
profanity.exists("Don't be an arsenic-monster");
// false
profanity.exists("Don't be an arse-monster");
// true (matched on arse)
Setting wholeWord to false, results in partial word matches on each portion of a compound word:
profanity.exists("Don't be an arsenic-monster");
// true (matched on arse)
unicodeWordBoundaries
When wholeWord is true, this controls whether word boundaries are Unicode-aware. By default this is set to false due to the performance impact.
- When
false(default), whole-word matching uses ASCII-style boundaries (similar to\b) plus underscore_as a separator. This is fastest and ideal for ASCII inputs. - When
true, whole-word matching uses Unicode-aware boundaries so words with diacritics (e.g.,vehículo,horário) and compound separators are handled correctly.
const profanity = new Profanity({ unicodeWordBoundaries: true });
profanity.exists('vehículo horario');
// false (does not match on "culo" inside "vehículo")
grawlix
By default this is set to @#$%&!:
profanity.censor('I like big butts and I cannot lie');
// I like big @#$%&! and I cannot lie
Setting this to ****, results in:
profanity.censor('I like big butts and I cannot lie');
// I like big **** and I cannot lie
grawlixChar
When specifying a CensorType other than CensorType.Word, this is the character used by the censor function.
By default this is set to *:
profanity.censor('I like big butts and I cannot lie', CensorType.AllVowels);
// I like big b*tts and I cannot lie
Setting this to $, results in:
profanity.censor('I like big butts and I cannot lie', CensorType.AllVowels);
// I like big b$tts and I cannot lie
Customize the word list
Add words:
profanity.addWords(['aardvark', 'zebra']);
Remove words:
profanity.removeWords(['butt', 'arse']);
Whitelist
The whitelist allows you to specify words that are always ignored by the profanity filter.
This can be useful if you want to enable partial word matching (
wholeWord = false), so combined words are caught (e.g., arselicker), while specific words you add to the whitelist are ignored (e.g., arsenic).
Add words to the whitelist:
profanity.whitelist.addWords(['arsenic', 'buttress']);
Remove words from the whitelist:
profanity.whitelist.removeWords(['arsenic', 'buttress']);
Benchmarking ⏱️
To see how Profanity performs, check out our benchmark results.
Contributing 🤝
So you want to contribute to the Profanity project? Fantastic! Please read the Contribute doc to get started.
Related Skills
openhue
353.3kControl Philips Hue lights and scenes via the OpenHue CLI.
sag
353.3kElevenLabs text-to-speech with mac-style say UX.
weather
353.3kGet current weather and forecasts via wttr.in or Open-Meteo
casdoor
13.3kAn open-source AI-first Identity and Access Management (IAM) /AI MCP & agent gateway and auth server with web UI supporting OpenClaw, MCP, OAuth, OIDC, SAML, CAS, LDAP, SCIM, WebAuthn, TOTP, MFA, Face ID, Google Workspace, Azure AD
