JavaScript Regex Tester Online — Test JS Patterns Instantly
Table of Contents
JavaScript regex has some quirks that trip up even experienced developers. The test() method vs match() vs exec(). The global flag that causes stateful issues with test() called in a loop. The u flag that changes how surrogate pairs are handled. Testing these live in a browser is faster and more reliable than console.log-driven debugging.
Our regex tester runs JavaScript's native regex engine — the same one your browser uses for String.prototype.match() and RegExp.prototype.test(). You get accurate results for all JS-specific flag combinations, including the s (dotAll) and u (unicode) flags added in modern ECMAScript.
Every JavaScript Regex Flag Explained with Examples
JavaScript regex supports six flags. Most online testers show them; fewer explain when you actually need them:
| Flag | Name | What It Changes | When to Use |
|---|---|---|---|
| g | Global | Find all matches, not just the first | Whenever you need all occurrences — always on for most use cases |
| i | Case-insensitive | A-Z and a-z treated identically | Email validation, username matching, keyword search |
| m | Multiline | ^ and $ match start/end of each line, not just the full string | Parsing multi-line text, log files, markdown |
| s | dotAll | . matches newline characters too | Matching across line breaks — HTML tag contents, multi-line blocks |
| u | Unicode | Enables Unicode code point escapes, fixes surrogate pair handling | Any text that might contain emoji, CJK characters, or non-ASCII content |
| y | Sticky | Only matches at the current lastIndex position | Tokenizers, parsers, streaming text processing |
The default in our tester is gi — global and case-insensitive, which covers the most common use case. Change flags by toggling the checkboxes next to the pattern field.
The Global Flag Gotcha — Why test() in a Loop Breaks
The most common JavaScript regex bug: using a regex with the g flag in a while or for loop with .test(). Here is what happens:
A regex object with the g flag is stateful. After each successful .test() call, it advances its internal lastIndex to just past the last match. The next call starts searching from that position. When no more matches exist, it resets to 0 — and the cycle repeats.
The result: your if (pattern.test(str)) check returns true on odd calls and false on even calls if you're calling it repeatedly on the same string.
Fix options:
- Create a new regex object each time:
const match = new RegExp(pattern, 'g').test(str) - Use a regex literal without the
gflag when you only care about "does this match anywhere":/pattern/i.test(str) - Reset
lastIndexmanually:pattern.lastIndex = 0before each call
When testing in our tester, you're always starting fresh — no stale state. But be aware this gotcha only shows up in your actual JavaScript code, not in the tester.
Sell Custom Apparel — We Handle Printing & Free ShippingJavaScript Regex Methods — test() vs match() vs exec()
Three methods. Different return values. Knowing which to use prevents a lot of null pointer errors:
RegExp.prototype.test(str) — returns true or false. Use this when you only need to know if a match exists. Fastest option. Does not give you the matched text or groups.
String.prototype.match(regex) — returns an array of matches, or null if nothing matched. With the g flag, returns all matches as strings. Without g, returns the first match with capture groups attached. Always check for null before accessing results.
RegExp.prototype.exec(str) — returns a single match result (with groups, index, input), or null. With g, each call returns the next match — useful for iterating all matches when you need the match index. The modern alternative is String.prototype.matchAll() which returns an iterator.
For testing purposes, our tester uses global matching equivalent to matchAll() — it shows every match location, which gives you the clearest view of what your pattern actually captures.
Testing Common JavaScript Validation Patterns
Email (HTML5 spec-ish): [a-zA-Z0-9.!#$%&'*+\/=?^_{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*
Phone (US, flexible): ^[+]?[(]?[0-9]{3}[)]?[-\s.]?[0-9]{3}[-\s.]?[0-9]{4,6}$
URL (http/https): https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&\/=]*)
Slug: ^[a-z0-9]+(?:-[a-z0-9]+)*$
Hex color: #([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})\b
Credit card (generic 16-digit): \b(?:\d[ -]?){16}\b
Test each one with both valid and invalid examples. The patterns above are starting points — edge cases in real data will require tuning.
Named Capture Groups — Testing the Modern JavaScript Syntax
Named capture groups were added in ES2018 and are now supported in all modern browsers. The syntax is (?<name>...):
(?<year>\d{4})-(?<month>0[1-9]|1[0-2])-(?<day>0[1-9]|[12]\d|3[01])
In your JavaScript code, access named groups via match.groups.year, match.groups.month, and match.groups.day. This is cleaner than positional capture groups and makes your patterns self-documenting.
Our tester supports this syntax — paste the pattern, test a date string like 2026-04-08, and confirm the match is captured correctly before using it in your code.
Try It Free — No Signup Required
Runs 100% in your browser. No data is collected, stored, or sent anywhere.
Open Free Regex TesterFrequently Asked Questions
Does this regex tester use the same engine as Chrome and Node.js?
Yes. The tester runs in your browser, which uses the V8 JavaScript engine — the same engine that powers Node.js and Chrome. Patterns that work in the tester will work the same way in V8-based environments.
Why does my regex with the g flag return different results in a loop?
Regex objects with the g flag are stateful. Their lastIndex advances after each match, so calling .test() in a loop on the same regex object alternates between true and false. Always create a new regex object or reset lastIndex to 0 before reusing.
How do I test a regex that uses lookbehind?
Lookbehind assertions ((?<=...) and (?

