Free tool
URL slug generator
A slug is the readable part of a URL that names a page, like how-to-build-a-rest-api in example.com/blog/how-to-build-a-rest-api. Paste a title to get its slug as you type. Paste many titles, one per line, to slugify them in bulk: accents and non-Latin letters are transliterated and repeats can be made unique.
Free · no sign-up · runs in your browser, nothing is uploaded
Slugs appear here as you type.
What makes a good URL slug
Google's URL structure guide gives a few rules that apply directly to slugs:
- Readable words rather than long ID numbers.
- Hyphens, not underscores, between words. Google reads a hyphen as a word break.
- One case. Google treats URLs as case sensitive, so
/Blog/My-Postand/blog/my-postare two URLs. Lower case avoids duplicates. - Non-ASCII characters are percent-encoded when sent. Transliterating them keeps links readable everywhere.
| Title | Slug | What happened |
|---|---|---|
| 10 Tips & Tricks for Node.js | 10-tips-and-tricks-for-node-js | & spelled out, dot split |
| Crème Brûlée Recipe 🍮 | creme-brulee-recipe | Accents removed, emoji dropped |
| What's New in Next.js 15? | whats-new-in-next-js-15 | Apostrophe joins, ? removed |
| Привет, мир | privet-mir | Cyrillic transliterated |
| Über die Größe | uber-die-grosse | ü → u, ß → ss (or ueber with German on) |
| The Best Way to Learn Rust | best-way-learn-rust | With "Remove stop words" on |
How the slug is built
Each line goes through the same steps, in this order:
- Apostrophes inside words are removed, so
don'tbecomesdontand notdon-t. &,@,%and+becomeand,at,percentandplus(switch off "Spell out" to drop them).- Letters are transliterated to ASCII: accents are stripped with Unicode NFKD normalization, and letters without a plain form are spelled out (table below).
- Everything is lower-cased, and anything that is not a letter or digit becomes a word break. Emoji and symbols disappear.
- Optional: numbers and stop words are removed.
- Words are joined with the separator. With a max length, the slug stops at the last whole word that fits, and a cut slug never ends on a word like
andorthe. - In bulk mode with "Unique" on, a slug that already appeared gets
-2,-3and so on, still within the max length.
Empty lines stay empty, so line 12 of the output is always the slug of line 12 of the input. That makes it easy to paste a column from a spreadsheet and paste the slugs back next to it.
Transliteration: accents, ß, Cyrillic and Greek
Most accented Latin letters are a base letter plus a combining mark, so Unicode normalization (normalize('NFKD')) splits é into e and an accent that can be dropped. Some letters have no such split and need a table:
| Letter | Becomes | Notes |
|---|---|---|
| é è ê ë á à ç ñ å | e e e e a a c n a | Accent stripped by NFKD |
| ß | ss | German sharp s |
| æ œ | ae oe | Ligatures |
| ø ł đ | o l d | Letters with a stroke |
| þ ð | th d | Icelandic |
| ä ö ü | a o u, or ae oe ue | Turn on "German" for ae, oe, ue |
| ж ч ш щ | zh ch sh sch | Russian and Ukrainian Cyrillic |
| ю я ё й | yu ya yo y | |
| θ χ ψ | th ch ps | Greek |
Scripts without a Latin spelling here, such as Chinese, Japanese or Arabic, are dropped in ASCII mode. Turn off "Transliterate to ASCII" to keep them: the slug then works like Django's slugify(value, allow_unicode=True), and browsers send the letters percent-encoded. For the encoded form, see the URL encoder and decoder.
Slugify in code
JavaScript, without a library:
function slugify(text) {
return text
.normalize('NFKD') // é -> e + accent
.replace(/[\u0300-\u036f]/g, '') // drop the accents
.toLowerCase()
.replace(/['’]/g, '') // don't -> dont
.replace(/[^a-z0-9]+/g, '-') // everything else -> -
.replace(/^-+|-+$/g, ''); // trim dashes
}
slugify('Crème Brûlée: 10 Tips'); // 'creme-brulee-10-tips'
// Or the slugify package (npm i slugify)
import slugify from 'slugify';
slugify('Crème Brûlée', { lower: true, strict: true }); // 'creme-brulee'Python (Django):
from django.utils.text import slugify
slugify(" Joel is a slug ") # 'joel-is-a-slug'
slugify("你好 World", allow_unicode=True) # '你好-world'PHP:
// Laravel
use Illuminate\Support\Str;
Str::slug('Laravel 5 Framework', '-'); // 'laravel-5-framework'
// WordPress
sanitize_title('Crème Brûlée'); // 'creme-brulee'Ruby on Rails:
"Donald E. Knuth".parameterize # "donald-e-knuth" "Donald E. Knuth".parameterize(separator: "_") # "donald_e_knuth"
Changing the slug of a live page
A new slug is a new URL. Links, bookmarks and search results still point to the old one, so add a permanent (301) redirect from the old URL to the new one. Google's redirect guide says a permanent server-side redirect is the best way to move a page and keep it in search.
Store the slug when the page is created instead of building it from the title on every request. Then fixing a typo in a title does not quietly change the URL. If two pages can share a title, make the slug unique in the database, the same way the "Unique" option adds -2.
Related free tools: the case converter for camelCase and snake_case names, the URL parser to check a full URL, and the meta tag generator for the rest of the page. For SEO products, see SEO tools on DevHunt.
More free developer tools
FAQ
What is a slug generator?+
A slug generator turns a title into the part of a URL that names the page. "10 Tips & Tricks for Node.js" becomes 10-tips-and-tricks-for-node-js: lower case, accents and symbols removed, words joined with hyphens. Blogs, CMSs and web frameworks use slugs so URLs are readable instead of ?id=4812.
How do I generate a slug?+
Paste the title into the box above and copy the slug. For many titles, paste one per line and download the list. In code, most frameworks have a function for it: slugify() in Django, Str::slug() in Laravel, parameterize in Rails, sanitize_title() in WordPress, or the slugify package on npm.
Why is it called a slug?+
The word comes from news media, where a slug is the short internal name given to a story while it is being written and edited. Web publishing tools such as Django took the term for the short label in a URL that names a page.
Can you give me an example of a URL slug?+
In https://example.com/blog/how-to-build-a-rest-api, the slug is how-to-build-a-rest-api. The rest of the URL is the domain and the section (/blog/). The slug is usually made from the page title when the page is created.
Should a slug use hyphens or underscores?+
Hyphens. Google Search Central recommends hyphens instead of underscores to separate words in URLs, because underscores are often read as joining words, as in programming. Underscores and dots are offered here for file names, keys and systems that need them.
Should I remove stop words from a slug?+
It is a choice, not a rule. Removing words like the, a, of and to makes slugs shorter (best-way-learn-rust instead of the-best-way-to-learn-rust), but can change the meaning of some titles. This tool keeps them by default; turn on "Remove stop words" and read the result before you publish.
How long should a URL slug be?+
Google does not set a length limit for slugs; its advice is to keep URLs simple and readable. A short slug is easier to read, share and type, so many sites keep only the key words of the title. Use the Max length setting to cut slugs at a whole word.
Can a slug contain non-English characters?+
Yes. Browsers show them, and they are sent percent-encoded (/%D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82 for /привет). Many sites transliterate to ASCII instead (privet), so links stay readable when copied. Turn off "Transliterate to ASCII" here to keep letters like привет, é or 日本語 as they are.
Sources: Google Search Central: URL structure · Google Search Central: redirects · Django glossary: slug · Django slugify() · WordPress sanitize_title() · Laravel Str::slug() · Rails parameterize · slugify on npm · MDN: String.prototype.normalize() · Wikipedia: Clean URL (slug). Checked 2026-10-30.