What Makes a Good URL Slug
Most slug advice is about length and hyphens, which are the easy parts. The decisions that actually cost something later are what to do with accented characters, whether to include a date, and the fact that a slug is effectively permanent the moment anyone links to it.

A URL slug is the human-readable part of a URL that identifies one page:
/blog/what-makes-a-good-url-slug. Short, lowercase, hyphenated, no stop words —
that is the advice everywhere, and it is correct as far as it goes.
The parts that go wrong later are elsewhere.
The rules that are genuinely settled
Lowercase. URL paths are case-sensitive on most servers, so /Aboutand
/aboutcan be two different pages. Two URLs for one page splits its signals and
creates a duplicate-content question you did not need to answer. Lowercase
everything, always.
Hyphens, not underscores. Google has stated it treats hyphens as word separators
and underscores as joiners, so url_slugreads as one token and url-slugas two.
This is one of the few pieces of SEO folklore with a direct source.
Three to five words. Long enough to say what the page is, short enough to survive
being pasted into a message without wrapping. /how-to-remove-duplicate-lines-from-a-text-file-online-free
is not better than /remove-duplicate-lines.
No dates. /2024/03/how-to-bake-breadtells a reader the article is old before
they read a word, and it makes updating the piece awkward — either the URL lies or
you change it, and changing it is the thing you must not do.
The accent decision
This is the one that quietly breaks things.
crème brûléehas to become something. There are three options and only one is
right:
Delete the accented characters. crme brle. Unreadable, and it happens more
often than you would expect, because the naive implementation strips anything
non-ASCII.
Percent-encode them. cr%C3%A8me-br%C3%BBl%C3%A9e. Technically valid, and it
looks like line noise anywhere the URL is displayed as text — which includes search
results, shared links, and your own analytics.
Fold to the closest ASCII letter. creme-brulee. Readable, stable, and what
every well-built CMS does.
Folding works by decomposing each character into a base letter plus its diacritical
marks, then dropping the marks — ébecomes e+ a combining acute, and the accent
is removed. Unicode NFD normalization does the decomposition.
There is one language where this needs a decision rather than a default. German has
established conventions for writing umlauts without them: ü→ ue, ö→ oe,
ä→ ae, ß→ ss. So Straßenbahn für Anfängershould arguably be
strassenbahn-fuer-anfaengerrather than strassenbahn-fur-anfanger. Both are
defensible; a German-language site should use the expansion, because that is what a
German reader would type. Our slug generatoroffers both, as
a switch rather than a guess.
Stop words
Removing a, the, of, andand similar shortens a slug at almost no cost to
meaning, and it is standard practice.
Two exceptions where removing them breaks the slug. When the stop word is load-bearing:
the-whois a band and whois not, and war-of-the-worldsneeds its of the.
And when removing everything leaves nothing — a title like "The Best of the Rest"
strips down to best-rest, and a title of pure stop words strips to an empty slug. A
generator that can return an empty string will eventually return one, so it needs a
floor.
Never change a slug
This is the rule with the largest consequences and the least attention.
The moment a URL has been published, it may have been linked, bookmarked, shared in a message, or indexed. Changing it breaks all of those. A 301 redirect preserves most of the link value and none of the shared-message convenience, and every redirect is a permanent piece of configuration you now maintain.
The practical implication is about the moment of creation: spend the thought on the slug before you publish, not after. A slug that is slightly worse than ideal is much cheaper than a redirect, and far cheaper than a broken link.
Corollary: do not derive slugs mechanically from titles if titles change. Titles are edited for clarity all the time and should be. If your CMS regenerates the slug when you edit the title, turn that off.
Multi-word casing in general
Slugs are one case among several, and the conventions do not transfer. kebab-case
for URLs, snake_casein many databases and Python, camelCasein JavaScript,
PascalCasefor types and components, CONSTANT_CASEfor constants.
Converting between them is more error-prone by hand than it looks, particularly at
boundaries: parseHTMLDocumentshould become parse-html-document, not
parse-h-t-m-l-document, which means splitting on lower-to-upper transitions while
keeping runs of capitals together. The
case converterhandles those boundaries, and also handles
the Turkish dotless-ı case that catches anyone who assumes lowercasing is
locale-independent.
The short version
Lowercase, hyphens, three to five words, no dates, fold accents rather than deleting or encoding them, and decide before publishing — because after publishing, the slug is not yours to change any more.