Skip to content

Slugify

Convert text to a URL-friendly slug (lowercase, hyphens, ASCII).

Slugify converts a string (typically a title) into a URL-safe identifier (a “slug”). The tool above runs the conversion in your browser; nothing leaves your machine.

A typical slugification

Input:  "Hello, World! This is a Test"
Output: "hello-world-this-is-a-test"

The mechanical steps:

  1. Lowercase everything.
  2. Transliterate non-ASCII to ASCII (é → e, ñ → n, 中 → ?).
  3. Replace spaces and other separators with hyphens.
  4. Remove non-alphanumeric characters.
  5. Collapse repeated hyphens.
  6. Strip leading and trailing hyphens.

The result is suitable for URLs, filenames, identifiers — any context where the input would have problematic characters.

Where slugs are used

  • URLs. https://example.com/blog/hello-world-this-is-a-test is more readable and SEO-friendly than https://example.com/blog/post?id=42.
  • Filenames. A slug derived from a title makes a sensible filename without escapes.
  • CSS classes / HTML IDs. A slug is valid as an HTML id attribute (mostly — some IDs starting with a digit are problematic).
  • Database identifiers. When the natural key is human-readable, a slug column augments the auto-increment ID.

Transliteration

The hard part of slugify. Different languages have different conventions:

"café"     → "cafe"        (drop the accent)
"naïve"    → "naive"
"über"     → "uber"         (drop the umlaut)
"crème"    → "creme"

"München"  → "munchen"      (German convention 1)
"München"  → "muenchen"     (German convention 2 — use the alternate form)

"日本"     → ???            (Japanese — no Latin transliteration is "right")
"中国"     → "zhongguo"      (Pinyin)
"中国"     → "china"        (English exonym)

For Latin-script languages with diacritics, accent-stripping is the common approach. For non-Latin scripts, options are: drop entirely, transliterate via romanization (Pinyin, kana-roman), or keep the original characters (modern URLs allow them).

The tool above always strips to ASCII: accents are removed (é → e) and characters without an ASCII base letter, such as Chinese or Cyrillic, are dropped. Modern URLs can carry non-ASCII characters directly via RFC 3987 (IRIs); for non-Latin titles, write or transliterate the slug by hand.

Length limits

Slugs that go in URLs face length limits:

  • 2,048 characters is a common URL length cap.
  • Search engines usually display only the first ~60 characters of a URL. Slugs longer than that are truncated visually.
  • Filesystems historically limited filenames to 255 characters; modern ones allow more but slugs over ~80 characters are unusual.

Most slugify implementations don’t enforce a limit (you do that at use time), but it’s worth knowing the practical cap.

Uniqueness

A slug is derived from a title, but slugs need to be unique in their context (no two posts at the same URL). When two pieces of content have the same title, the slugify output is the same — and you need a disambiguator.

Common patterns:

  • Append a number: hello-world, hello-world-2, hello-world-3.
  • Append a date: hello-world-2026-04-30.
  • Append a hash: hello-world-a1b2c3 (truncated content hash).
  • Use the database ID: 42-hello-world or hello-world-42.

The “ID + slug” pattern is common for sites with many short titles where collisions are likely.

Reserved words and patterns

Some slug values cause routing or filesystem issues:

  • Reserved file names in Windows: CON, PRN, AUX, NUL, COM1, LPT1. A blog post titled “CON” produces a slug that crashes file-based systems on Windows.
  • Routing collisions. A site that has /admin route can’t have a post slugged admin.
  • Pure-numeric slugs. 2025 could be ambiguous with year-based URLs.

Most slugify libraries don’t handle these — they’re application-specific concerns.

Hyphen vs underscore

Two conventions for word separator:

  • Hyphen (-) — the dominant convention for URL slugs. Search engines treat hyphens as word separators.
  • Underscore (_) — common for code identifiers (Python variable names, database column names). Search engines treat underscores as word connectors.

For URLs, use hyphens. For code identifiers, use underscores. The tool above defaults to hyphens; switch to underscores for code-identifier use.

Common pitfalls

  • Lossy transliteration. “Café” and “Cafe” both slug to cafe. If both exist as content, you have a collision.
  • Trailing punctuation in input. "Hello!" slugs to hello (drops the exclamation), which is usually right but means "Hello" and "Hello!" both produce hello.
  • Empty slug from punctuation-only input. "!!!" slugs to empty. Decide what to do — error out, use a default like untitled, or use a fallback.
  • Mixed-language titles. A title with Latin and CJK script produces partially-transliterated, partially-stripped output. Decide which language’s rules apply.
  • Case sensitivity in URLs. Slugs are lowercased in convention but URLs are technically case-sensitive. Use case-insensitive routing if you need to be tolerant.
  • Re-slugifying. Slugifying an already-slug input is idempotent in well-implemented slugify. Re-slugifying a URL-encoded input may not be.

For other text utilities, see text case, URL encoder.