What a slug is and why it matters
A slug is the human-readable identifier in a URL path — the how-to-brew-better-coffee in example.com/blog/how-to-brew-better-coffee. It replaces an opaque database ID with something a person can read, remember and trust before clicking.
The requirements are narrow but strict. A slug must be safe in a URL path without percent-encoding, unique within its namespace, stable once published, and ideally short enough to survive being displayed in a search result. Everything this tool does follows from those four constraints.
What the generator does, step by step
- Expand special characters. & becomes "and", and ligatures and non-decomposable letters are mapped: æ→ae, ø→o, ß→ss, þ→th.
- Decompose and strip accents. Unicode NFKD normalisation splits é into e plus a combining acute accent; the combining marks are then removed. café becomes cafe, Björk becomes Bjork.
- Drop apostrophes without a gap. What's becomes whats, not what-s. This is a small detail that most naive implementations get wrong.
- Replace everything else with spaces. Punctuation, symbols and brackets all collapse to word boundaries.
- Optionally remove stop words. Common English function words are dropped when doing so still leaves something.
- Apply case and join with the separator, collapsing repeats and trimming any separator from the ends.
- Truncate at a word boundary if a maximum length is set, so you never get a slug ending mid-word.
A worked example
Input: Café Society: 10 Ways to Brew Better Coffee (2026 Edition)
| Step | Result |
|---|---|
| Accent folding | Cafe Society: 10 Ways to Brew Better Coffee (2026 Edition) |
| Strip non-alphanumerics | Cafe Society 10 Ways to Brew Better Coffee 2026 Edition |
| Lowercase and join | cafe-society-10-ways-to-brew-better-coffee-2026-edition |
| Truncate to 60, word boundary | cafe-society-10-ways-to-brew-better-coffee-2026-edition (54 ch, fits) |
| With stop words removed | cafe-society-10-ways-brew-better-coffee-2026-edition |
Separator choice
Use the hyphen. This is not merely convention — Google has stated for years that hyphens are treated as word separators while underscores are treated as word joiners. That means brew_better_coffee may be read as one token, whereas brew-better-coffee is read as three words.
| Separator | URL-safe | Verdict |
|---|---|---|
| Hyphen - | Yes | The standard. Use this unless you have a specific reason not to. |
| Underscore _ | Yes | Legal but treated as a word joiner. Common in file naming, poor in URLs. |
| Dot . | Yes | Legal, but can be confused with a file extension by both users and servers. |
| Space | No | Must be percent-encoded as %20. Never use. |
| Plus + | Ambiguous | Means "space" in query strings. Avoid entirely. |
Length, and where 60 characters comes from
There is no technical limit that matters — the practical URL ceiling is around 2,000 characters. The constraint is presentational. Search engines truncate long URLs in result listings, and a slug that gets cut mid-thought is less clickable. Fifty to sixty characters keeps the whole thing visible in most result layouts and still carries the meaning.
Word-boundary truncation matters here. Cutting at exactly 60 characters can leave you with ...better-coff, which looks broken. With the option enabled, whole words are dropped instead so the slug always ends cleanly.
Handling duplicates
URLs must be unique, and titles frequently are not. Two posts called "Monthly Update" produce identical slugs. Common resolutions, roughly in order of preference:
- Append a counter — monthly-update-2. Simple, readable, requires a uniqueness check at save time.
- Prefix with a date — 2026-07-monthly-update. Naturally unique for periodic content and sorts well.
- Append a short ID — monthly-update-a7f3. Guaranteed unique, slightly less clean.
- Prefix with the record ID — 4821-monthly-update. The pattern Stack Overflow uses; the slug becomes purely decorative and can change freely without breaking links.
The generator counts duplicates in bulk output so you can spot collisions before they reach your database.
Non-Latin scripts
Accent folding works because Latin letters with diacritics decompose into a base ASCII letter plus a combining mark. That approach fails entirely for scripts with no ASCII equivalent — Chinese, Arabic, Hebrew, Devanagari, Cyrillic, Greek. Those characters have nothing to fold to, so they are stripped, and a title written wholly in such a script produces an empty slug.
Three real options exist. Transliterate using a script-specific library (Cyrillic → Latin is well standardised; Chinese → pinyin needs word segmentation). Use the native script directly — modern browsers handle percent-encoded UTF-8 in paths correctly and display it decoded, which many non-English sites now do. Or fall back to an ID when the slug comes out empty. This tool does none of the three; it tells you when nothing usable was produced so you can handle it deliberately.
Frequently asked questions
Should I remove stop words?
Can slugs contain uppercase letters?
Should numbers stay in the slug?
What characters are actually illegal in a URL path?
How do I handle slugs when a title changes?
Is my input sent anywhere?
URL structure patterns
The slug is one part of a URL, and where it sits in the path affects both usability and how much redirect maintenance you accumulate.
| Pattern | Example | Trade-off |
|---|---|---|
| Flat | /how-to-brew-coffee | Shortest and cleanest, but every slug shares one namespace, so collisions are more likely |
| Sectioned | /blog/how-to-brew-coffee | Clear structure, separate namespaces. The common default. |
| Dated | /2026/07/how-to-brew-coffee | Naturally unique and sorts well, but visibly ages evergreen content |
| ID-prefixed | /4821/how-to-brew-coffee | The slug becomes decorative and can change freely without breaking links — the Stack Overflow approach |
| Deep hierarchy | /blog/coffee/brewing/how-to-brew | Long and fragile; recategorising breaks every URL beneath it |
Shallower is generally better. Deep hierarchies look tidy in a sitemap and become a liability the first time content is reorganised, because every move requires a redirect and every redirect is a small permanent tax.
Slugs and canonical URLs
If your application accepts any slug for a given ID — the ID-prefixed pattern above — you have created infinitely many URLs for one page. Search engines treat those as duplicates unless you tell them otherwise. The fix is a <link rel="canonical"> tag naming the correct URL, ideally paired with a 301 redirect when the requested slug does not match the stored one.
The same applies to trailing slashes and case. /my-post, /my-post/ and /My-Post are three distinct URLs to a crawler. Pick one form, redirect the others to it, and be consistent everywhere — internal links, sitemaps and canonical tags alike.