What is Glin-Profanity?
Glin-Profanity is an open-source content moderation library for JavaScript/TypeScript and Python. Unlike basic word-list filters, it handles the evasion techniques users actually try, leetspeak substitutions (f4ck, 5h1t), Unicode homoglyphs (Cyrillic characters that look like Latin), and character separation tricks.
Key capabilities:
- Leetspeak & Unicode normalization (catches
@$$,fսck,sh!t) - 23 language dictionaries built-in
- Optional ML toxicity detection via TensorFlow.js
- 21M+ operations/sec with LRU caching
- Works in Node.js, browsers, and Python
Try It Live
Test the filter directly in your browser — no installation required.
Quick Reference
| Feature | JavaScript | Python |
|---|---|---|
| Install | npm install glin-profanity |
pip install glin-profanity |
| Languages | 23 supported | 23 supported |
| Performance | 21M ops/sec | Native C extension |
| ML Support | TensorFlow.js | TensorFlow |
| Bundle Size | ~45KB (tree-shakeable) | N/A |
Installation
# JavaScript/TypeScript
npm install glin-profanity
# Python
pip install glin-profanity
# With ML toxicity support (optional)
npm install glin-profanity @tensorflow/tfjs
Code Templates
Template 1: Basic Profanity Check
JavaScript:
import { checkProfanity } from 'glin-profanity';
const result = checkProfanity("user input here", {
languages: ['english']
});
if (result.containsProfanity) {
console.log('Blocked words:', result.profaneWords);
}
Python:
from glin_profanity import Filter
filter = Filter({"languages": ["english"]})
result = filter.check_profanity("user input here")
if result.contains_profanity:
print(f"Blocked words: {result.profane_words}")
Template 2: Leetspeak & Unicode Evasion Detection
Catches: f4ck, 5h1t, @$$, fսck (Cyrillic), s.h" "i.t
import { Filter } from 'glin-profanity';
const filter = new Filter({
detectLeetspeak: true,
leetspeakLevel: 'aggressive', // 'basic' | 'moderate' | 'aggressive'
normalizeUnicode: true
});
filter.isProfane('f4ck'); // true
filter.isProfane('5h1t'); // true
filter.isProfane('@$$'); // true
filter.isProfane('fսck'); // true (Cyrillic 'ս')
Leetspeak Levels:
-
basic: Common substitutions (4→a, 3→e, 1→i, 0→o) -
moderate: + Extended symbols (@→a, $→s, !→i) -
aggressive: + Separated characters, mixed patterns
Template 3: Multi-Language Detection
const filter = new Filter({
languages: ['english', 'spanish', 'french', 'german']
});
// Or check all 23 languages:
const filterAll = new Filter({ allLanguages: true });
Supported Languages:
arabic chinese czech danish dutch english esperanto finnish french german hindi hungarian italian japanese korean norwegian persian polish portuguese russian spanish swedish thai turkish
Template 4: Auto-Replace Profanity
const filter = new Filter({
replaceWith: '***',
detectLeetspeak: true
});
const result = filter.checkProfanity("What the f4ck");
console.log(result.processedText); // "What the ***"
Custom replacement patterns:
// Asterisks matching word length
{ replaceWith: '*' } // "f**k" → "****"
// Fixed replacement
{ replaceWith: '[FILTERED]' } // "f**k" → "[FILTERED]"
// Character-based
{ replaceWith: '#' } // "f**k" → "####"
Template 5: Severity-Based Moderation
import { Filter, SeverityLevel } from 'glin-profanity';
const filter = new Filter({ detectLeetspeak: true });
const result = filter.checkProfanity(userInput);
switch (result.maxSeverity) {
case SeverityLevel.HIGH:
// Block message, notify moderators
blockMessage(result);
notifyModerators(result);
break;
case SeverityLevel.MEDIUM:
// Auto-replace, flag for review
sendFiltered(result.processedText);
flagForReview(result);
break;
case SeverityLevel.LOW:
// Just replace and continue
sendFiltered(result.processedText);
break;
default:
// Clean message
send(userInput);
}
Template 6: React Hook for Real-Time Input
import { useProfanityChecker } from 'glin-profanity';
function ChatInput() {
const { result, checkText, isChecking } = useProfanityChecker({
detectLeetspeak: true,
languages: ['english']
});
return (
<div>
<textarea
onChange={(e) => checkText(e.target.value)}
placeholder="Type a message..."
/>
{result?.containsProfanity && (
<span className="text-red-500">
Please remove inappropriate language.
</span>
)}
</div>
);
}
Template 7: ML Toxicity Detection (v3+)
Catches toxic content without explicit profanity:
- "You're the worst player ever"
- "Nobody wants you here"
- "Just quit already"
import { loadToxicityModel, checkToxicity } from 'glin-profanity/ml';
// Load once on app startup
await loadToxicityModel({ threshold: 0.9 });
// Check any text
const result = await checkToxicity("You're terrible at this");
console.log(result);
// {
// toxic: true,
// categories: {
// toxicity: 0.92,
// insult: 0.87,
// threat: 0.12,
// identity_attack: 0.08,
// obscene: 0.45
// }
// }
Note: ML model runs 100% locally. No API calls, no data leaves your server.
Template 8: Full Chat Moderation Pipeline
import { Filter, SeverityLevel } from 'glin-profanity';
import { loadToxicityModel, checkToxicity } from 'glin-profanity/ml';
// Setup
const filter = new Filter({
languages: ['english', 'spanish'],
detectLeetspeak: true,
leetspeakLevel: 'moderate',
normalizeUnicode: true,
replaceWith: '***'
});
await loadToxicityModel({ threshold: 0.85 });
// Moderation function
async function moderateMessage(text) {
// Fast rule-based check
const profanity = filter.checkProfanity(text);
// ML toxicity check
const toxicity = await checkToxicity(text);
// Decision logic
if (profanity.maxSeverity === SeverityLevel.HIGH) {
return { action: 'block', reason: 'severe_profanity' };
}
if (toxicity.toxic) {
return {
action: 'flag',
text: profanity.processedText,
reason: 'toxic_content'
};
}
if (profanity.containsProfanity) {
return { action: 'filter', text: profanity.processedText };
}
return { action: 'allow', text };
}
// Usage
const result = await moderateMessage("User message here");
Template 9: Express.js Middleware
import { Filter } from 'glin-profanity';
const filter = new Filter({
detectLeetspeak: true,
languages: ['english']
});
function profanityMiddleware(req, res, next) {
const fieldsToCheck = ['body.message', 'body.comment', 'body.bio'];
for (const field of fieldsToCheck) {
const value = getNestedValue(req, field);
if (value && filter.isProfane(value)) {
return res.status(400).json({
error: 'Content contains inappropriate language'
});
}
}
next();
}
app.post('/api/comments', profanityMiddleware, commentHandler);
Template 10: Custom Whitelist/Blacklist
const filter = new Filter({
languages: ['english'],
ignoreWords: ['hell', 'damn'], // Allow these words
customWords: ['badword', 'toxic'] // Add custom blocked words
});
Architecture
Performance Benchmarks
| Operation | Speed |
|---|---|
| Simple check | 21M ops/sec |
| With leetspeak (moderate) | 8.5M ops/sec |
| Multi-language (3 langs) | 18M ops/sec |
| Unicode normalization | 15M ops/sec |
Results are cached using LRU strategy.
API Quick Reference
Filter Options
interface FilterOptions {
languages?: string[]; // ['english', 'spanish', ...]
allLanguages?: boolean; // Check all 23 languages
detectLeetspeak?: boolean; // Enable leetspeak detection
leetspeakLevel?: 'basic' | 'moderate' | 'aggressive';
normalizeUnicode?: boolean; // Handle Unicode homoglyphs
replaceWith?: string; // Replacement character/string
ignoreWords?: string[]; // Whitelist
customWords?: string[]; // Additional blocked words
}
Result Object
interface CheckResult {
containsProfanity: boolean;
profaneWords: string[];
processedText: string; // With replacements applied
maxSeverity: SeverityLevel;
matches: MatchDetail[];
}
Resources
Tags: #javascript #typescript #python #react #opensource #webdev #contentmoderation #npm #profanityfilter


Top comments (0)