Slug rules for URLs and filenames

Published: 2026-09-05

How to turn titles into stable URL path segments and safe filenames—separators, Unicode vs ASCII folding, collisions, and how slugify differs from percent-encoding.

A slug is a short, stable string derived from a human title for use in a URL path or filename. Spaces and punctuation become separators; letters are usually lowercased. Good slugs stay readable in the address bar, survive copy-paste, and avoid characters that break paths or shells.

Slugify is a string transform, not a CMS rulebook: frameworks and CDNs still decide redirects, uniqueness, and whether /Blog/ and /blog/ collide. Understanding the transform helps you pick options that match your stack.

What makes a good slug

Goal Prefer Avoid
Readable URLs Lowercase words joined by hyphens Mixed case, %20 from raw spaces
Stable links Deterministic output from the same title Random suffixes unless you need uniqueness
Path safety Letters, digits, - or _ /, ?, #, &, quotes, control characters
Cross-system filenames ASCII-only when tools choke on Unicode Relying on every OS/encoding to agree

Example: title Résumé — Café & Øresund 2026! might become:

  • Latin ASCII + hyphen: resume-cafe-oresund-2026
  • Unicode + hyphen: résumé-café-øresund-2026 (letters kept; punctuation dropped)

Neither is “more correct”—they solve different constraints (conservative ASCII hosts vs. native-script URLs).

Separators: hyphen vs underscore

  • Hyphen (-) — Default for public URLs and kebab-case. Search engines and humans treat hyphens as word breaks. Path segments like /learn/slug-rules-for-urls-and-filenames follow this pattern.
  • Underscore (_) — Common in code identifiers and some file naming schemes. Underscores are fine in URLs but are often not treated as word separators for readability.

Use one separator consistently per surface (blog paths vs. download filenames). Mixing both in one slug (user_profile-id) is usually a smell.

Unicode mode vs Latin ASCII folding

Many sites need ASCII path segments so proxies, older analytics, and hand-typed links stay simple. Others want native letters in the path for language-specific brands.

Typical pipeline for a Latin ASCII slug:

  1. Expand a few compatibility letters (e.g. ßss, œoe).
  2. Normalize and strip combining accents (ée).
  3. Keep only a–z and digits; everything else becomes a separator boundary.
  4. Join runs with - or _ and lowercase.

A Unicode mode keeps letters and numbers across scripts after lowercasing, and still drops punctuation and spaces into separators. Prefer that when the title is not Latin-script and you do not want lossy folding. A deterministic slugify is not a curated dictionary for every language—edge scripts may need editorial overrides.

URLs vs filenames

Slugs in URLs sit in a path segment. After you have a clean slug, any remaining reserved characters still need percent-encoding if you assemble the string by hand—but a well-formed slug usually needs little or no further escaping.

Filenames add OS and tool constraints:

  • Length limits and reserved names (CON, NUL on Windows).
  • Leading/trailing dots and spaces.
  • Whether the filesystem is case-sensitive (Photo.jpg vs photo.jpg).

Treat the slug as the basename; keep the extension separate (report.pdf, not inside the slugified title).

Collisions and uniqueness

Different titles can collapse to the same slug ("Hello!" and "hello"hello). CMS platforms often append -2, a date, or an id. Do that after slugify, as a product rule—not inside a generic string tool—so previews stay predictable.

When batching many titles, enable one slug per line so each row is independent. Empty lines should stay empty so you can align with a spreadsheet column.

Slugify vs case conversion vs encoding

Task Tool / concept
Title → path segment / basename Slugify
Identifier style (camelCasesnake_case) Text case converter
Escape reserved URL bytes URL encoder

Case conversion preserves more of the original token structure; slugify throws away punctuation and often folds accents. Encoding escapes bytes for transport—it does not invent readable hyphens.

Try it locally

Unpublished post titles and internal doc names do not need to leave your machine. LocalTools’ Slugify runs entirely in the browser:

  1. Paste a title (or one title per line).
  2. Choose Unicode or Latin ASCII, and hyphen or underscore.
  3. Pick whole-box vs per-line batching, then copy the result.

Nothing is uploaded for processing.

Related reading

All learn articles