Skip to main content

Text to Slug

Generate URL-friendly slugs from any text.

Reviewed by · Last reviewed

How to Use the Text-to-Slug Generator

  1. Paste or type a phrase - a blog title, product name, category, or any piece of text you want to turn into a URL segment.
  2. Pick a separator: hyphen (-) for web URLs following SEO convention, or underscore (_) for systems that prefer it (Django URL patterns, some internal namespaces).
  3. Set a maximum length if the downstream field has a limit. Leave at 0 for unlimited. The tool truncates at the last complete word rather than mid-word.
  4. Toggle Transliterate accents if you want accented characters like café, naïve, or Zurich to become cafe, naive, zurich. Leave off to preserve Unicode in the slug (some modern CMSes support this).
  5. Read the slug output that updates on every keystroke, and click Copy to paste it into your CMS, router, or filename.

How the Slugification Works

The transformation runs in four passes. First, String.prototype.toLowerCase() lower-cases the entire input using the Unicode case-folding rules implemented by the browser. Second, if transliteration is on, the string is normalized with str.normalize("NFD") to decompose accented characters into base letter plus combining marks, then the combining marks (Unicode category Mn) are stripped with the regex /[\\u0300-\\u036f]/g. Third, a regex replaces runs of non-alphanumeric characters with the chosen separator: /[^a-z0-9]+/g when transliteration is on, or a looser Unicode-aware variant /[^\\p{L}\\p{N}]+/gu when it is off. Fourth, leading and trailing separators are trimmed. Length truncation happens last, cutting at a whole-word boundary when possible. Everything runs locally in the browser tab without any fetch call.

When You Would Generate a Slug

  • Creating a blog post URL: "How I Ship Astro Sites to Cloudflare Pages" becomes how-i-ship-astro-sites-to-cloudflare-pages.
  • Naming a GitHub issue branch from the title: issue/123-fix-jwt-expiry-check.
  • Generating a filename for a user-uploaded report: q1-2026-sales-analysis.pdf from "Q1 2026 Sales Analysis".
  • Building Kubernetes resource names where DNS-1123 compliance requires lowercase alphanumerics and hyphens only.
  • Creating a category or tag identifier for your CMS where the UI displays a friendly name but the URL needs a machine-safe form.
  • Producing anchor IDs for Markdown headings - many static site generators apply essentially this same transformation to build #section-id jump links.

Common Pitfalls and Edge Cases

  • Ambiguous transliteration. German ü can become u or ue depending on convention. This tool picks the ASCII-closest form (ü becomes u). If your audience expects ü becomes ue (a common German transliteration), adjust the output manually.
  • Non-Latin scripts. Cyrillic, Arabic, Hebrew, Chinese, Japanese, and Korean text do not decompose to Latin via NFD. With transliteration off, the tool preserves them as-is (requires a modern CMS); with transliteration on, they are stripped leaving an empty slug. For proper transliteration across scripts, use a dedicated library like slugify or iuliia (for Cyrillic).
  • Numbers. Digits are preserved. A title like "2026 Outlook" becomes 2026-outlook. That is usually what you want for dated content.
  • Apostrophes. "Bob's Burgers" becomes bobs-burgers (apostrophe stripped, no separator added). Straight and curly apostrophes (U+2019) are both handled.
  • Reserved URL characters. Characters like ?, #, &, % are always stripped because they have structural meaning in URLs and would break routing.
  • Double separators. Runs of non-alphanumerics collapse to a single separator, so "Hello - World" becomes hello-world not hello---world.

Why Slugs Exist

The URL path was standardized in RFC 3986 (2005) with strict rules about which characters are allowed unencoded. Spaces must be percent-encoded (%20), reserved characters (: / ? # [ ] @ ! $ & ' ( ) * + , ; =) have structural meaning, and Unicode characters are allowed via the IRI spec (RFC 3987) but not universally supported by legacy tools. Slugs emerged as a pragmatic convention: use only [a-z0-9-] and you avoid every percent-encoding question entirely. The term "slug" comes from newspaper publishing, where the slug was the short name on a story used during layout before the headline was finalized. WordPress popularized the term for web URLs in the 2000s. Kubernetes resource names follow DNS-1123 label rules (lowercase, alphanumerics, hyphens, 63 chars max, must start and end with alphanumeric), which is essentially the same set.

Comparison to Alternatives

npm has several popular slugify libraries: slugify (supports locale-specific transliteration), url-slug, and @sindresorhus/slugify. Python has python-slugify and Django's built-in slugify filter. Ruby on Rails has parameterize. PostgreSQL has no built-in but the unaccent extension is commonly chained with regexp_replace to achieve the same effect in SQL. For static-site build-time generation, Astro, Next.js, and Gatsby all have plugins that automatically slugify filenames or front-matter titles. Use this web tool when you need one slug now and do not want to write a one-liner - especially handy when pasting from a rich-text editor that may have introduced smart quotes or invisible characters you would miss in a CLI script.

Frequently Asked Questions

What characters are allowed in a slug?

With transliteration on, the output uses only lowercase a-z, digits 0-9, and the chosen separator. With transliteration off, any Unicode letter (\p{L}) or number (\p{N}) survives, producing Unicode slugs that modern browsers, frameworks, and search engines accept. Reserved URL characters from RFC 3986 are always stripped regardless of the transliteration setting because they would otherwise corrupt the URL path parsing.

Should I prefer hyphens or underscores?

Google's webmaster guidelines explicitly recommend hyphens because they are interpreted as word separators, whereas underscores are treated as part of a single word. For SEO that usually matters. However, Python modules, CLI tools, and some CMS internal identifiers prefer underscores as a convention. For public-facing URLs pick hyphens; for internal keys match whatever your framework expects. Kubernetes resource names, for instance, require hyphens and reject underscores entirely.

Is my text sent to a server?

No. The transformation is a pure JavaScript function running in your browser tab. String.prototype.normalize, String.prototype.toLowerCase, String.prototype.replace, and the regex constructor are all native browser APIs with no network dependencies. There is no fetch call, no analytics capture, and no service worker caching the input. Closing the tab releases the text from memory.

How does the tool handle Cyrillic or Chinese text?

Unicode Normalization Form D (NFD) decomposes accented Latin characters but does not transliterate non-Latin scripts. With transliteration on, a Cyrillic or Chinese title ends up stripped of all letters and produces an empty slug. With transliteration off, the Unicode letters pass through and you get a slug like "привет-мир". For proper script conversion (Russian to Latin, Japanese romaji, Chinese pinyin) use a language-aware library like iuliia, kuroshiro, or pypinyin - none of that logic is in this tool.

What should the max length be?

If you have no constraint, zero (unlimited) is fine. Common targets: 63 characters for Kubernetes DNS-1123 labels, 100 characters for most CMSes with sensible defaults, 255 characters if you are filling a default VARCHAR column. For SEO readability, aim below 60 characters because search engines truncate long URLs in SERP display. Choose whatever the downstream target requires and let the tool truncate at a whole-word boundary.

Do slugs need to be globally unique?

Only as unique as your routing requires. For a blog, slugs must be unique within the same collection; two different years can reuse the same slug if the URL includes the year. Many CMSes auto-suffix duplicates with a counter (my-post, my-post-2). If you need both uniqueness and readability, slug + short random suffix is a common pattern: my-post-a3b9. This tool does not add uniqueness suffixes - add them in your application code.

Can the slug start or end with the separator?

No. The trim step removes leading and trailing separators unconditionally, because URLs with leading slashes already serve that role, and trailing separators are widely considered ugly. If your title is "---Special Offer---", the slug is special-offer with no leading or trailing hyphens.

What happens with pure emoji input?

With transliteration on, emoji are stripped (they are not a-z or 0-9) and you get an empty slug. With transliteration off and the Unicode regex path, emoji still do not match \p{L} or \p{N} and are also stripped. For emoji-heavy titles, either accept the emoji-free slug or pre-process with an emoji-to-name library like node-emoji that converts 😀 to :smile: first, which then slugifies to smile.

How does this differ from anchor-ID generation in static site generators?

Astro, Next.js, Gatsby, and Hugo all generate anchor IDs for headings using an algorithm very similar to this tool. The difference is that heading IDs often preserve a bit more Unicode by default (they are not URL paths, they are fragment identifiers which are more permissive) and some generators include a numeric suffix for duplicate headings. For SSG auto-generated IDs, let the framework handle it; for one-off URL slugs, this tool is the right fit.

Why does my slug come out shorter than I expected?

Three common causes. First, punctuation and spaces collapse to a single separator, reducing length. Second, transliteration drops characters that do not map to Latin - Arabic and Chinese in particular leave very short residue. Third, if max length is set, the truncation cuts at the last complete word before the limit, which may drop more characters than you expected. Increase the max length or disable transliteration depending on your goal.

More Text Tools