10 Regex Patterns Every JavaScript Developer Should Know (2026)
Author
Muhammad Awais
Published
June 13, 2026
Reading Time
14 min read
Views
14k

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 too. Multiple times. On production projects. That's embarrassing to admit, but it's also why I finally sat down and built a proper reference one I actually understand, not just copy-paste blindly.
These are the 10 common regex patterns I reach for constantly in JavaScript projects. Each one is copy-paste ready, explained properly, and tested against real edge cases. And if you want to test any of these patterns live without writing a single line of code, our free Regex Tester tool lets you do exactly that right in your browser, no data sent anywhere.
What You'll Learn
10 production-ready regex patterns with copy-paste JavaScript 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
How to test any pattern live before committing it to your codebase
What Is a Regex Pattern? (Fast Version)
A regular expression is a sequence of characters that defines a search pattern. In JavaScript, you write them between forward slashes: /pattern/flags. You use them with methods like .test(), .match(), and .replace().
The three methods you'll use 90% of the time:
/pattern/.test(str)— Returnstrueorfalse. Use this for validation.str.match(/pattern/g)— Returns an array of all matches. Use this for extraction.str.replace(/pattern/, 'replacement')— Swaps matches. Use this for sanitization.
That's genuinely all you need to understand the 10 patterns below. Let's get into it.
Pattern 1 - Email Validation
This is the one everyone needs and everyone gets slightly wrong. Here's the pattern I use in production:
const emailRegex = /^[^s@]+@[^s@]+.[^s@]+$/;
// Usage
function isValidEmail(email) {
return emailRegex.test(email.trim());
}
console.log(isValidEmail("user@example.com")); // true
console.log(isValidEmail("user+tag@company.co")); // true
console.log(isValidEmail("notanemail")); // false
console.log(isValidEmail("missing@tld")); // false
What this does: [^s@]+ means "one or more characters that are NOT a space or @". Simple, readable, and it handles the edge cases that trip up overcomplicated RFC-5322 patterns like plus signs in Gmail addresses (user+filter@gmail.com) and longer TLDs like .photography.
Important: Regex validates format, not deliverability. It can't tell you if the mailbox actually exists. For that, you need a verification API or simply send a confirmation email. Don't over-engineer the regex trying to do something it structurally can't do.
If you want to test this with your own email addresses before putting it in code, try our Regex Tester tool paste the pattern and your test strings, see matches highlighted instantly.
Pattern 2 - Password Strength
Most auth systems need at least: 8 characters, one uppercase, one lowercase, one number, one special character. Here's the pattern using lookaheads probably the most useful regex feature for password validation:
const strongPasswordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*d)(?=.*[!@#$%^&*()_+-=[]{}|;:,.<>?]).{8,}$/;
// Medium strength — only requires length + one number + one uppercase
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]) means "at this position, look ahead and check that at least one uppercase letter exists somewhere". Each (?=...) is a separate check all of them must pass. The final .{8,} sets minimum length. Clean, readable once you know the trick.
Edge case to watch: bcrypt which is what you should be using to store passwords silently truncates at 72 bytes. If your users set 100-character passphrases, only the first 72 count. Mention this in your security docs. Speaking of bcrypt, our free Bcrypt Hash Generator lets you hash and verify passwords right in the browser.
Pattern 3 - URL Validation
URLs are tricky. They come in a dozen valid formats. Here's a pattern that handles the 99% case without exploding for edge cases:
const urlRegex = /^(https?://)([w-]+.)+[w-]+(/[w-._~:/?#[]@!$&'()*+,;=]*)?$/i;
// Quick version — more permissive, good for most forms
const simpleUrlRegex = /^https?://(www.)?[-a-zA-Z0-9@:%._+~#=]{1,256}.[a-zA-Z0-9()]{1,6}([-a-zA-Z0-9()@:%_+.~#?&/=]*)$/;
console.log(simpleUrlRegex.test("https://webtoolshub.online")); // true
console.log(simpleUrlRegex.test("https://sub.domain.co.uk/path?q=1")); // true
console.log(simpleUrlRegex.test("ftp://not-http.com")); // false
console.log(simpleUrlRegex.test("just-text")); // false
My honest take: For complex URL parsing in production, use the built-in URL constructor instead new URL(str) throws if the URL is invalid, which is easier to handle with try/catch. The regex above is perfect for quick form validation or search-and-replace operations.
Pattern 4 - Phone Number (International)
Phone numbers are where regex ambitions go to die. There is no single regex that perfectly validates every international format. Here's what I actually use:
// International format with optional country code
const phoneRegex = /^+?[1-9]d{6,14}$/;
// US-specific (more strict)
const usPhoneRegex = /^(+1[-.s]?)?(?d{3})?[-.s]?d{3}[-.s]?d{4}$/;
// Flexible — strips formatting first, then validates digit count
function isValidPhone(phone) {
const digitsOnly = phone.replace(/[s-().+]/g, "");
return /^d{7,15}$/.test(digitsOnly);
}
console.log(isValidPhone("+92 300 1234567")); // true
console.log(isValidPhone("(555) 867-5309")); // true
console.log(isValidPhone("123")); // false
Real talk: The flexible version strip non-digits first, then validate digit count handles 95% of real user input better than any strict pattern. Users type phone numbers in wildly different formats. Strip the formatting, count the digits, move on. Save the strict pattern for when you specifically need E.164 format for an SMS API.
Pattern 5 - URL Slug (SEO-Friendly)
If you're building a CMS, blog, or any content platform, you need this. A slug should be lowercase letters, numbers, and hyphens nothing else:
const slugRegex = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
// The slugify function — converts any string to a valid slug
function slugify(text) {
return text
.toLowerCase()
.trim()
.replace(/[^ws-]/g, "") // remove special chars
.replace(/[s_-]+/g, "-") // spaces and underscores to 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")); // true
console.log(slugRegex.test("Invalid Slug!")); // false
I use the slugify function almost everywhere it's more useful than just the validation regex alone. If you're building a Next.js app and generating slugs for routes, this combo saves you from encoding issues and broken URLs later.
Pattern 6 - Hex Color Code
Useful for color pickers, design tools, CSS parsers, and theme generators. This pattern accepts both 3-digit and 6-digit hex with optional alpha channel:
// 3-digit and 6-digit hex (with optional #)
const hexColorRegex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/;
// Includes 4-digit and 8-digit (with alpha channel)
const hexColorWithAlphaRegex = /^#([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")); // true
console.log(hexColorRegex.test("#FF5733")); // true
console.log(hexColorRegex.test("FF5733")); // false — missing #
console.log(hexColorRegex.test("#GGGGGG")); // false — G is not hex
console.log(hexColorWithAlphaRegex.test("#FF573380")); // true — 8-digit with alpha
I built this pattern when working on a Shadcn theme generator. Users kept pasting hex codes without the #, so I added a quick normalization step check for the hash, add it if missing, then validate. If you're working with Tailwind or Shadcn themes, our Shadcn Theme Generator might save you some time too.
Pattern 7 - Date Format (YYYY-MM-DD)
ISO date format is what every API expects and what databases prefer. This pattern validates the format not the date logic:
const isoDateRegex = /^d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]d|3[01])$/;
console.log(isoDateRegex.test("2026-06-13")); // true
console.log(isoDateRegex.test("2026-13-01")); // false — month 13 invalid
console.log(isoDateRegex.test("2026-02-30")); // true — regex can't catch this
console.log(isoDateRegex.test("06/13/2026")); // false — wrong format
Critical caveat: 2026-02-30 passes this regex because regex can't know that February doesn't have 30 days. Always follow up with new Date(str) and check if the result is a valid date object. The regex handles format; JavaScript's Date handles logic.
function isValidDate(str) {
if (!isoDateRegex.test(str)) return false;
const d = new Date(str);
return d instanceof Date && !isNaN(d);
}
console.log(isValidDate("2026-02-30")); // false — properly caught now
console.log(isValidDate("2026-06-13")); // true
Pattern 8 - Username Validation
Username rules vary by app, but the standard: 3-20 characters, letters, numbers, underscores, hyphens no spaces, no special characters:
const usernameRegex = /^[a-zA-Z0-9_-]{3,20}$/;
// Stricter version — must start with a letter
const strictUsernameRegex = /^[a-zA-Z][a-zA-Z0-9_-]{2,19}$/;
console.log(usernameRegex.test("muhammad_awais")); // true
console.log(usernameRegex.test("dev-42")); // true
console.log(usernameRegex.test("ab")); // false — too short
console.log(usernameRegex.test("has spaces")); // false
console.log(usernameRegex.test("has!special")); // false
Adjust the {3,20} range to match your app's requirements. The strict version prevents usernames like _admin or 123user worth considering if usernames are user-facing (they look cleaner in URLs and @mentions).
Pattern 9 - IPv4 Address
Needed for network tools, server config validators, and log parses. A proper IPv4 pattern validates each octet (0-255):
// Basic — doesn't validate range (lets 999.999.999.999 through)
const basicIpRegex = /^(d{1,3}.){3}d{1,3}$/;
// Strict — validates each octet is 0-255
const strictIpv4Regex = /^(25[0-5]|2[0-4]d|1d{2}|[1-9]d|d).(25[0-5]|2[0-4]d|1d{2}|[1-9]d|d).(25[0-5]|2[0-4]d|1d{2}|[1-9]d|d).(25[0-5]|2[0-4]d|1d{2}|[1-9]d|d)$/;
console.log(strictIpv4Regex.test("192.168.1.1")); // true
console.log(strictIpv4Regex.test("255.255.255.0")); // true
console.log(strictIpv4Regex.test("999.0.0.1")); // false
console.log(strictIpv4Regex.test("192.168.1")); // false — incomplete
The strict version looks verbose but it's doing real math: 25[0-5] matches 250-255, 2[0-4]d matches 200-249, 1d{2} matches 100-199, and so on. Use the strict version the basic one will let through invalid IPs that will cause cryptic errors downstream.
Pattern 10 - Credit Card Format
This is format-only validation it won't tell you if the card is valid or has funds. For format, the key is: 13-19 digits, optionally separated by spaces or hyphens:
// Format validation (strips spaces/hyphens first)
const creditCardRegex = /^d{13,19}$/;
// With spaces or hyphens allowed
const creditCardFormattedRegex = /^[ds-]{13,23}$/;
// Visa, Mastercard, Amex, Discover prefix validation
const cardTypeRegex = {
visa: /^4d{12}(?:d{3})?$/,
mastercard: /^5[1-5]d{14}$/,
amex: /^3[47]d{13}$/,
discover: /^6(?:011|5d{2})d{12}$/,
};
function validateCard(cardNumber) {
const stripped = cardNumber.replace(/[s-]/g, "");
if (!creditCardRegex.test(stripped)) return "invalid";
for (const [type, regex] of Object.entries(cardTypeRegex)) {
if (regex.test(stripped)) return type;
}
return "unknown card type";
}
console.log(validateCard("4111 1111 1111 1111")); // "visa"
console.log(validateCard("5500 0000 0000 0004")); // "mastercard"
console.log(validateCard("1234 5678")); // "invalid"
Always use the Luhn algorithm alongside this for real card validation it mathematically checks if the card number is structurally valid before making any API calls. And in production, always use a payment processor like Stripe for actual validation never store raw card numbers yourself.
Common Regex Mistakes That Ship to Production
I've made all of these. At least once. Some of them twice.
1. Forgetting anchors (^ and $)
Without ^ (start) and $ (end), your pattern matches anywhere in the string. /d{4}/ matches "abc1234xyz" probably not what you want for a 4-digit PIN. Always anchor validation patterns.
// Wrong — matches "I have 1234 in the middle"
const badPinRegex = /d{4}/;
// Correct — only matches exactly 4 digits
const goodPinRegex = /^d{4}$/;
2. Not escaping the dot
In regex, . means "any character". So example.com as a regex pattern would also match exampleXcom. Escape it: example.com.
3. Catastrophic backtracking
Nested quantifiers like /(a+)+/ can cause your regex engine to hang on long strings this is called ReDoS (Regular Expression Denial of Service). Avoid nesting + or * inside groups that also have + or *.
4. Case sensitivity
Forgetting the i flag when you need case-insensitive matching. Email addresses should be compared case-insensitively User@Example.COM is the same as user@example.com. Use /pattern/i or .toLowerCase() before testing.
5. Using regex for HTML parsing
Don't. Just don't. Use DOMParser in the browser or cheerio in Node. Regex and HTML together is a well-documented path to madness.
Quick Reference Table
Here's everything at a glance copy the pattern you need and test it in our Regex Tester:
Use Case | Pattern | Flags |
|---|---|---|
|
| |
Strong Password |
| — |
URL (https) |
|
|
Phone (flexible) | Strip non-digits → | — |
URL Slug |
| — |
Hex Color |
|
|
ISO Date |
| — |
Username |
| — |
IPv4 Address |
| — |
Credit Card Format | Strip spaces → | — |
How to Test These Patterns Without Writing Code
The fastest way to verify a regex before shipping it is to test it live. Our Regex Tester & Debugger runs entirely in your browser paste any pattern from this list, add your test strings, and see matches highlighted in real time. No account, no data sent anywhere, completely free.
Here's how I use it during development:
Copy the regex pattern from this guide (or one I found elsewhere)
Paste it into the tester with 5-6 test strings including intentionally bad ones
Verify the pattern matches exactly what I expect and rejects what I don't
Only then copy it into my codebase
This two-minute habit has saved me from shipping broken validation at least a dozen times. The visual match highlighting makes edge cases obvious in a way that staring at console.log(true) just doesn't.
For deeper learning on how these patterns work under the hood including capture groups, lookaheads, and flags our complete Regex guide for JavaScript covers all of it with worked examples.
Privacy & Security Note
All tools on WebToolsHub including the Regex Tester, Bcrypt Generator, and JWT Decoder run 100% client-side. Nothing you type is sent to a server or logged anywhere. This matters especially when you're testing patterns against real data like email lists or authentication tokens.
Conclusion
Regex isn't magic. Each of these 10 patterns is built from the same small set of building blocks character classes, quantifiers, anchors, and lookaheads. Once you understand what each symbol actually does, you stop copy-pasting blindly and start writing patterns you can actually debug when they break at 2am.
Bookmark this page. Copy the patterns you need. And before you ship any of them, spend two minutes in the Regex Tester confirming they behave exactly how you expect.
If you're also interested in how to handle authentication which is where password and email validation patterns get used most check out our guide on Next.js Server Actions security and how to properly layer client-side and server-side validation together.
Frequently Asked Questions
What is the best regex for email validation in JavaScript?
The most practical pattern for production is /^[^s@]+@[^s@]+.[^s@]+$/i. It's readable, handles edge cases like plus-sign aliases and long TLDs, and avoids the overcomplicated RFC-5322 patterns that still can't tell you if an email actually receives mail. For deliverability, you need an email verification API no regex can do that.
What does ^ mean at the start of a regex pattern?
^ is a start anchor it means the match must begin at the very start of the string. Without it, your pattern can match text anywhere in the string. For validation, always pair ^ (start) with $ (end) so the entire string must match, not just part of it.
How do lookaheads work in password validation regex?
A positive lookahead (?=.*[A-Z]) is a zero-width assertion it says "from this position, check that the rest of the string contains at least one uppercase letter" without consuming any characters. By chaining multiple lookaheads, you can enforce several rules simultaneously: (?=.*[a-z])(?=.*[A-Z])(?=.*d) checks for lowercase, uppercase, and a digit all in one expression.
How do I test a regex pattern online for free?
Use our free Regex Tester & Debugger paste any pattern and test strings, see matches highlighted in real time, and test all flags (global, case-insensitive, multiline). It runs entirely in your browser, no account needed, no data sent anywhere.
Can regex validate HTML or nested structures?
You can extract simple patterns from HTML like a specific attribute value but you should never use regex to parse HTML as a whole. Nested tags, self-closing elements, and attribute order make it structurally impossible to do reliably. Use DOMParser in the browser or a library like cheerio in Node.js instead.
How do I validate both format and logic for dates?
Use a two-step approach. First, validate the format with regex: /^d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]d|3[01])$/. Then validate the logic with JavaScript: const d = new Date(str); return d instanceof Date && !isNaN(d);. The regex catches format errors; JavaScript's Date constructor catches impossible dates like February 30th.
What is the difference between .test() and .match() in JavaScript regex?
.test() is called on the regex and returns a boolean use it when you only need to know if a pattern exists: /pattern/.test(str). .match() is called on the string and returns an array of matches (or null) use it when you need to extract the matched values: str.match(/pattern/g). For validation, always use .test() it's faster and returns exactly what you need.
Continue Reading
Explore All ArticlesLevel Up Your Workflow
Free professional tools mentioned in this article
Advanced SEO Meta Tag & Open Graph Generator
Generate highly optimized meta tags, Twitter Cards, and Open Graph data for Google and Facebook with real-time visual previews.
CSS to Tailwind CSS Converter
Convert legacy CSS to modern Tailwind CSS utility classes instantly. 100% secure, free, and runs entirely in your browser. Boost your core web vitals today.
JSON to TypeScript Converter
Convert any JSON object into clean TypeScript interfaces instantly. Supports nested objects, arrays, and optional fields free, no signup, runs entirely in your browser.
PX to REM Converter
Convert px to rem and rem to px instantly - bidirectional, custom base font size, bulk converter, and CSS snippet output. Free, no signup.



