Skip to content
Free · Runs in your browser

Regex Tester for JavaScript

Write a JavaScript regular expression and see every match highlighted in your own text, with capture groups, positions and a replace preview. Slow patterns are stopped instead of freezing the page.

Without the surrounding slashes. Runs as /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/g

Flags

Testing…

Running the pattern against your text.

How to use the regex tester

  1. Type your pattern into Regular expression without the slashes. For /\d+/g, enter \d+ and tick the g flag.
  2. Paste realistic sample data into Test string. Include the lines that should match and, just as important, the ones that should not.
  3. Read the result. Every match is highlighted in place, and the table lists its exact text, its start and end position, and the value of each capture group.
  4. Tick Replace to preview what text.replace(pattern, replacement) would produce before you run it on real files or database rows.

Results update as you type. The pattern runs with the same engine as your browser’s JavaScript, so what you see here is what String.prototype.match, matchAll and replace will do in Node.js, Deno, Bun and every modern browser.

What each flag changes

  • g (global) finds every match instead of stopping at the first. Without it, replace changes only the first occurrence, a classic source of half-fixed data.
  • i (ignore case) makes error match ERROR and Error.
  • m (multiline) makes ^ and $ match at the start and end of every line rather than only the whole string. You need it to match line by line in a log file or a CSV.
  • s (dotAll) lets . match line breaks too. Without it, .* stops at the end of the line.
  • u (unicode) treats the pattern and text as Unicode code points, so an emoji counts as one character, and enables property escapes such as \p{L} (any letter in any script). It also makes the parser strict, turning silent mistakes such as an unnecessary escape into errors.
  • y (sticky) only matches at the current position, which is how tokenizers walk through input one piece at a time.

Capture groups and replacements

Parentheses do two jobs: they group part of a pattern so a quantifier applies to all of it, and they capture the text that part matched. Captures are numbered from left to right by their opening parenthesis. In the example loaded above, (?<year>…) is a named group, so the year is available both as $1 and by name.

Named groups make patterns readable and survive edits: if you add a group at the front, $1 silently changes meaning but $<year> does not. When you only need grouping, use a non-capturing group, (?:…), so the numbering of the groups you do care about stays stable.

In a replacement string you can use:

  • $1, $2… for numbered groups and $<name> for named ones
  • $& for the whole match, for example to wrap it: [$&]
  • $` and $' for the text before and after the match, and $$ for a literal dollar sign

The date example reorders 2026-11-02 into 02/11/2026 with the replacement $<day>/$<month>/$<year>. Tick Replace to see it.

Avoiding slow patterns (catastrophic backtracking)

JavaScript’s regex engine is a backtracking engine. When part of a pattern fails, it goes back and tries every other way the earlier parts could have matched. Usually that is quick. But nested or overlapping quantifiers, such as (a+)+$, (\w+\s?)*$ or (.*,)*, can give the engine an exponential number of ways to split the same text. On a string that almost matches, a 30-character input can take minutes.

On a server this is a denial-of-service risk known as ReDoS: one crafted request can pin a CPU core. This tester runs each pattern in a background worker and stops it after two seconds, so you see the problem instead of a frozen tab. To fix a slow pattern:

  • Remove the nesting. (a+)+ matches exactly what a+ matches.
  • Make alternatives mutually exclusive, so only one branch can match any given character.
  • Replace .* with a negated class that cannot run past the delimiter, such as [^,]* for a CSV field or [^"]* inside quotes.
  • Anchor the pattern with ^ and limit lengths, such as \d{1,10}, when you validate untrusted input.

Patterns worth knowing

  • ISO date: ^\d{4}-\d{2}-\d{2}$ checks the shape only, so it accepts 2026-02-31. Use a date library, or the timestamp converter, to check that the date exists.
  • Trim repeated whitespace: replace \s+ with a single space using the g flag.
  • Pull IDs out of a log: request_id=([0-9a-f-]{36}) captures a UUID. Need test values? Use the UUID generator.
  • Email addresses: a simple ^[^\s@]+@[^\s@]+\.[^\s@]+$ catches typos. A pattern that tries to follow the full standard gets very long and still cannot tell whether a mailbox exists. Send a confirmation email instead.

Regular expressions are the wrong tool for nested formats such as HTML or JSON. Parse JSON with a real parser; the JSON formatter shows exactly where a document is broken.

Frequently asked questions

Which regex flavour does this tester use?

JavaScript (ECMAScript), using your browser’s own engine. Most syntax is shared with PCRE, Python and Java, but some features differ: JavaScript has no possessive quantifiers or atomic groups, and lookbehind is supported only in modern engines. Test in the flavour your code will run in.

Why does my pattern only find the first match?

The g (global) flag is off. Without it, exec, match and replace stop after the first match. Tick g to find, highlight and replace all of them.

Why do ^ and $ not match each line?

By default they match only at the very start and end of the whole text. Turn on the m (multiline) flag to make them match at every line break.

How do I match a literal dot, bracket or slash?

Escape it with a backslash: \. matches a dot, \( a parenthesis and \[ a square bracket. A forward slash needs escaping only inside a /…/ literal in source code, not in this tester.

Why did the tester stop with “took too long”?

The pattern caused catastrophic backtracking, where nested quantifiers such as (a+)+ make the engine try an exponential number of combinations. Remove the nesting or use a narrower character class; the section on slow patterns above shows how.

Is my test text sent anywhere?

No. Matching runs in a background worker inside your browser. Nothing you type is uploaded or stored, so it is safe to test against real log lines.

All tools

Need something bigger than a browser tool?

We design and build web apps, internal tools, APIs and cloud infrastructure for teams that need them done properly. Tell us what you are working on.