filenamify vs sanitize-filename vs slugify
Safe String Transformation for Files and URLs
filenamifysanitize-filenameslugifySimilar Packages:

Safe String Transformation for Files and URLs

filenamify, sanitize-filename, and slugify are utilities designed to clean and normalize strings, but they serve distinct purposes in web architecture. filenamify focuses on creating valid filesystem filenames while preserving readability and case. sanitize-filename prioritizes security by stripping dangerous characters and preventing path traversal attacks. slugify transforms text into URL-friendly slugs, enforcing lowercase and replacing spaces with separators for web addresses.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
filenamify051811.7 kB27 months agoMIT
sanitize-filename036917.5 kB243 months agoWTFPL OR ISC
slugify01,73316.2 kB392 months agoMIT

Safe String Transformation: filenamify vs sanitize-filename vs slugify

When handling user input for files or URLs, raw strings are rarely safe. Special characters, reserved words, and path separators can break filesystems, expose security vulnerabilities, or ruin URL structures. filenamify, sanitize-filename, and slugify solve these problems, but they approach them from different angles. Let's compare how they handle real-world data.

πŸ› οΈ Core Behavior: Replacement vs Removal vs Transformation

The fundamental difference lies in how each package treats invalid characters. filenamify replaces them to keep the name intact. sanitize-filename removes them to ensure safety. slugify transforms the entire string for web usage.

filenamify replaces invalid characters with a safe substitute (default _). It preserves case and most punctuation that is safe.

import filenamify from 'filenamify';

// Input: "Project: Alpha (Final).docx"
const safe = filenamify('Project: Alpha (Final).docx');
// Output: "Project_ Alpha (Final).docx"

sanitize-filename removes invalid characters entirely. It does not replace them, which can shorten the string unexpectedly.

import sanitize from 'sanitize-filename';

// Input: "Project: Alpha (Final).docx"
const safe = sanitize('Project: Alpha (Final).docx');
// Output: "Project Alpha (Final).docx"

slugify converts the string to lowercase and replaces spaces/symbols with a separator (default -). It removes most punctuation.

import slugify from 'slugify';

// Input: "Project: Alpha (Final).docx"
const safe = slugify('Project: Alpha (Final).docx');
// Output: "project-alpha-final-docx"

πŸ”’ Security and Path Traversal

Security is critical when accepting filenames from users. Attackers might try to include path separators to write files outside the intended directory.

filenamify focuses on filename validity, not path security. It does not automatically strip path separators like / or \.

import filenamify from 'filenamify';

// Input: "../../etc/passwd"
const safe = filenamify('../../etc/passwd');
// Output: ".._.._etc_passwd" (Still contains dots, may need extra logic)

sanitize-filename is built specifically to prevent path traversal. It strips path separators and reserved names aggressively.

import sanitize from 'sanitize-filename';

// Input: "../../etc/passwd"
const safe = sanitize('../../etc/passwd');
// Output: ".._.._etc_passwd" (Strips path separators effectively)

slugify removes most special characters, including slashes, but it is not designed for security auditing.

import slugify from 'slugify';

// Input: "../../etc/passwd"
const safe = slugify('../../etc/passwd');
// Output: "etc-passwd" (Removes dots and slashes, but not security-hardened)

⚠️ Warning: Never rely solely on these packages for security. Always validate paths on the server and use safe join methods.

πŸ–₯️ Platform Compatibility and Reserved Names

Different operating systems have different rules. Windows reserves names like CON, PRN, and AUX. filenamify and sanitize-filename handle these; slugify does not.

filenamify detects Windows reserved names and adds a suffix to make them valid.

import filenamify from 'filenamify';

// Input: "CON.txt"
const safe = filenamify('CON.txt');
// Output: "CON!.txt" (Modifies reserved name)

sanitize-filename also handles reserved names by appending an underscore or similar modification.

import sanitize from 'sanitize-filename';

// Input: "CON.txt"
const safe = sanitize('CON.txt');
// Output: "CON_.txt" (Modifies reserved name)

slugify ignores OS reserved names because it targets URLs, not filesystems.

import slugify from 'slugify';

// Input: "CON.txt"
const safe = slugify('CON.txt');
// Output: "con-txt" (Lowercases, does not handle Windows reservation)

πŸŽ›οΈ Configuration and Control

Developers often need to tweak how sanitization happens. filenamify and slugify offer options; sanitize-filename is opinionated.

filenamify allows you to set the replacement character and max length.

import filenamify from 'filenamify';

filenamify('file:name', { replacement: '-', maxLength: 10 });
// Output: "file-name"

sanitize-filename has no configuration options. It runs with fixed security rules.

import sanitize from 'sanitize-filename';

// No options available
sanitize('file:name');
// Output: "filename"

slugify offers extensive options for locale, lowercase toggling, and custom removal patterns.

import slugify from 'slugify';

slugify('file:name', { lower: false, replacement: '_' });
// Output: "file_name" (Preserves case)

🌐 Real-World Scenarios

Scenario 1: User Download Button

You need to save a report generated by the user with their custom title.

  • βœ… Best choice: filenamify
  • Why? It keeps the name readable and safe for the user's OS without forcing lowercase.
const filename = filenamify(`${userTitle}.pdf`);
downloadUrl(blob, filename);

Scenario 2: Server-Side File Upload

You accept files from an API endpoint and store them on disk.

  • βœ… Best choice: sanitize-filename
  • Why? It prioritizes security against path traversal and illegal characters.
const safeName = sanitize(req.file.originalname);
fs.writeFileSync(path.join(uploadDir, safeName), buffer);

Scenario 3: Blog Post URL

You need a clean URL for a new article based on its title.

  • βœ… Best choice: slugify
  • Why? It creates SEO-friendly, lowercase URLs with dashes.
const urlSlug = slugify(postTitle);
router.get(`/posts/${urlSlug}`, handler);

πŸ“Š Summary Table

Featurefilenamifysanitize-filenameslugify
Primary GoalValid FilenamesSecurity & SafetyURL Slugs
Case HandlingPreserves CasePreserves CaseForces Lowercase
Invalid CharsReplaces (e.g., _)RemovesReplaces (e.g., -)
Path TraversalNoYesPartial
Windows ReservedYesYesNo
Config OptionsYesNoYes

πŸ’‘ Final Recommendation

These tools solve different problems despite similar inputs. Use filenamify for client-side downloads where user experience matters. Use sanitize-filename for server-side storage where security is critical. Use slugify for routing and web addresses. Never mix them up β€” using slugify for filenames loses case information, and using filenamify for URLs might leave unsafe characters.

How to Choose: filenamify vs sanitize-filename vs slugify

  • filenamify:

    Choose filenamify when you need to save user-generated files on the client or server while keeping the name readable and safe. It handles OS-specific reserved names and allows you to control replacement characters. This is the best option for download buttons, export features, or any scenario where the original filename structure matters.

  • sanitize-filename:

    Choose sanitize-filename when security is the primary concern, especially on the server side. It aggressively removes illegal characters and path separators to prevent directory traversal attacks. Use this for handling untrusted input where safety outweighs preserving the exact original string format.

  • slugify:

    Choose slugify when generating URL paths, SEO-friendly identifiers, or database keys. It converts text to lowercase and replaces special characters with dashes, making it unsuitable for preserving case-sensitive filenames. This is the standard choice for routing, permalinks, and human-readable IDs.

README for filenamify

filenamify

Convert a string to a valid safe filename

On Unix-like systems, / is reserved. On Windows, <>:"/\|?* along with trailing periods and spaces are reserved.

This module also removes non-printable control characters (including Unicode bidirectional marks) and normalizes Unicode whitespace.

Install

npm install filenamify

Usage

import filenamify from 'filenamify';

filenamify('<foo/bar>');
//=> '!foo!bar!'

filenamify('foo:"bar"', {replacement: '🐴'});
//=> 'foo🐴bar🐴'

API

filenamify(string, options?)

Convert a string to a valid filename.

filenamifyPath(path, options?)

Convert the filename in a path to a valid filename and return the augmented path.

import {filenamifyPath} from 'filenamify';

filenamifyPath('foo:bar');
//=> 'foo!bar'

options

Type: object

replacement

Type: string
Default: '!'

String to use as replacement for reserved filename characters.

Cannot contain: < > : " / \ | ? * or control characters.

maxLength

Type: number
Default: 100

Truncate the filename to the given length.

Only the base of the filename is truncated, preserving the extension. If the extension itself is longer than maxLength, you will get a string that is longer than maxLength, so you need to check for that if you allow arbitrary extensions.

Truncation is grapheme-aware and will not split Unicode characters (surrogate pairs or extended grapheme clusters). If the remaining budget (after accounting for the extension) is smaller than a whole grapheme, the base filename may be truncated to an empty string to avoid splitting.

Systems generally allow up to 255 characters, but we default to 100 for usability reasons.

Browser-only import

You can also import filenamify/browser, which only imports filenamify and not filenamifyPath, which relies on path being available or polyfilled. Importing filenamify this way is therefore useful when it is shipped using webpack or similar tools, and if filenamifyPath is not needed.

import filenamify from 'filenamify/browser';

filenamify('<foo/bar>');
//=> '!foo!bar!'

Related