Implementing Content Moderation in Node.js with `bad-words`
Posted by Nuno Marques on 19 Mar 2025
Introduction
User-generated content can be unpredictable, and without proper moderation, it can lead to offensive or inappropriate language appearing in applications. In this article, we’ll explore how to implement a simple yet effective profanity filter in a Node.js application using the bad-words
package.
Estimated reading time: 5 min
Why Content Moderation Matters
- User Safety: Prevents harmful or offensive content from appearing in public spaces.
- Compliance: Many platforms require content moderation to meet legal and ethical standards.
- Brand Reputation: Helps maintain a professional and respectful community.
Setting Up bad-words
for Moderation
The bad-words
package is a simple, easy-to-use JavaScript library for filtering out offensive words. Here’s how you can integrate it into your Node.js application.
Installation
First, install the package via npm:
npm install bad-words
Implementing the Profanity Filter
Here’s a middleware function that filters user-submitted content from req.body
before processing it:
import { Filter } from 'bad-words';
const filter = new Filter();
// Optionally add or remove specific words
filter.addWords('custombadword');
filter.removeWords('hell');
// Recursive function to check all nested fields
function checkProfanity(obj, keyPath = '') {
if (typeof obj === 'string' && filter.isProfane(obj)) {
return keyPath || 'some field'; // Default to a generic message
}
if (Array.isArray(obj)) {
for (let i = 0; i < obj.length; i++) {
if (typeof obj[i] === 'string' && filter.isProfane(obj[i])) {
return `${keyPath}[${i}]`;
}
}
}
if (typeof obj === 'object' && obj !== null) {
for (const key in obj) {
const foundProfanity = checkProfanity(obj[key], keyPath ? `${keyPath}.${key}` : key);
if (foundProfanity) return foundProfanity;
}
}
return null; // No profanity found
}
export function moderateContent(req, res, next) {
console.log('🛠️ Profanity Check:', req.body);
// Check for profanity in all fields, including nested ones
const foundProfanity = checkProfanity(req.body);
if (foundProfanity) {
console.log(`⚠️ Profanity detected in: "${foundProfanity}"`);
return res.status(400).json({ error: `Inappropriate content in "${foundProfanity}"` });
}
console.log('✅ No profanity detected, proceeding...');
next(); // Proceed if no profanity is found
}
Example Console Outputs
Case 1: Profanity Found
Input:
{
"comment": "You're a bad ass!"
}
Console Output:
🛠️ Profanity Check: { comment: 'You're a bad ass!' }
⚠️ Profanity detected in: "comment"
Case 2: No Profanity Found
Input:
{
"comment": "This is a clean comment."
}
Console Output:
🛠️ Profanity Check: { comment: 'This is a clean comment.' }
✅ No profanity detected, proceeding...
Explanation of the Middleware
-
Create a
Filter
instance: This initializes the profanity filter. -
Customize the filter: You can add custom words (
filter.addWords
) and remove false positives (filter.removeWords
). -
Use a recursive function to check for profanity:
- If a field is a string, check for profanity.
- If a field is an array, scan each item.
- If a field is an object, recursively check nested properties.
-
Return an error if profanity is detected.
-
Call
next()
if no issues are found, allowing the request to proceed.
Using the Middleware in an Express App
To apply this middleware to your API routes, use it in an Express.js app like this:
import express from 'express';
import { moderateContent } from './moderation.js';
const app = express();
app.use(express.json());
app.post('/submit', moderateContent, (req, res) => {
res.json({ message: 'Content accepted!' });
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});
Key Takeaways
bad-words
is an easy-to-use library for filtering offensive content.- Custom words can be added or removed for better control.
- The middleware checks all fields, including nested ones.
- Integrating it into Express ensures all incoming requests are filtered.