A slug is the URL-friendly part of a page address: in https://toolsnug.com/text/transform/slugify, the bits separated by slashes are slugs. Generating one from a title is one of those tasks that looks trivial until you realise how many edge cases hide in plain text — accented letters, ligatures, characters from non-Latin scripts, punctuation, runs of whitespace, capitalisation conventions.
This tool produces clean, predictable slugs from any input, with the same algorithm most static-site generators and CMSs use under the hood.
How it works
Six steps:
- Apply special-case map. A handful of characters Unicode normalisation doesn’t help with (German ß, Polish ł, Norwegian ø, AE/OE ligatures, Icelandic þ/ð) get manually mapped to ASCII equivalents.
- Unicode NFKD normalisation. Decomposes accented characters into base letter + combining mark. Café becomes Cafe + combining acute.
- Strip combining marks. The combining marks from step 2 (and any others) get removed via the regex
\p{M}+. - Replace non-alphanumerics with separator. Anything that isn’t
[A-Za-z0-9]becomes the chosen separator (hyphen by default). - Collapse separator runs and trim. Multiple separators in a row become one; leading and trailing separators get stripped.
- Lowercase. Optional but on by default.
Optional extras: stop-word removal (drops English connector words like ‘the’, ‘and’, ‘of’) and max-length truncation (cuts at the most recent word boundary if possible).
Example: blog post title
My New Blog Post About Café & Résumé becomes my-new-blog-post-about-cafe-resume. The accented characters lose their accents (NFKD + strip-combining), the punctuation collapses to a single hyphen, and the result is a clean URL slug.
With remove stop words on, the same input becomes new-blog-post-cafe-resume — my and about get dropped as English stop words.
Example: branch name
Git branch names benefit from the same treatment. Fix the Sign-Up Form Bug → fix-the-sign-up-form-bug. Some teams prefer underscores in branch names; switch the separator. The output is safe for any Git remote, no special escaping needed.
Example: non-English titles
Łódź København weiß → lodz-kobenhavn-weiss. The special-case map handles ł, ø, and ß explicitly because those don’t decompose helpfully via NFKD alone.
hello мир world → hello-world. Cyrillic doesn’t decompose to ASCII, so the Russian word гets dropped (replaced with the separator and collapsed). For non-Latin source languages, transliterate to ASCII first with a locale-aware tool, then slugify.
Common mistakes
Expecting Cyrillic / CJK / Arabic to transliterate. They don’t, and shouldn’t — generic Unicode normalisation can’t know whether your Russian “Х” should map to “Kh” (English convention) or “H” (Bulgarian) or something else. Use a locale-specific transliteration tool first.
Slugifying after URL-encoding. If your input is already URL-encoded (Caf%C3%A9 instead of Café), slugify it before encoding, not after. Otherwise the percent signs get stripped along with the encoding and you lose the character entirely.
Forgetting that slug uniqueness is your job. Slugify is deterministic — the same input always gives the same slug. If two posts have similar titles (“My Post” and “My Post 2”) they’ll both want my-post. Adding the disambiguator (date, ID, suffix) is the calling system’s job.
Slugifying user-supplied raw HTML. If your input might contain HTML tags, strip them first with the strip HTML tool. Otherwise tag characters become hyphens and the structure leaks into the slug.
What this tool does not do
It doesn’t transliterate non-Latin scripts. Real transliteration needs locale knowledge.
It doesn’t enforce uniqueness against an existing set. The output is deterministic; uniqueness logic lives in the application that consumes the slug.
It doesn’t preserve case in any locale-aware way (Turkish dotted/undotted i, etc.). Lowercase uses JavaScript’s default toLowerCase, which works for most languages but has the well-known Turkish bug for that specific case. For non-URL case transformations (camelCase, snake_case, CONSTANT_CASE), the case converter is the sibling tool.