Examples
| Title | Slug | Keeping non-Latin letters |
|---|---|---|
| Crème Brûlée & Café au Lait | creme-brulee-and-cafe-au-lait |
creme-brulee-and-cafe-au-lait |
| Straße, Łódź und Øresund | strasse-lodz-und-oresund |
strasse-lodz-und-oresund |
| What’s New in Node.js 24? | whats-new-in-node-js-24 |
whats-new-in-node-js-24 |
| --Hello World-- | hello-world |
hello-world |
| Привет, мир — hello | hello |
привет-мир-hello |
Generating slugs in code
function slugify(title) {
return title
.normalize('NFKD')
.replace(/\p{M}/gu, '') // strip accents
.toLowerCase()
.replace(/['’]/g, '') // don't -> dont
.replace(/[^a-z0-9]+/g, '-') // everything else separates words
.replace(/^-+|-+$/g, '');
}
slugify('Crème Brûlée: A Beginner’s Guide'); // 'creme-brulee-a-beginners-guide'
// Note: ß, æ, ø and ł don't decompose and need a lookup table (or the slugify package).
# pip install python-slugify
from slugify import slugify
slugify("Crème Brûlée: A Beginner’s Guide") # 'creme-brulee-a-beginners-guide'
slugify("Привет мир") # 'privet-mir' (transliterates)
# Django
from django.utils.text import slugify
slugify("Crème Brûlée", allow_unicode=False) # 'creme-brulee'
use Illuminate\Support\Str;
Str::slug('Crème Brûlée & Café'); // 'creme-brulee-cafe'
Need a different naming style, like snake_case or camelCase? Use the case converter. To percent-encode text for a query string instead, use URL encode.
Frequently asked questions
What is a URL slug?
The readable part of a URL that identifies a page, like how-to-fix-502-bad-gateway in example.com/blog/how-to-fix-502-bad-gateway. A good slug is short, lowercase, uses hyphens between words and only contains letters, digits and hyphens, so it never needs percent-encoding.
Hyphens or underscores?
Hyphens. Google treats a hyphen as a word separator, so red-shoes is read as “red shoes”, while red_shoes may be read as one word. Underscores are fine for file names and identifiers, which is why the separator can be changed.
How are accents and special letters handled?
Accents are removed by splitting each letter into its base letter and accent (Unicode NFKD) and dropping the accent, so é becomes e and ñ becomes n. Letters that don’t decompose are mapped by hand: ß to ss, æ to ae, ø to o, ł to l, đ to d and þ to th. An ampersand becomes “and”, and apostrophes are dropped so don’t becomes dont rather than don-t.
What happens to Chinese, Cyrillic or Arabic titles?
By default letters without a Latin equivalent are dropped, because they would be percent-encoded in many tools (%D0%BF%D1%80…). Tick “Keep non-Latin letters” to keep them: modern browsers display such URLs readably, and Google indexes them fine. Transliteration (привет to privet) depends on the language, so it isn’t guessed.
Should I remove stop words?
It’s optional. Dropping words like “the”, “a” and “of” makes slugs shorter (how-to-fix-the-error becomes fix-error), but can make them less readable. Google says it doesn’t matter for ranking; keep slugs short and descriptive either way. A title made only of stop words is never reduced to nothing.