Free URL Slug Generator
Turn any text into a URL-friendly slug.
What Is a URL Slug?
A slug is the human-readable, URL-safe path segment that identifies a page within a site. It sits at the tail of the URL and replaces what would otherwise be an opaque database identifier with a descriptive token. In https://example.com/blog/2026/my-awesome-post, the slug is my-awesome-post. Mechanically, a slug is the output of a deterministic transformation: take an arbitrary input string, strip everything that isn't allowed in a URL path segment, fold case, replace whitespace with a separator, and emit ASCII. The transformation is one-way in practice, you can't reliably reconstruct "My Awesome Post: Take Two!" from my-awesome-post-take-two: which is why slugs are stored alongside the original title, not in place of it.
A good slug is URL-safe (every character can appear without percent-encoding), stable (once published it should never change, broken links rot the web), descriptive (a reader skimming the URL should be able to guess the topic), short (long enough to be useful, short enough to fit in tweets and search snippets), and unique within its containing path. The slug is distinct from the path (which may include directory segments), the query string (the part after the question mark), and the fragment (the part after the hash). It is the last meaningful component of the path.
Where the Word Comes From, 19th-Century Newsrooms
The word predates the web by a century. In Linotype-era composing rooms, each line of type was cast as a single strip of metal (a "slug") about thirty picas wide and weighing roughly twelve ounces in lead. The term then drifted to mean the short identifier an editor wrote at the top of a story to label it through production: a one- or two-word handle like mayor-budget or school-fire that journalists, sub-editors and printers could use to refer to the story without typing out the full headline. AP and major-daily style guides still document the usage.
When Movable Type, WordPress and the early Django docs adopted "slug" as a field name in the early 2000s, they were borrowing the newsroom term wholesale. Django's documentation has called the field slug since at least the 0.91 release in 2005, with the now-canonical definition: a short label containing only letters, numbers, underscores or hyphens, generally used in URLs. The metaphor lands precisely because both the lead-cast slug and the URL slug are short, distinct, machine-friendly tokens that point to a longer thing.
RFC 3986 and the Unreserved Character Set
URL syntax is defined by RFC 3986 ("Uniform Resource Identifier (URI): Generic Syntax"), published January 2005 by Tim Berners-Lee, Roy Fielding and Larry Masinter, replacing RFCs 2396 and 2732. It is an STD 66 Internet Standard, the IETF's highest maturity tier, reserved for protocols of demonstrated stability and broad implementation. Section 2.3 of RFC 3986 defines the unreserved characters, the only characters that are guaranteed to be safe in any URI component without percent-encoding: A-Z, a-z, 0-9, hyphen, period, underscore, and tilde. That's sixty-six characters total. Everything else is either a reserved character (with structural meaning in some URI component) or "other", anything in the latter group must be percent-encoded if it appears in a URI.
Because the unreserved set is the only set guaranteed to round-trip cleanly through every URI parser ever written, slug generators converge on a near-identical pipeline: lowercase the alphabetic characters, keep the digits, keep the hyphens, replace whitespace with a single hyphen, and either strip-or-transliterate everything else. Underscore, period and tilde are technically allowed but conventionally avoided in slugs, period clashes with file extensions, tilde reads as a home directory in old URL conventions, and underscore loses to hyphen for the SEO reasons covered below.
"Cool URIs Don't Change", Berners-Lee, 1998
Tim Berners-Lee's 1998 style note "Cool URIs Don't Change", hosted on the W3C site, is the most-cited piece of slug philosophy ever written. The opening line is famous: a cool URI is one which does not change. The note then reads as a polemic against URL designs that bake transient implementation details into the path. The recommended don'ts have shaped slug practice for nearly thirty years: don't put authoring-tool extensions into the URL (they leak the implementation and break when you migrate; don't put status into the URL) pages move out of "current" but the URL shouldn't; don't put authors' names in, authors move on; don't put dates in unless the date is fundamental to the resource; don't put session IDs, query parameters or login state into a canonical URL.
The slug (the descriptive, semantic, lowercase-hyphen-words) is exactly what is allowed in a "cool" URI. Everything else is structural decoration that should not bleed into the address. WordPress's permalink design, Django's SlugField and Rails's to_param all internalise this guidance: emit a URL that's the meaning of the page, not the mechanics of how it is served.
Hyphens Beat Underscores, and It's Documented
In a 2005 WebmasterWorld interview, Google engineer Matt Cutts said hyphens are treated as word separators by Google's tokenizer, while underscores are word joiners. So green-apples is read as the two tokens green and apples, while green_apples is read as the single token green_apples. For the query "green apples", the hyphenated URL would match the title-keyword check; the underscored URL would not. Cutts revisited this in 2007 on his blog and in a 2011 Google Webmaster Help video on YouTube ("Underscores vs. dashes in URLs"), reaffirming the same advice and noting that Google had at one point evaluated changing the underscore behaviour to also act as a separator but had not done so because it would have broken too many existing URLs that intentionally used underscores as joiners (__init__.py, programming function names).
Google's current "URL structure best practices for Google Search" page recommends hyphens directly: a URL like /green-dress.html is more useful than /greendress.html, and you should use hyphens instead of underscores. The recommendation has been continuously documented for over twenty years. The effect is small per URL but compounds across a site of thousands of pages, and converting hyphens to underscores has no upside, there's no SEO scenario where underscores win. Every credible slug guide ends with the same advice: use hyphens.
Unicode Normalisation, How NFD Strips Accents
The Unicode standard defines two ways to encode many accented characters: precomposed (a single code point, where é is U+00E9) and decomposed (a base letter followed by combining marks, where é is U+0065 plus U+0301, the combining acute accent). Visually identical, byte-for-byte different. Unicode Technical Standard #15 defines four normalisation forms (NFC, NFD, NFKC, NFKD) and for slug generation, NFD is the lever. If you take an input string, normalise to NFD, then strip every code point in the Unicode range U+0300 to U+036F (the Combining Diacritical Marks block), you get the base ASCII letter back. Café becomes cafe, naïve becomes naive, François becomes Francois, niño becomes nino, crème brûlée becomes creme brulee.
NFD does not fold characters that aren't decomposable into base+mark. The German ß (sharp s) does not decompose to ss under NFD, it requires explicit transliteration. The Polish ł (l with stroke) does not decompose to l. The Norwegian ø does not decompose to o. The Icelandic þ (thorn) and ð (eth) need lookup tables. Browsers have natively supported String.prototype.normalize() since approximately 2015 (Chrome 34, Firefox 31, Safari 10), which is why even small JavaScript slugify utilities can do the diacritic-stripping work without a library.
The slugify Library Family, What Each Ecosystem Ships
Django's django.utils.text.slugify() has been in the Python framework since the early 2000s. It lowercases, strips characters not in [A-Za-z0-9_-], and replaces whitespace with hyphens. Since Django 1.9 (2015) an allow_unicode=True keyword switches to a Unicode-aware mode that preserves non-ASCII letters. It's the reference implementation that everyone else copies. In Node.js, Sindre Sorhus's @sindresorhus/slugify is the most-downloaded slugify package on npm, with millions of weekly downloads, features include human-readable separators, customisable replacements (so you can map & to and, @ to at), Unicode handling and locale-aware lowercase (Turkish dotted/dotless I, German ß → ss). For Python users not using Django, Val Neekman's python-slugify on PyPI wraps the unidecode transliteration library and adds slug-specific behaviour: regex word-splitting, replacement characters, max length, stop-word removal.
Other ecosystems follow the same pattern. PHP has Cocur's cocur/slugify on Packagist, used by Laravel and Symfony plugins, and Symfony itself ships an AsciiSlugger in symfony/string since version 5.0. Ruby on Rails uses String#parameterize, built into ActiveSupport since at least Rails 1.0; the friendly_id gem layers history-tracking and collision-handling on top. Go has gosimple/slug with locale tables for over eighty languages. Rust has the slug crate. Java has Apache Commons Text and slugify-jvm. The remarkable thing is how convergent the API is: input string in, slug string out, with the same handful of options, separator, max-length, lowercase, locale. Absolutool's tool sits in the same family but runs entirely in your browser, with no library to install.
WordPress: 43% of the Web Runs This Pipeline
WordPress is the single largest slug-emitting system on the web, it powers roughly 43% of all websites by W3Techs's 2026 survey, so its slug conventions effectively are the web's slug conventions for most readers. When a post is saved, WordPress auto-generates the slug from the title via sanitize_title() (which calls sanitize_title_with_dashes() for the default rewrite case): lowercase, strip HTML, decode entities, replace whitespace and most punctuation with hyphens, percent-encode unsafe characters, collapse adjacent hyphens, trim leading/trailing hyphens. If the result collides with an existing post's slug, WordPress appends -2, -3, and so on. The slug is editable in the post editor, once a post is published, changing the slug breaks every existing link unless the publisher sets up a redirect. WordPress historically did not transliterate non-ASCII characters by default; it percent-encoded them, which produced the famously ugly Cyrillic URLs like %D0%BF%D1%80%D0%B8... that plugins like Cyr-To-Lat were written to fix.
Beyond Latin: Transliteration for Cyrillic, CJK, Arabic
NFD only handles characters that decompose into ASCII base + combining marks. For non-Latin scripts, the slug pipeline needs transliteration: a mapping from each non-Latin character to its Latin-script equivalent. The canonical Python library is unidecode, originally a port of Sean M. Burke's Perl Text::Unidecode from 2001, which maps virtually every character in the Basic Multilingual Plane to a best-guess ASCII string: Москва → Moskva, Αθήνα → Athena. The CJK fallback is the controversial bit: unidecode uses Mandarin pinyin for all CJK characters because Chinese has the largest CJK character coverage, which produces nonsensical romanisations for Japanese (東京 → Dong Jing in pinyin, not Tokyo). Japanese-specific tools like pykakasi do the work of converting kanji + kana into proper rōmaji. The International Components for Unicode (ICU) library, maintained by the Unicode Consortium and IBM, provides a Transliterator API with named rule sets like Russian-Latin/BGN, Greek-Latin/UNGEGN, and Han-Latin that implement official romanisation standards. Absolutool's tool sits at the lighter end: it folds Latin diacritics via NFD and drops everything else. A user wanting a slugged Russian or Chinese title can run a separate transliteration step before pasting the text in.
URL Length Limits, Where the 2,000-Character Rule Comes From
There is no length limit specified by RFC 3986 itself, the URI syntax is unbounded. Every limit is practical. Internet Explorer historically capped URLs at 2,083 characters (a hard limit baked into the Trident engine), which is the origin of the widely cited "2,000 character" rule of thumb. Chrome, Firefox, Safari and modern Edge support URLs up to roughly 64,000 to 100,000+ characters in the address bar. Apache's LimitRequestLine defaults to 8,190 bytes for the entire request line; nginx's large_client_header_buffers default is 8 KB; IIS defaults to 4,096 bytes for the URL and 2,048 for the query string. RFC 9110 (HTTP/1.1, 2022) recommends in §4.1 that a server "ought to be capable of handling URIs of length 8,000 octets or longer" but stops short of mandating an upper bound. For slugs, what matters is that they are conventionally short (three to seven words, thirty to sixty characters) for SEO and shareability. Google's John Mueller has said in multiple Webmaster Hangouts that URL length itself is not a ranking signal, but long URLs may be truncated in search-result snippets, hurt click-through rates, and look unprofessional in social shares. Most slug generators expose a max-length option for this reason; this one defaults to unlimited and lets you set a cap.
Stop-Word Removal: Dense vs. Grammatical
Many slugify libraries offer optional stop-word removal, drop common short words (a, an, the, of, is, and, or, to, in, for, on) before assembling the slug. The rationale is that they add no SEO signal and pad the URL. So "The Best Way to Make a Cup of Tea" becomes best-way-make-cup-tea (5 tokens, 24 characters) instead of the-best-way-to-make-a-cup-of-tea (10 tokens, 35 characters). The trade-off: shorter and denser, but with occasional grammar collapse (how-to-be-good stripped to how-good loses meaning) and a risk of removing words that actually carry intent (art-of-war stripped to art-war). WordPress does not strip stop words by default (it's an opt-in plugin behaviour) and most modern slug generators leave it off by default and surface it as a checkbox. Yoast SEO for WordPress flags a slug containing stop words as a minor recommendation rather than an error. This generator does not strip stop words automatically, on the grounds that the publisher knows the title's intent better than a static word list does. If you want them gone, edit the output directly.
Slug Collisions: What CMSes Do When Two Posts Share a Title
When two posts auto-generate the same slug, "My Post" and "My-Post!" both produce my-post: the system has to resolve the conflict. The most common strategies: a numeric suffix (my-post-2, my-post-3) (predictable, never collides, but the suffix carries no semantic difference; a date prefix (2026-04-27/my-post)) works well for blog content and is the default in Jekyll, Hugo and most news sites; an author suffix (my-post-jane) (used by Medium and multi-author blogs; a random hash suffix (my-post-a3f9)) used by Stack Overflow, Notion and shortlinking systems, trading human readability for guaranteed uniqueness; or manual edit at publish time, editorially clean but rarely the default because it interrupts the flow. The pragmatic choice for most CMSes is the numeric suffix with manual editing as the escape hatch. Date-prefixed permalinks are popular for time-anchored content where the date is meaningful information.
SEO Impact: Slug as Minor but Visible Signal
Google's ranking documentation lists URL structure as a minor ranking signal, page content, backlinks, user-engagement signals and freshness all carry more weight. But URL words contribute, and they contribute visibly. Slug terms appear in the SERP snippet URL line under the title, which influences click-through rate even when the slug isn't itself ranked. Slug terms can appear bolded in the SERP if they match the user's query, extra visual weight. Anchor text from internal and external links often defaults to the URL when no link text is supplied, so a semantic slug becomes the link text and carries its keywords through inbound link equity. A/B tests across publishers consistently show that descriptive slugs increase CTR by single-digit percentages over opaque IDs. Backlinko's 2020 ranking-factors study (1.18 million SERPs analysed) found short URLs slightly outperformed long URLs at the top of SERPs.
There is one exception to the "more keywords = better" intuition: keyword stuffing. The September 2012 Exact-Match Domain (EMD) update specifically reduced credit for low-quality exact-match domains and slugs (cheap-life-insurance.com/buy-cheap-life-insurance), and Google has continued to discount keyword stuffing in URLs since. The 2026 takeaway: keyword presence in the slug helps modestly; keyword stuffing hurts. The single largest SEO win from a slug is not changing it after publish. Inbound links accumulate to a URL. Page authority compounds at the URL level. A 301 redirect preserves most but not all of the link equity, and only if the publisher actually sets the redirect up, many don't. The Berners-Lee "Cool URIs Don't Change" advice has direct SEO consequences: every slug change, even with a redirect, costs a small amount of authority that takes time to recover.
Slug Best Practices, Distilled
- Keep slugs short, three to five words, thirty to sixty characters, ideal for SERP snippet display.
- Include the target keywords once, in natural order, no stuffing.
- Use hyphens, never underscores. Google's tokenizer treats hyphens as word separators and underscores as joiners.
- Drop common stop words (the, a, of, to, and) when they add no value, but keep them when they carry meaning.
- Lowercase only, case-sensitive servers treat Page.html and page.html as different URLs.
- Never change a slug after publishing without setting up a 301 redirect, broken inbound links cost authority.
- Strip or transliterate non-ASCII characters unless your platform handles IRIs cleanly across analytics, social shares and email clients.
- Avoid dates unless the date is fundamental to the resource; avoid file extensions, session IDs, author names and status words.
Frequently Asked Questions
Does this handle accented characters?
Yes. The generator uses Unicode NFD normalisation to decompose accented letters into base + combining mark, then strips the marks. Café becomes cafe, naïve becomes naive, François becomes Francois. NFD doesn't fold characters that aren't decomposable into base+mark, German ß, Polish ł, Norwegian ø, Icelandic þ need explicit transliteration and won't be folded by this tool. Edit them manually if they appear in your input.
Should I use hyphens or underscores?
Hyphens, every time. Google engineer Matt Cutts confirmed in 2005, 2007 and 2011 (and Google's current URL best-practices page reaffirms) that hyphens are treated as word separators by the search tokenizer while underscores are word joiners. green-apples matches the query "green apples"; green_apples matches only the literal phrase "green_apples", which almost no real user types. Underscores are only kept in URLs for legacy programming reasons (__init__.py), they have no SEO upside.
What happens to emoji and symbols?
Emoji are not in the URL unreserved character set, and NFD doesn't decompose them, they have no Latin equivalent. This generator drops them. Other tools percent-encode emoji (turning a single character into a long string like %F0%9F%94%A5), which technically works in modern browsers but produces unreadable URLs in analytics, social shares and email previews. Most slug guides recommend stripping emoji entirely; if you want them preserved, percent-encode them upstream of the slug step.
Will this slugify Russian, Chinese or Arabic titles?
Not on its own. NFD only folds Latin-script accented characters; it can't transliterate Cyrillic, Greek, Arabic, Hebrew or CJK scripts to Latin. Pasting a Russian or Chinese title into this tool will drop those characters and produce an empty or near-empty slug. The right workflow is to run a transliteration step first (Python's unidecode, JavaScript's transliteration npm package, or Wikipedia's romanisation conventions) and paste the romanised result here. For Japanese specifically, use a kana-aware tool like pykakasi: generic CJK transliterators apply Mandarin pinyin and produce Dong Jing for 東京 rather than Tokyo.
What if I need to change a slug after publishing?
Set up a 301 redirect from the old URL to the new one before changing the slug. A 301 ("Moved Permanently") preserves most of the link equity that's accumulated to the old URL and tells crawlers and browsers to update their bookmarks. Without a redirect, every existing inbound link breaks and you lose the page authority those links represented. Even with a redirect, you lose a small amount of equity that takes weeks or months to recover. The Berners-Lee maxim (cool URIs don't change) is partly aesthetic, partly an SEO truth: every slug change costs something, so it's worth getting the slug right the first time.
Is there a recommended slug length?
Convention is three to seven words, roughly thirty to sixty characters. Long enough to be descriptive, short enough that Google's SERP snippet doesn't truncate it and humans can grasp the topic at a glance. There's no hard technical maximum (RFC 3986 doesn't specify one and modern browsers handle URLs in the tens of thousands of characters) but Apache, nginx and IIS impose practical caps in the kilobytes range, and the legacy "2,000 character" rule from Internet Explorer is still cited as a safe cross-platform ceiling. The Max Length option here lets you cap the output; setting it to 0 means unlimited.
Are my texts stored or sent anywhere?
No. The transformation runs entirely in your browser using JavaScript's built-in String.prototype.normalize() method (supported since Chrome 34, Firefox 31, Safari 10, roughly 2015). Nothing is uploaded, no API is called, no logs are written. You can verify this by opening your browser's DevTools Network tab while you generate slugs, there are no outbound requests. The page is safe for slugs derived from unpublished titles, internal documentation, draft posts or any other content you don't want leaving your device.