Implementing Content Moderation in Node.js with `bad-words`

Blog

Posted by Nuno Marques on 19 Mar 2025

Implementing Content Moderation in Node.js with `bad-words`

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

  1. Create a Filter instance: This initializes the profanity filter.

  2. Customize the filter: You can add custom words (filter.addWords) and remove false positives (filter.removeWords).

  3. 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.
  4. Return an error if profanity is detected.

  5. 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.