DEV Community

Muhammad Awais
Muhammad Awais

Posted on • Originally published at webtoolshub.online

10 Regex Patterns Every JavaScript Developer Should Know (2026)

10 Regex Patterns Every JavaScript Developer Should Know (2026)
You're halfway through building a signup form. Email field. Phone field. Password field.

And suddenly you're Googling "email validation regex javascript" for the 40th time this year — copying a Stack Overflow answer from 2018, crossing your fingers, and moving on.

I've done this. On production projects. That's embarrassing to admit, but it's also why I finally built a proper reference — one I actually understand, not just copy-paste blindly.

These are the 10 regex patterns I reach for constantly in JavaScript projects. Each one is copy-paste ready, explained properly, and tested against real edge cases.


What You'll Learn

  • 10 production-ready regex patterns with copy-paste JS code
  • What each pattern actually does — no cryptic symbol blindness
  • Edge cases that will bite you if you skip them
  • Common mistakes that ship to production every single day

Quick Method Reference

Before the patterns — the three methods you'll use 90% of the time:

/pattern/.test(str)          // → true/false. Use for validation.
str.match(/pattern/g)        // → array of matches. Use for extraction.
str.replace(/pattern/, 'x')  // → new string. Use for sanitization.
Enter fullscreen mode Exit fullscreen mode

That's genuinely all you need. Let's get into the patterns.


1. Email Validation

This is the one everyone needs and everyone gets slightly wrong.

const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

function isValidEmail(email) {
  return emailRegex.test(email.trim());
}

console.log(isValidEmail("user@example.com"));    // ✅ true
console.log(isValidEmail("user+tag@company.co")); // ✅ true — plus sign works
console.log(isValidEmail("notanemail"));           // ❌ false
console.log(isValidEmail("missing@tld"));          // ❌ false
Enter fullscreen mode Exit fullscreen mode

What [^\s@]+ does: Matches one or more characters that are NOT a space or @. Simple, readable, and handles edge cases like plus-sign aliases (user+filter@gmail.com) and long TLDs like .photography — things that trip up overcomplicated RFC-5322 patterns.

⚠️ Important: Regex validates format, not deliverability. It can't tell you if the mailbox actually exists. For that, use a verification API or just send a confirmation email.


2. Password Strength (with Lookaheads)

Most auth systems need: 8+ characters, one uppercase, one lowercase, one digit, one special character. Here's the pattern using lookaheads:

const strongPasswordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*()_+\-=\[\]{}|;:,.<>?]).{8,}$/;
const mediumPasswordRegex = /^(?=.*[A-Z])(?=.*\d).{8,}$/;

function checkPasswordStrength(password) {
  if (strongPasswordRegex.test(password)) return "strong";
  if (mediumPasswordRegex.test(password)) return "medium";
  return "weak";
}

console.log(checkPasswordStrength("Passw0rd!"));  // strong
console.log(checkPasswordStrength("Password1"));  // medium
console.log(checkPasswordStrength("password"));   // weak
Enter fullscreen mode Exit fullscreen mode

How lookaheads work: (?=.*[A-Z]) says "look ahead and confirm at least one uppercase letter exists somewhere in the string" — without consuming characters. Each (?=...) is a separate requirement. The final .{8,} enforces minimum length.

⚠️ bcrypt gotcha: bcrypt silently truncates passwords at 72 bytes. If users set 100-character passphrases, only the first 72 characters are actually hashed. Worth mentioning in your security docs.


3. URL Validation

const urlRegex = /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&/=]*)$/;

console.log(urlRegex.test("https://webtoolshub.online"));          // ✅
console.log(urlRegex.test("https://sub.domain.co.uk/path?q=1"));  // ✅
console.log(urlRegex.test("ftp://not-http.com"));                   // ❌
console.log(urlRegex.test("just-text"));                            // ❌
Enter fullscreen mode Exit fullscreen mode

Honest take: For complex URL parsing in production, use the built-in URL constructor — new URL(str) throws if invalid, easier to handle with try/catch. The regex is perfect for quick form validation.


4. Phone Number (International)

Phone numbers are where regex ambitions go to die. No single regex perfectly handles every international format. Here's what I actually use:

// Flexible — strip formatting first, then validate digit count
function isValidPhone(phone) {
  const digitsOnly = phone.replace(/[\s\-().+]/g, "");
  return /^\d{7,15}$/.test(digitsOnly);
}

console.log(isValidPhone("+92 300 1234567"));  // ✅
console.log(isValidPhone("(555) 867-5309"));   // ✅
console.log(isValidPhone("123"));              // ❌
Enter fullscreen mode Exit fullscreen mode

Real talk: Strip non-digits first, count the digits, move on. Users type phone numbers in wildly different formats. This handles 95% of real-world input better than any strict pattern.


5. URL Slug (SEO-Friendly)

Essential for any CMS, blog, or content platform. A slug: lowercase letters, numbers, hyphens only.

const slugRegex = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;

function slugify(text) {
  return text
    .toLowerCase()
    .trim()
    .replace(/[^\w\s-]/g, "")   // remove special chars
    .replace(/[\s_-]+/g, "-")   // spaces/underscores → hyphens
    .replace(/^-+|-+$/g, "");   // trim leading/trailing hyphens
}

console.log(slugify("My Blog Post Title!"));       // "my-blog-post-title"
console.log(slugify("  TypeScript & Next.js  "));  // "typescript-nextjs"
console.log(slugRegex.test("valid-slug-123"));      // ✅
console.log(slugRegex.test("Invalid Slug!"));       // ❌
Enter fullscreen mode Exit fullscreen mode

The slugify function is more useful than just the validation regex — I use it everywhere in Next.js projects when auto-generating routes from titles.


6. Hex Color Code

For color pickers, CSS parsers, and theme generators. Handles 3-digit and 6-digit formats:

const hexColorRegex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/;

// With alpha channel (8-digit and 4-digit)
const hexWithAlphaRegex = /^#([A-Fa-f0-9]{8}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{4}|[A-Fa-f0-9]{3})$/;

console.log(hexColorRegex.test("#fff"));       // ✅
console.log(hexColorRegex.test("#FF5733"));    // ✅
console.log(hexColorRegex.test("FF5733"));     // ❌ — missing #
console.log(hexColorRegex.test("#GGGGGG"));    // ❌ — G isn't hex
Enter fullscreen mode Exit fullscreen mode

7. Date Format (ISO: YYYY-MM-DD)

What every API expects, what databases prefer. This validates format — not date logic:

const isoDateRegex = /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/;

// For logic validation, combine with Date constructor
function isValidDate(str) {
  if (!isoDateRegex.test(str)) return false;
  const d = new Date(str);
  return d instanceof Date && !isNaN(d);
}

console.log(isValidDate("2026-06-13")); // ✅
console.log(isValidDate("2026-02-30")); // ❌ — Feb 30 caught by Date constructor
console.log(isValidDate("2026-13-01")); // ❌ — month 13 caught by regex
Enter fullscreen mode Exit fullscreen mode

Always use both: Regex catches format errors; new Date() catches impossible dates like Feb 30.


8. Username Validation

Standard rules: 3-20 characters, letters, numbers, underscores, hyphens — no spaces.

const usernameRegex = /^[a-zA-Z0-9_-]{3,20}$/;

// Stricter — must start with a letter
const strictUsernameRegex = /^[a-zA-Z][a-zA-Z0-9_-]{2,19}$/;

console.log(usernameRegex.test("muhammad_awais")); // ✅
console.log(usernameRegex.test("dev-42"));         // ✅
console.log(usernameRegex.test("ab"));             // ❌ — too short
console.log(usernameRegex.test("has spaces"));     // ❌
Enter fullscreen mode Exit fullscreen mode

Adjust {3,20} to your requirements. The strict version prevents usernames like _admin — cleaner in URLs and @mentions.


9. IPv4 Address (Strict)

Basic patterns let 999.0.0.1 through. This one properly validates each octet (0-255):

const ipv4Regex = /^(25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.(25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.(25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.(25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)$/;

console.log(ipv4Regex.test("192.168.1.1"));   // ✅
console.log(ipv4Regex.test("255.255.255.0")); // ✅
console.log(ipv4Regex.test("999.0.0.1"));     // ❌
console.log(ipv4Regex.test("192.168.1"));     // ❌
Enter fullscreen mode Exit fullscreen mode

How the octet math works: 25[0-5] → 250-255 | 2[0-4]\d → 200-249 | 1\d{2} → 100-199 | [1-9]\d → 10-99 | \d → 0-9. Always use the strict version — bad IPs cause cryptic downstream errors.


10. Credit Card Format

Format-only validation. For real validation, always combine with the Luhn algorithm:

const creditCardRegex = /^\d{13,19}$/;

const cardTypes = {
  visa:       /^4\d{12}(?:\d{3})?$/,
  mastercard: /^5[1-5]\d{14}$/,
  amex:       /^3[47]\d{13}$/,
  discover:   /^6(?:011|5\d{2})\d{12}$/,
};

function identifyCard(number) {
  const stripped = number.replace(/[\s\-]/g, "");
  if (!creditCardRegex.test(stripped)) return "invalid";
  for (const [type, regex] of Object.entries(cardTypes)) {
    if (regex.test(stripped)) return type;
  }
  return "unknown";
}

console.log(identifyCard("4111 1111 1111 1111")); // visa
console.log(identifyCard("5500 0000 0000 0004")); // mastercard
console.log(identifyCard("1234 5678"));           // invalid
Enter fullscreen mode Exit fullscreen mode

⚠️ Production rule: Use a payment processor (Stripe, etc.) for actual card validation. Never store raw card numbers.


Common Mistakes That Ship to Production

I've made all of these. Some of them twice.

1. Forgetting ^ and $ anchors

Without anchors, your pattern matches anywhere in the string.

// ❌ Wrong — matches "I have 1234 in the middle"
const badPin = /\d{4}/;

// ✅ Correct — only matches exactly 4 digits
const goodPin = /^\d{4}$/;
Enter fullscreen mode Exit fullscreen mode

2. Not escaping the dot

In regex, . means "any character". So example.com as a pattern also matches exampleXcom. Always escape: example\.com.

3. Catastrophic backtracking

Nested quantifiers like /(a+)+/ can hang your regex engine on long strings (ReDoS attack). Avoid nesting + or * inside groups that already have + or *.

4. Missing the i flag for case-insensitive matching

Email addresses are case-insensitive. User@Example.COM is the same mailbox as user@example.com. Use /pattern/i or normalize with .toLowerCase() first.

5. Using regex to parse HTML

Don't. Use DOMParser in the browser or cheerio in Node. Regex and HTML is a well-documented disaster.


Quick Reference Table

Use Case Pattern Flag
Email ^[^\s@]+@[^\s@]+\.[^\s@]+$ i
Strong Password ^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*]).{8,}$
URL ^https?:\/\/(www\.)?[-\w@:%._+~#=]{1,256}\.[a-zA-Z]{1,6} i
Phone Strip non-digits → ^\d{7,15}$
URL Slug ^[a-z0-9]+(?:-[a-z0-9]+)*$
Hex Color `^#([A-Fa-f0-9]{6}\ [A-Fa-f0-9]{3})$`
ISO Date `^\d{4}-(0[1-9]\ 1[0-2])-(0[1-9]\
Username {% raw %}^[a-zA-Z0-9_-]{3,20}$
IPv4 `^(25[0-5]\ 2[0-4]\d\
Credit Card Strip spaces → {% raw %}^\d{13,19}$

Test These Live

Before you ship any pattern, spend 2 minutes testing it. I use WebToolsHub's free Regex Tester — paste the pattern, add test strings including intentionally bad ones, see matches highlighted in real time. Everything runs in your browser, nothing gets sent to a server.

This two-minute habit has saved me from broken validation in production more times than I want to count.


Want to Go Deeper?


All tools on WebToolsHub are 100% client-side — no data is sent to any server. Your patterns and test strings stay in your browser.

Top comments (0)