
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.
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
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
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")); // ❌
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")); // ❌
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!")); // ❌
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
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
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")); // ❌
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")); // ❌
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
⚠️ 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}$/;
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 |
|---|---|---|
^[^\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?
- Complete Regex Guide for JavaScript — capture groups, lookaheads, flags, all of it
- Next.js Server Actions Security Guide — where these patterns get used in real auth flows
- MDN Regular Expressions — the authoritative reference
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)