Slug Generator

Turn a title into a clean URL slug. The tool transliterates accents, drops punctuation and collapses spaces into hyphens, so "Đà Nẵng: A Developer's Guide" becomes da-nang-a-developers-guide. Paste a list of post titles and you get one slug per line back.

Titles
Slugs

1 Slug Generator example

Titles

1
2
3
10 Things I Learned Building a Café Menu API
Đà Nẵng: A Developer's Guide
Why "Move Fast" Broke Our Deploy Pipeline

Slugs

1
2
3
10-things-i-learned-building-a-cafe-menu-api
da-nang-a-developers-guide
why-move-fast-broke-our-deploy-pipeline

2 What happens to your title

Accents are transliterated

Café becomes cafe, Đà Nẵng becomes da-nang. A percent-encoded accent also works in a browser, but a pasted link then shows caf%C3%A9 instead of a readable word.

Punctuation is dropped

Quotes, colons, apostrophes and emoji are removed. An apostrophe is deleted instead of replaced, so developer's becomes developers instead of developer-s.

Separators are collapsed

Runs of spaces and symbols become a single hyphen, and leading or trailing hyphens are trimmed.

Case is folded

Lowercase is on by default. Most servers treat /About and /about as different paths, so a mixed-case slug invites broken links and duplicate pages.

3 A slug is a permanent decision

Changing a slug later means either a redirect or a broken link, so choose it before you publish. Keep slugs short. The first four or five meaningful words carry the topic, and the rest adds length without adding meaning. Skip the date unless the content is tied to it. For example, /2024-guide-to-css looks stale a year later, while /guide-to-css can be updated in place.

Use hyphens, not underscores. Google has treated hyphens as word separators and underscores as joiners for well over a decade, so web_dev_utility reads as one token and web-dev-utility reads as three words.

How to use the Slug Generator tool

  1. Paste one or more titles into the left panel, one per line.
  2. Change the Separator field if you want something other than a hyphen.
  3. Lowercase is on by default. Tick Drop stop words to shorten long titles by removing words such as the, of and and.
  4. The right panel shows one slug per input line, ready to copy into a CMS or a migration.

How to generate a URL slug in JavaScript, PHP and Python

JavaScript / Node.js

function slugify(input, sep = "-") {
    return input
        .normalize("NFD")                    // split accents from letters
        .replace(/[\u0300-\u036f]/g, "")     // drop the accents
        .replace(/['\u2018\u2019]/g, "")      // apostrophes join, not separate
        .replace(/[^a-zA-Z0-9]+/g, " ")
        .trim()
        .split(/\s+/)
        .join(sep)
        .toLowerCase();
}

console.log(slugify("10 Things I Learned Building a Café API"));
// 10-things-i-learned-building-a-cafe-api

// NFD does not handle every letter: ø, đ and ł have no combining form,
// so map those explicitly if your content needs them.

PHP

<?php
function slugify(string $text, string $sep = '-'): string {
    // Transliterate to ASCII (needs the intl extension)
    $text = transliterator_transliterate('Any-Latin; Latin-ASCII', $text);
    $text = preg_replace("/['\x{2018}\x{2019}]/u", '', $text);
    $text = preg_replace('/[^A-Za-z0-9]+/', $sep, $text);
    $text = trim($text, $sep);
    return strtolower($text);
}

echo slugify("10 Things I Learned Building a Café API"), PHP_EOL;

// Laravel: Str::slug($title) does the same thing, with a language argument
// for locale-specific rules such as German ä -> ae.

Python

import re
import unicodedata

def slugify(text: str, sep: str = "-") -> str:
    text = unicodedata.normalize("NFKD", text)
    text = text.encode("ascii", "ignore").decode("ascii")
    text = re.sub(r"['\u2018\u2019]", "", text)
    text = re.sub(r"[^A-Za-z0-9]+", " ", text).strip()
    return sep.join(text.split()).lower()

print(slugify("10 Things I Learned Building a Café API"))

# Django has django.utils.text.slugify, which does the same
# with allow_unicode as an option.

Common errors and how to fix them

Two posts generate the same slug
Titles repeat, especially across years. Add a uniqueness check at save time and append -2, -3 on a collision, which is what WordPress does.
Accents disappear entirely instead of transliterating
NFD only decomposes letters that have a combining form. ø, đ, ł and ß do not, so the ASCII filter strips them. Map them explicitly before normalizing, as this tool does.
The slug ends with a hyphen
Trailing punctuation in the title became a separator. Trim the separator from both ends after replacing.
Changing a slug broke every existing link
Keep the old slug and send a 301 redirect to the new one. Other sites, bookmarks and search results link to the old URL, so treat a published slug as permanent.
Chinese or Arabic titles produce an empty slug
These scripts have no simple ASCII transliteration. Either allow Unicode in the URL, which modern browsers display correctly, or fall back to the post ID plus a hand-written English slug.

Good to know

Percent-encoded Unicode in a URL does work: /caf%C3%A9 loads and Google indexes it. The trouble comes from the tools around it. The link shows as %C3%A9 when pasted into a chat, some analytics tools decode it twice, and older systems corrupt it. Transliterating to ASCII loses the accent but gives you a URL that stays readable wherever it is copied.

Specifications and references

This tool follows the specifications below. Read them when you need the exact normative wording, for example to settle an edge case between two implementations.

Frequently Asked Questions

What does it do with accented characters?

It transliterates them: café becomes cafe, Ünal becomes unal, Łódź becomes lodz. A percent-encoded accent also works in modern browsers, but a link pasted into a chat then shows caf%C3%A9 instead of a readable word.

Can I use an underscore instead of a hyphen?

Yes. Type _ or any other string into the Separator field. However, we recommend hyphens for a public URL, because Google has said for years that it reads hyphens as word breaks and underscores as part of the word.

Are stop words removed?

Only when you tick Drop stop words. It removes short words such as the, of, and, to and with from titles longer than two words. That shortens a long slug but can make it read oddly, so it is off by default.

What about non-Latin scripts?

Russian Cyrillic is transliterated letter by letter, so Привет becomes privet. Greek, Chinese, Japanese, Korean, Arabic, Hebrew and letters outside the Russian alphabet are dropped, because the tool has no mapping for them. Write those slugs by hand.

Can I slug a whole list?

Yes. Each input line produces one slug on the matching output line, so you can paste a list of post titles and copy the slugs back in the same order.

Related

For identifiers instead of URLs, the case converter covers camelCase and snake_case. If a URL already exists and you need to read it, the URL parser breaks it into parts and the URL decoder unwraps percent-encoding.

More Text & Content Tools

Browse all text & content tools

Copied to clipboard!