The Quick Answer
A URL slug is the readable part of a URL that identifies a specific page:
https://example.com/blog/how-to-create-url-slugs
└─────────────────────┘
slug
Good slug: how-to-create-url-slugs
Bad slug: post?id=123&ref=abc
A good slug is lowercase, uses hyphens as word separators, contains only ASCII letters and numbers, and is short enough to read at a glance — typically 3 to 5 words.
Why Slugs Matter
For SEO
Search engines use URLs to understand page content. Keywords in slugs provide a lightweight ranking signal and, more importantly, improve click-through rates in search results:
// Good - tells Google what the page is about
/blog/javascript-array-methods
// Bad - no useful information
/blog/post-12345
Google highlights matching keywords in URLs in search results. A user searching for "javascript array methods" sees their query bolded in the URL, making the result more clickable.
For Users
People read and share URLs. Readable slugs build trust and set expectations:
// Would you click this?
example.com/products/blue-wireless-headphones
// Or this?
example.com/products/item?sku=BWH-001&ref=nav
Readable URLs are also easier to share verbally, in chat, and on social media. When a URL is truncated in a tweet or message preview, a descriptive slug still communicates what the page is about.
Slug Formatting Rules
1. Lowercase Everything
// Good
/blog/my-article-title
// Bad
/blog/My-Article-Title
Why: URLs are case-sensitive on many servers. My-Article and my-article can resolve to different pages, creating duplicate content issues. Consistent lowercase prevents this entirely.
2. Use Hyphens, Not Underscores
// Good
/blog/my-article-title
// Bad
/blog/my_article_title
Why: Google treats hyphens as word separators, but underscores join words. The slug blue-shoes is indexed as two words ("blue" and "shoes"), while blue_shoes is treated as one token ("blue_shoes"). This has been confirmed by Google's Matt Cutts and remains the standard.
3. Remove Special Characters
// Original: "What's the Best Way to Learn C++?"
// Good
/blog/whats-best-way-learn-cpp
// Bad
/blog/what's-the-best-way-to-learn-c++?
Special characters like ?, &, =, #, and % have reserved meanings in URLs. Including them in slugs causes encoding issues and makes URLs harder to read. Replace known abbreviations with readable text when possible (C++ → cpp).
4. Remove Stop Words (When It Helps)
Stop words: a, an, the, is, at, which, on, for, etc.
// With stop words
/blog/how-to-create-a-url-slug
// Without (more concise)
/blog/create-url-slugs
Remove stop words if the slug is too long. Keep them if removal changes meaning or hurts readability. "how-to-tie-a-tie" is clearer than "tie-tie."
5. Keep It Short
// Good (3-5 words)
/blog/javascript-array-methods
// Too long
/blog/the-complete-guide-to-all-javascript-array-methods-with-examples
Aim for 3–5 words or under 60 characters. Google truncates displayed URLs in search results beyond roughly 60 characters, and longer URLs are harder to share, copy, and remember.
Handling Accented and International Characters
One of the most common slug challenges is dealing with non-ASCII text — accented letters, characters from non-Latin scripts, and special typographic symbols.
Transliteration: Accented Characters to ASCII
Accented characters like é, ü, ñ, ø, and ß should be converted to their closest ASCII equivalents. This is called transliteration:
| Input | Transliterated | Slug |
|---|---|---|
| Café Résumé | Cafe Resume | cafe-resume |
| Über uns | Uber uns | uber-uns |
| El niño | El nino | el-nino |
| Ærø Island | Aero Island | aero-island |
| Straße | Strasse | strasse |
The standard approach uses Unicode NFKD normalization, which decomposes characters like é into e + a combining accent mark. You then strip the combining marks, leaving the base letter.
Non-Latin Scripts
For text in Cyrillic, Chinese, Japanese, Arabic, or other non-Latin scripts, you have two options:
-
Transliterate to Latin — Convert characters to their romanized equivalents. "Москва" becomes
moskva. This works well when your audience primarily uses Latin-script search engines. -
Use percent-encoded Unicode — Keep the original script in the URL. Modern browsers display Unicode URLs correctly, and Google indexes them. "example.com/блог/москва" appears readable in the browser address bar.
For most international sites, option 1 (transliteration) produces cleaner, more portable slugs.
Common Transliteration Mappings
| Character | ASCII equivalent | Language |
|---|---|---|
| ä, ö, ü | ae, oe, ue | German |
| ß | ss | German |
| æ, ø, å | ae, oe, aa | Danish, Norwegian |
| ñ | n | Spanish |
| ç | c | French, Portuguese, Turkish |
| ş, ğ, ı | s, g, i | Turkish |
| ł, ż, ź | l, z, z | Polish |
| ð, þ | d, th | Icelandic |
Some transliterations are language-dependent. German "ü" is conventionally transliterated as "ue," while Turkish "ü" is typically just "u." Choose mappings based on your audience's expectations.
Slugify Code in Multiple Languages
JavaScript
function slugify(text) {
return text
.normalize('NFKD') // Decompose accented characters
.replace(/[\u0300-\u036f]/g, '') // Strip combining diacritical marks
.toLowerCase()
.trim()
.replace(/[^\w\s-]/g, '') // Remove remaining special chars
.replace(/\s+/g, '-') // Spaces to hyphens
.replace(/-+/g, '-') // Collapse consecutive hyphens
.replace(/^-+|-+$/g, ''); // Trim leading/trailing hyphens
}
slugify("Héllo Wörld!") // "hello-world"
slugify("Café Résumé") // "cafe-resume"
slugify(" Multiple Spaces ") // "multiple-spaces"
The normalize('NFKD') step is the key to handling accented characters — it breaks é into e + ◌́ (combining acute accent), and the regex strips the accent.
Python
from slugify import slugify
slugify("Hello World!") # "hello-world"
slugify("Café Résumé") # "cafe-resume"
slugify("日本語テスト") # "ri-ben-yu-tesuto"
Install with pip install python-slugify. The library handles Unicode transliteration, CJK characters, and edge cases automatically. For Django projects, use django.utils.text.slugify which is built in but does not transliterate non-Latin scripts by default.
PHP
function slugify(string $text, string $separator = '-'): string {
// Transliterate
$text = transliterator_transliterate(
'Any-Latin; Latin-ASCII; Lower()', $text
);
// Remove non-alphanumeric characters
$text = preg_replace('/[^a-z0-9\s-]/', '', $text);
// Replace whitespace and repeated separators
$text = preg_replace('/[\s-]+/', $separator, trim($text));
return $text;
}
slugify("Héllo Wörld!"); // "hello-world"
This uses PHP's intl extension for robust transliteration. In Laravel, use Str::slug() which handles this automatically.
Ruby
require 'babosa' # gem install babosa
"Héllo Wörld!".to_slug.transliterate.normalize.to_s
# => "hello-world"
In Rails, ActiveSupport provides parameterize:
"Hello World!".parameterize
# => "hello-world"
CMS and Framework Guidance
Different platforms handle slugs differently. Here is what to know for the most common ones:
WordPress
WordPress auto-generates slugs from post titles. You can edit them in the post editor under the "Permalink" section. WordPress handles basic transliteration for some languages but may need the WP Slugs or Flavor plugin for better non-Latin support.
Tips:
- Edit the auto-generated slug before publishing — WordPress does not remove stop words by default
- If you change a slug after publishing, WordPress does not create a redirect automatically — use a redirect plugin
- Avoid changing slugs on high-traffic pages unless necessary
Next.js / Gatsby (Static Site Generators)
These frameworks typically derive slugs from filenames or frontmatter:
// File-based routing (Next.js App Router)
app/blog/javascript-array-methods/page.tsx
// Slug = "javascript-array-methods"
// Frontmatter-based (MDX/Gatsby)
---
slug: javascript-array-methods
---
For dynamic slug generation, use a library like slugify or github-slugger:
npm install github-slugger
import GithubSlugger from 'github-slugger'
const slugger = new GithubSlugger()
slugger.slug('Hello World!') // 'hello-world'
Django
Django provides slugify in django.utils.text:
from django.utils.text import slugify
slugify("Hello World!") # "hello-world"
For Unicode support, set allow_unicode=True or use python-slugify for transliteration. In models, combine with unique=True on the slug field to prevent duplicates:
class Article(models.Model):
title = models.CharField(max_length=200)
slug = models.SlugField(unique=True)
Hugo
Hugo auto-generates slugs from filenames. Override with frontmatter:
slug: "custom-slug-here"
Configure default slug behavior in config.toml:
[permalinks]
posts = "/:slug/"
SEO Best Practices
Include Your Target Keyword
// Targeting "chocolate chip cookies recipe"
/recipes/chocolate-chip-cookies
// Not helpful
/recipes/recipe-47
Place the primary keyword near the start of the slug. Search engines give slightly more weight to words earlier in the URL, and truncated URLs in search results still show the keyword.
Match User Intent
// Informational
/blog/what-is-seo
// Transactional
/products/wireless-mouse
// Navigational
/about/contact
Align the slug with the search intent of your target query. Informational slugs often work well with "what-is" or "how-to" prefixes. Product slugs should describe the item, not an internal SKU.
Avoid Dates in URLs (Usually)
// Bad - becomes outdated and adds unnecessary depth
/blog/2024/01/15/seo-tips
// Better - evergreen
/blog/seo-tips
Exception: News sites where publication date is editorially important. For evergreen content, dateless URLs allow you to update the content without the URL looking stale.
Keep URLs Flat
// Too deep - hard to read, confusing hierarchy
/blog/2024/tech/programming/javascript/arrays/methods
// Better - clear and concise
/blog/javascript-array-methods
Each additional path segment implies a hierarchical relationship. Deep nesting makes URLs harder to read and gives search engines a more complex site structure to crawl. Keep paths to 2–3 segments when possible.
Keep URLs Stable
Changing URLs loses:
- Search engine rankings built over time
- Backlinks from other sites
- Social media shares and bookmarks
If you must change a slug, always set up a 301 redirect from the old URL to the new one. This tells search engines to transfer link equity to the new address. Without the redirect, any authority the old URL had is lost.
Common Mistakes
1. Keyword Stuffing
// Bad - reads like spam
/seo-tips-seo-guide-seo-tutorial-seo-help
// Good - natural and descriptive
/seo-guide-for-beginners
Repeating keywords in slugs does not improve rankings — search engines recognize this as manipulation and it hurts click-through rates because the URL looks untrustworthy.
2. Using IDs Without Descriptive Text
// Bad - tells nobody anything
/products/12345
// Good - describes the product
/products/wireless-bluetooth-headphones
Numeric IDs are fine as internal identifiers but should not be the only thing in a slug. If your CMS generates ID-only URLs, override them with descriptive slugs.
3. Including File Extensions
// Unnecessary for modern web servers
/about-us.html
// Cleaner
/about-us
Modern web servers and frameworks serve pages without file extensions. Removing .html, .php, or .aspx from slugs makes URLs cleaner and prevents issues if you change server technology later.
4. Inconsistent Separator Usage
// Mixing separators - confusing
/blog/my_article-title
// Consistent
/blog/my-article-title
Pick one separator (hyphens) and use it everywhere. Mixing hyphens and underscores creates inconsistency and makes URLs harder to type correctly.
5. Not Handling Duplicate Slugs
When two pages generate the same slug (e.g., two articles titled "Best Practices"), most CMS platforms append a number: best-practices-2. This is functional but not ideal. Differentiate slugs manually:
// Instead of auto-generated duplicates
/blog/best-practices
/blog/best-practices-2
// Use distinct slugs
/blog/css-best-practices
/blog/javascript-best-practices
Slug Migration Checklist
When redesigning a site or changing URL structures, follow this checklist to avoid losing search traffic:
- Export all current URLs — crawl your site or export from your CMS
- Map old URLs to new URLs — create a spreadsheet with old slug → new slug
- Implement 301 redirects — server-level redirects (
.htaccess,nginx.conf, or your framework's redirect rules) - Test every redirect — verify with
curl -Ior a redirect checker tool - Update internal links — search your codebase and content for old URLs
- Submit updated sitemap — resubmit
sitemap.xmlin Google Search Console - Monitor 404 errors — check Google Search Console for crawl errors over the following weeks
A 301 redirect transfers approximately 90-99% of link equity to the new URL. A 302 (temporary) redirect does not transfer equity — always use 301 for permanent slug changes.
Slug Generator
Convert any text — including accented characters — into a clean, URL-friendly slug. Batch mode and custom separators available.
Open Slug GeneratorFrequently Asked Questions
What is a URL slug?
A URL slug is the human-readable part of a web address that identifies a specific page. In example.com/blog/how-to-bake-bread, the slug is how-to-bake-bread. Good slugs use lowercase letters, numbers, and hyphens.
Should I use hyphens or underscores in URL slugs?
Use hyphens. Google treats hyphens as word separators and underscores as word joiners. The slug blue-shoes is indexed as two words, while blue_shoes is treated as one.
How long should a URL slug be?
Aim for 3–5 words or under 60 characters. Google truncates URLs in search results around 60 characters. Shorter slugs are easier to read, share, and remember.
How do I handle accented characters in URL slugs?
Convert them to their closest ASCII equivalents through transliteration. Use Unicode NFKD normalization to decompose characters like é into e + accent mark, then strip the marks. Libraries like python-slugify, github-slugger, and PHP's transliterator_transliterate handle this automatically.
Do URL slugs affect SEO?
Yes, as a minor direct ranking factor. The bigger impact is on click-through rates — users are more likely to click a descriptive URL in search results than one with random IDs. Google also bolds matching keywords in URLs.
Can I change a slug after publishing?
You can, but it creates a new URL. Always set up a 301 redirect from the old URL to the new one. Without the redirect, you lose accumulated search rankings, backlinks, and social shares.
What happens if two pages have the same slug?
Most CMS platforms append a number (my-article-2). This works but is not ideal. Use distinct, descriptive slugs for every page to avoid confusion for both users and search engines.
Should I remove stop words from URL slugs?
Remove them if the slug is too long or they add no meaning. Keep them if removal changes the meaning — "how-to-tie-a-tie" is clearer than "tie-tie." There is no SEO penalty for including stop words.
How do I slugify text in Python?
Use python-slugify: from slugify import slugify then slugify("Hello World!") returns "hello-world". Install with pip install python-slugify. For Django, django.utils.text.slugify is built in.
Is it okay to use non-English characters in URL slugs?
Modern browsers and search engines support Unicode URLs. However, transliterated ASCII slugs are more portable — they work reliably in all contexts including email clients, social media previews, and older systems.
Related Tools
- Slug Generator — Convert any text into a clean URL slug
- URL Encoder/Decoder — Encode or decode special characters in URLs
- Meta Tag Generator — Create SEO meta tags for your pages
- SERP Preview Tool — Preview how your URL and title appear in Google results
- Keyword Density Calculator — Check keyword distribution in your content
- Robots.txt Generator — Control search engine crawling