This tool runs entirely in your browser. Nothing you paste is uploaded.
How you can check →JavaScript regex tester — ECMAScript RegExp, exactly as your browser or Node runs it
Ships in: JavaScript, TypeScript, Node.js, browsers
Want to test your own pattern under ECMAScript (RegExp)? Open the regex tester with this flavor already selected.
Open the regex tester — ECMAScript (RegExp) →JavaScript's RegExp is the flavor almost every online tester actually runs, whether it says so or not — which is exactly the trap. Paste a pattern here under "ECMAScript (RegExp)" and you are testing the literal engine that ships in every browser and in Node.js, not a JavaScript-flavored guess at what Python or Java would do with the same source text.
The single most common surprise is that JavaScript's shorthand classes never expand to Unicode on their own. \d, \w and \s are ASCII-only even with the u or v flag turned on — a rule several other mainstream engines break in JavaScript's favor. If you need to match a digit written in Arabic-Indic numerals, or a letter outside the Latin block, \d and \w will silently miss it here; you need \p{Number} or \p{Letter} explicitly, and only under u or v. This single divergence from Python and .NET (both Unicode-aware by default) is worth checking before you port a validation pattern in either direction.
The second trap is code units versus code points. Without the u or v flag, a JavaScript pattern matches UTF-16 code units, not characters — so a bare . can match one half of an emoji or another astral character, and a character class containing a surrogate pair behaves as a two-element class rather than one. Turning on u (or its superset, v) switches JavaScript to code-point semantics, which is also when \u{1F600}-style braced Unicode escapes and \p{...} properties become legal syntax at all; without the flag, that braced form is a hard parse error, not a fallback.
Inline flag switches are the newest divergence worth knowing about. A scoped modifier like (?i:foo) is real ES2025 syntax, but it only shipped in Chromium 125 and Firefox 132 — recent enough that relying on it in a pattern meant for older runtimes is a real compatibility risk, not a theoretical one. And the bare, unscoped (?i) switch that every other flavor on this page accepts as "turn on case-insensitivity for the rest of the pattern" is still not valid JavaScript at all, with or without a body — you always need the group form.
Global iteration is the other place JavaScript earns its own row in the flavor table. The g flag advances lastIndex itself between calls to exec, and getting that advance wrong on a zero-length match is the classic cause of an infinite matching loop in hand-rolled code — this tool's own VM implements the documented fix (advance by one code point after a zero-length match) so the count you see here is the count you should expect from matchAll, not a guess.
None of this is a reason to avoid JavaScript's regex engine — it is fast, it is everywhere, and its ES2018+ named groups and lookbehind support are both excellent. It is a reason to test against the actual rules rather than a generic "regex" mental model borrowed from whichever language you learned first. This page runs the real ECMAScript semantics — including the cross-check against your own browser's native RegExp — so what you see here is what new RegExp(pattern, flags) will actually do.
One more place JavaScript diverges quietly: a backreference to a capturing group that never participated in the match — \1 after an optional group (a)?\1 that took the empty branch — matches an empty string here, silently, rather than failing the whole attempt the way Python, Java and .NET all do for the identical construct. This is invisible until it isn't: a pattern built and tested against JavaScript that relies on an unparticipated backreference failing to match will pass every test here and then behave differently the moment the same logic is ported to a backend language, with no error at either end to point at why the counts disagree.
Delimiters are worth a paragraph of their own, because JavaScript is the one flavor on this page where the source text people actually paste usually still has them attached. A pattern copied from documentation, from another tool, or from source code frequently arrives as /foo/gi rather than bare foo — and this tool's pattern bar recognizes that shape on paste, strips the slashes, and sets the flag toggles from the trailing letters automatically, rather than leaving you to trim it by hand before the pattern will parse at all.
ECMAScript (RegExp) quirks, at a glance
The same facts this tool's engine implements and tests against — not a separate, unverified summary.
- \d, \w and \s are ASCII-only even under the u flag — Unicode digits and letters need \p{...} explicitly.
- Without u or v, . matches a single UTF-16 code unit, so it can match half of an astral character.
- (?i:...) is real ES2025 syntax; a bare (?i) with no group and no colon is not — every other flavor accepts it as a global switch.
A worked example: JavaScript / TypeScript (literal)
Extracting a date like 2026-08-22 — ^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})$.
/^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})$/
The u and v flags change what \p{...} and character-class syntax mean here — adding one after the fact can change how this same pattern matches.
Frequently asked questions
- Does \d match Unicode digits in JavaScript?
- No. \d, \w and \s are ASCII-only in JavaScript's RegExp even under the u or v flag — unlike Python and .NET, which are Unicode-aware by default. Use \p{Number} (with u or v) if you need non-ASCII digits.
- What's the difference between the u and v flags?
- u switches matching to Unicode code points (so . and character classes stop splitting astral characters in half) and enables \p{...} and \u{...} syntax. v is a superset of u that additionally allows set operations — union, intersection, difference — inside character classes.
- Why does my pattern with (?i) fail to compile?
- A bare, unscoped (?i) mid-pattern switch is not valid JavaScript syntax, with or without a following colon and group. Only the scoped form, (?i:...), compiles, and only in engines new enough to support ES2025 (Chromium 125+, Firefox 132+).
- Can I test the exact pattern my browser will run?
- Yes — this tool's cross-check receipt runs the equivalent pattern through your browser's own native RegExp and compares the offsets and captures against our engine's output, so an agreement is verifiable in your own devtools.
Other flavors
the engine behind PHP's preg_* and most Apache/nginx rewrite rules
re module rules, Unicode-by-default, 3.11+ possessive quantifiers
java.util.regex rules for Java, Kotlin, Scala and Android
System.Text.RegularExpressions rules, including the group-numbering quirk
RE2 rules, including why lookaround and backreferences don't compile
POSIX ERE and leftmost-longest matching, not leftmost-first
POSIX BRE, where ( ) and { } are literal and \( \) \{ \} do the work