FixTools Regex Tester runs in the browser, which means it uses the same V8 JavaScript regex engine your Node.js backend and web frontend use.
Loading Regex Tester…
Uses the real browser JavaScript regex engine (V8)
Supports ES2018+ features: named groups, lookbehinds, dotAll
Test with String.match(), matchAll(), replace(), and split() semantics
Verify Unicode mode behaviour with the u flag
Drop the Regex Tester into any page — blog post, product docs, intranet, school portal — with a single line of HTML. Your visitors get the full tool, processed entirely in their browser. No backend, no uploads, no signup.
Embed code
<iframe
src="https://www.fixtools.io/developer/regex-tester?embed=1"
width="100%"
height="780"
frameborder="0"
style="border:0;border-radius:16px;max-width:900px;"
title="Regex Tester by FixTools"
loading="lazy"
allow="clipboard-write"
></iframe>Attribution-friendly: a small "Powered by FixTools" link appears in the embed footer.
JavaScript regex has evolved significantly since ES5. ES2015 added the u (unicode) and y (sticky) flags. ES2018 introduced named capture groups ((?<name>...)), lookbehind assertions ((?<=...) and (?<!...)), the s (dotAll) flag, and Unicode property escapes (\p{...} with the u flag). ES2024 added the v (unicodeSets) flag, which enables set operations and string properties in character classes. Testing patterns that use these features in a browser-based tester is the most reliable way to confirm they work as expected in a JavaScript context, because the tester uses the same ECMAScript implementation as your runtime environment. A flavour-generic tester might accept or reject features that V8 handles differently, giving you false confidence or unnecessary warnings.
The key JavaScript-specific behaviours that differ from other regex flavours include: lastIndex state management when reusing RegExp objects with the g or y flag (a common source of bugs in loop-based parsing), the way String.prototype.replace() uses $1, $2, and named group references like $<name> in replacement strings, the difference between match() and exec() regarding group capture data in global mode, and how matchAll() returns an iterator of match objects each containing the full group data including named groups and the match index. These nuances are impossible to test accurately in a flavour-generic tester but are immediately observable in a browser-based JavaScript tester running the actual V8 engine.
For TypeScript developers, regex patterns are typed as RegExp and string methods that accept RegExp are well-typed in the standard library definitions. The patterns themselves are untyped string literals to the type checker, so runtime testing in a browser-based tool remains the primary verification mechanism for confirming that a pattern produces the expected match structure. If you use the TypeScript noUncheckedIndexedAccess option, named capture groups must be accessed as match.groups?.name rather than match.groups.name, and your pattern must be tested accordingly to understand the match object shape before writing the access code.
Performance pitfalls in JavaScript regex deserve attention because V8 does not implement the linear-time matching algorithms (such as Rust regex or Go regexp) that guarantee polynomial worst case. JavaScript uses a backtracking NFA, which means a poorly written pattern can take exponential time on adversarial input. The classic danger pattern in JavaScript is the nested or overlapping quantifier such as (a+)+ or (a|aa)*b, applied to a string that almost matches. In a browser context the symptom is a frozen tab and an eventual "page unresponsive" dialog. Mitigate this by avoiding nested quantifiers entirely (rewrite (a+)+ as a+), preferring possessive-equivalent unrolled patterns such as [^a]*a, and capping input length before applying user-supplied or dynamically constructed patterns. On the server side, run untrusted regex inside a worker thread with a timeout so a single slow match cannot stall the event loop.
Enter your JavaScript regex pattern and test string. The tester uses the browser JS engine, so named groups, lookbehinds, and Unicode mode work exactly as they would in your Node.js or browser JavaScript code.
Step-by-step guide to test javascript regex online, real v8 engine in the browser:
Open the Regex Tester
Navigate to the FixTools Regex Tester using the link on this page. Because the tool runs in the browser, it uses the V8 JavaScript regex engine natively. No configuration is needed to access ES2018 or later features such as lookbehinds, named groups, or dotAll mode.
Enter your JS regex pattern
Type or paste your JavaScript pattern into the pattern field without forward slash delimiters or inline flags. Just the pattern content itself. For a named group example, enter (?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2}) and see each named group appear in the match results panel with its label and captured value.
Set JavaScript-specific flags
Enable the flags your production code uses: g for global matching with matchAll(), u for Unicode mode to enable property escapes, s for dotAll so the dot matches newlines, or y for sticky matching in parser loops. Each flag changes the engine's behaviour, so test with the exact flag combination your code will use rather than defaulting to g alone.
Paste your test string
Enter the string you pass to match(), test(), or replace() in your JavaScript code. For global matching, paste several lines of representative data and enable both g and m flags to see all matches across the full input at once. Check the match results panel for named group values and positions before writing the code that accesses them.
Common situations where this approach makes a real difference:
Testing a named capture group pattern for date extraction
A developer writes (?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2}) to extract ISO date components from a log string. In the tester, the named groups year, month, and day appear in the match results panel with their respective values. This confirms that match.groups.year, match.groups.month, and match.groups.day will contain the expected strings when the pattern is used with String.prototype.match() in production JavaScript code, before the developer writes the downstream processing logic.
Verifying a lookbehind assertion for currency parsing
A financial data parser needs to extract the numeric value following a currency symbol without including the symbol in the extracted text. The pattern (?<=\$)[\d,]+\.\d{2} uses a positive lookbehind to assert the presence of a dollar sign at the current position without consuming it. Testing against "$1,234.56 USD" in the browser tester confirms that 1,234.56 is captured and the dollar sign is not. The developer also tests a bare number like 1234.56 to confirm it is not captured when the dollar sign context is absent.
Debugging a sticky regex used in a parser loop
A hand-written tokeniser uses the y (sticky) flag to consume tokens from a source string one at a time, advancing lastIndex after each match. A bug causes occasional tokens to be skipped silently. Reproducing the token pattern in the tester with a sample token sequence reveals that the pattern does not account for optional whitespace between tokens. When lastIndex lands on a space character, the next sticky match fails because the pattern expects to start on a token character directly, not on whitespace.
Testing Unicode property escapes for international text classification
A content filter needs to detect strings containing only characters from the Latin script and reject strings mixing scripts. The pattern ^\p{Script=Latin}+$ with the u flag uses a Unicode property escape for script-level character classification. Testing against "Hello" (Latin), "Привет" (Cyrillic), and "مرحبا" (Arabic) in the browser tester confirms the pattern accepts only Latin text and rejects the other two, validating that Unicode property escapes behave correctly in the V8 engine before deploying the filter.
Use this page when you are writing JavaScript or TypeScript code that uses RegExp and want to verify pattern behaviour using the actual JS engine rather than a generic regex tester that may behave differently.
Get better results with these expert suggestions:
Use named capture groups over index-based groups for maintainable code
Named groups (?<name>...) make both replacement strings and extraction code self-documenting. Instead of writing match[1] and match[2] and counting groups, you write match.groups.year and match.groups.month, which communicate intent at a glance. In String.replace(), reference named groups as $<name>. Test both the named capture pattern and the replacement string in the tester to confirm all names resolve to the expected values before embedding them in production code.
Reset lastIndex when reusing a RegExp object with the g flag
A common and subtle JavaScript bug: a RegExp literal with the g flag stored in a variable retains its lastIndex between calls. Calling regex.test() or regex.exec() in a loop without resetting lastIndex to 0 before each new input string causes the engine to start mid-string, making every other call fail unexpectedly. Use String.prototype.matchAll() for global matching in loops rather than managing lastIndex manually, or explicitly set regex.lastIndex = 0 before each new input.
Enable the u flag when working with emoji or non-BMP characters
Without the u flag, a JavaScript regex treats characters outside the Basic Multilingual Plane as two surrogate pairs. The dot metacharacter matches one surrogate unit rather than one full character, and quantifiers count surrogates rather than code points. This produces incorrect results for emoji, many CJK extension characters, and mathematical symbols. Always enable the u flag when your pattern or test string contains any character outside the standard Latin and Cyrillic ranges to ensure correct character-level matching.
Verify replacement string syntax with $<name> in named-group replacements
Named group back-references in JavaScript replacement strings use the $<name> syntax, not \1 (PCRE-style) and not \k<name> (which is the pattern-side back-reference syntax used inside the regex itself). A common mistake is using the wrong syntax form in the replacement string, which causes the literal text "$<name>" or "\k<name>" to appear in the output instead of the captured value. Test your replacement string output in the tester before writing the String.replace() call.
More use-case guides for the same tool:
Open the full Regex Tester — free, no account needed, works on any device.
Open Regex Tester →Free · No account needed · Works on any device