URL Slug Regex
Validates a URL-friendly slug made of lowercase letters and digits, with single hyphens allowed only between word groups (no leading, trailing, or doubled hyphens).
Regex Pattern
^[a-z0-9]+(?:-[a-z0-9]+)*$Pattern Breakdown
Hover over a token to see what it does.
| Token | Meaning |
|---|---|
| ^ | Anchors the match to the start of the string |
| [a-z0-9]+ | One or more lowercase letters or digits forming the first word |
| (?: | Start of a non-capturing group for repeated hyphen-separated words |
| -[a-z0-9]+ | A literal hyphen followed by one or more lowercase letters/digits |
| )* | Closes the group and allows it to repeat zero or more times |
| $ | Anchors the match to the end of the string |
Detailed Explanation
What it does
This pattern matches strings that follow the classic 'slug' convention used in blog and product URLs: lowercase alphanumeric words joined by single hyphens, such as my-blog-post-123. It rejects uppercase letters, spaces, underscores, and malformed hyphen placement.
Why it works
The pattern requires an initial run of lowercase letters/digits, then allows the non-capturing group (?:-[a-z0-9]+)* to repeat for each additional hyphen-joined word. Because each repetition of the group demands a hyphen immediately followed by at least one alphanumeric character, two consecutive hyphens or a hyphen at the start/end of the string can never satisfy the pattern, and the ^/$ anchors ensure the whole string is checked.
Common use cases
- Validating slugs before saving them to a database or using them in a route
- Auto-generating and then verifying SEO-friendly URLs from article titles
- Enforcing consistent slug formatting in a CMS or static site generator
- Sanitizing user-submitted permalink overrides
Edge cases
- A single word with no hyphens, like hello, is valid since the repeating group is optional
- Purely numeric slugs like 2026-07-10 are valid because digits are allowed alongside letters
- Double hyphens (hello--world) are correctly rejected because the group requires an alphanumeric character right after each hyphen
- Leading or trailing hyphens (-hello, hello-) are rejected since the string must start and end with an alphanumeric character
Limitations
- Does not transliterate or normalize accented/Unicode characters — that must happen before validation
- Does not enforce a maximum length, so extremely long slugs will still pass
- Cannot detect semantically reserved slugs (e.g. 'admin' or 'api') — that needs an application-level check
Interactive Tester
Edit the pattern or text below — matching runs live in your browser.
Test Cases
Editable — add your own inputs to see if they pass.
| Input | Expected | Result | |
|---|---|---|---|
| Pass | |||
| Pass | |||
| Pass | |||
| Pass | |||
| Pass | |||
| Pass | |||
| Pass | |||
| Pass |
Language Variants
Production-ready examples in 12 languages.
const slugRegex = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
console.log(slugRegex.test('my-blog-post-123')); // trueCommon Mistakes
Using [a-z0-9-]+ without structure, which allows leading, trailing, and doubled hyphens like --hello--
Fix: Use the (?:-[a-z0-9]+)* structure so every hyphen is guaranteed to be followed by an alphanumeric character
Forgetting to lowercase and trim the source string before generating a slug
Fix: Normalize the input (toLowerCase, trim, replace spaces with hyphens) before running it through the validation regex
Not stripping accented characters, producing slugs like 'caf-au-lait' that lose information
Fix: Transliterate Unicode characters (e.g. e with an accent becomes e) before slugifying
Performance Notes
- The pattern has no ambiguous overlap between the initial class and the repeated group, so it runs in linear time with no catastrophic backtracking risk
- Anchors (^ and $) let the engine reject invalid strings immediately without scanning the whole input for a partial match
- For slugifying large batches of titles, generate the slug first (lowercase, replace spaces) and use this regex only as a final validation gate
Browser Compatibility
| Engine | Supported | Notes |
|---|---|---|
| Chrome | Yes | — |
| Firefox | Yes | — |
| Safari | Yes | — |
| Edge | Yes | — |
| Node.js | Yes | — |