Skip to content
AZ Tools

Regex Tester

Test JavaScript regular expressions live with highlighted matches and replace preview.

Flags
Matches2 match(es)
Contact me at jane@example.com or john@test.io for details.
  • #1 @14jane@example.com
  • #2 @34john@test.io
Replacement preview
Contact me at [redacted] or [redacted] for details.

How to use

  1. Enter a regex pattern (without delimiters).
  2. Toggle flags: g (global), i (case-insensitive), m (multiline), s (dotall), u (unicode).
  3. Type or paste a test string — matches highlight as you type.
  4. Provide a replacement string to preview the result.

About this tool

Show

Write a pattern, toggle the flags, and every match lights up in the test string as you type. Capture groups are listed per match and a replacement preview runs alongside, so you can confirm both what the pattern finds and what it would produce. The engine is the browser's own JavaScript RegExp, which means what you see is exactly what your code will do — and nothing leaves the page, which matters when the sample you are debugging is real data.

Being the real JavaScript engine also means inheriting its specific personality. \d matches only the ASCII digits 0 through 9, so a string of Arabic-Indic numerals fails a pattern that looks like it should accept any digits; \p{Nd} with the u flag is the one that does. The dot skips newlines unless you set the s flag. There is no \A or \z — anchoring to the whole string means ^ and $ without m. Lookbehind works in current browsers but arrived late, so a pattern using it may fail on an older device even though it passes here.

Portability is worth checking before you copy a pattern into another language. Go's standard library uses RE2, which has no backreferences and no lookaround at all, by design — a pattern that works perfectly here will simply be rejected there. Python and PCRE accept more than JavaScript does, including atomic groups and possessive quantifiers, so a pattern copied the other way may silently behave differently rather than erroring.

The failure mode to actually fear is catastrophic backtracking. A pattern with nested quantifiers over overlapping alternatives can take exponential time on input that nearly matches: /^(a+)+b$/ tested against twenty-eight a characters followed by an x takes seconds in this engine, and each extra character roughly doubles it. On a server that is a denial of service from a single short request, which is why the pattern class has its own name. If your regex has a quantifier inside a quantifier, try it against a long near-miss before shipping it — this page is a good place to find out.

Frequently asked questions

What dialect does this use?

JavaScript regex (ECMAScript). Lookbehinds, named groups, and Unicode property escapes are supported in modern browsers.

How do I reference capture groups in the replacement?

Use $1, $2, $& for the full match, or $<name> for named groups.

Is there a match limit?

The first 10,000 iterations are captured to keep the UI responsive; the first 50 are shown in the match list.

Is my data sent anywhere?

No. Patterns and test strings run only in your browser, and the auto-save keeps them in your local storage.

Why does my pattern freeze the page?

Almost certainly catastrophic backtracking. Patterns that nest quantifiers - something like (a+)+b - can force the engine through an exponential number of ways to split the input before admitting there is no match. The fix is to make the inner parts unambiguous, usually by replacing a greedy .* with a negated character class that cannot overlap the delimiter.

What does the global flag actually change?

Without g, matching stops at the first result. With g, the search continues through the string, which is what makes the match list longer than one - and it also makes the regular expression stateful in real code, because it remembers where it stopped. That is the usual reason a pattern reused in a loop appears to skip every other match.

How do I match across multiple lines?

Two different flags are involved and they are easy to confuse. Multiline changes what the anchors mean, so ^ and $ match at every line break instead of only at the ends of the string. Dot-all changes what the dot matches, letting it cover newlines too. If a pattern stops at the end of the first line, dot-all is usually the one you wanted.

Guides on this topic

Related tools