Skip to content

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.

Ganesh Patil·4 min read
Before and after comparison: Short, readable, and never changed afterwards.

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.