N

Runs in your browser · nothing is uploaded

Regex Tester

Use this regex tester to try a JavaScript regular expression against your own text: matches are highlighted as you type, capture groups and positions are listed, and a replace preview shows the result of $1 and named-group substitutions.

0 matches shown (maximum 1,000)

Contact hello@example.com today.
Match positions and capture groups
[]

JavaScript regex syntax. Runs in a disposable worker with a timeout. Match positions are zero-based UTF-16 offsets.

How the tester runs your pattern

  • Compilenew RegExp(pattern, flags)
  • Find matchesrepeat re.exec(text) while g or y is set, up to 1,000 matches
  • Replace previewtext.replace(new RegExp(pattern, flags), replacement)

The test starts 150 ms after you stop typing, in a fresh Web Worker. If it hasn't finished in 750 ms the worker is terminated, so a runaway pattern can't freeze the page. Empty matches (for example from a*) advance by one character — or one code point with the u flag — so the loop always ends.

JavaScript regex syntax. Match positions are zero-based UTF-16 offsets. The "Match positions and capture groups" panel lists each match's index, text, numbered groups and named groups.

Worked example

Rewrite ISO dates as day/month/year. Pattern (?<y>\d{4})-(?<m>\d{2})-(?<d>\d{2}) with flag g on:

Invoice 1042 due 2026-10-15; reminder sent 2026-11-01.
IndexMatchy · m · d
172026-10-152026 · 10 · 15
432026-11-012026 · 11 · 01

Replacement $<d>/$<m>/$<y> gives:

Invoice 1042 due 15/10/2026; reminder sent 01/11/2026.

The tool's default email pattern \b\w+@\w+\.\w+\b shows why you test on real data. On "Write to hello@example.com or first.last@mail.example.co.uk" it finds "hello@example.com" and "last@mail.example" — the second is only part of the address, because \w doesn't match dots.

JavaScript regex reference

Tokens

TokenMatches
.Any character except a line break (any character with the s flag)
\d \w \sDigit 0–9 · ASCII letter, digit or _ · whitespace
\D \W \SThe opposite of each class above
[abc] [^abc] [a-z]One of the listed characters · none of them · a range
\p{L} \p{N}Any Unicode letter · any Unicode number (needs the u flag)
^ $ \bStart · end (of each line with m) · word boundary
* + ?0 or more · 1 or more · 0 or 1 (greedy)
{3} {2,} {2,5}Exactly 3 · 2 or more · 2 to 5
*? +? {2,5}?Lazy versions: match as few as possible
(…) (?:…)Capturing group ($1, $2 …) · non-capturing group
(?<name>…)Named group, used as $<name> in the replacement
\1 \k<name>Backreference to a numbered or named group in the pattern
a|bAlternation: a or b
(?=…) (?!…)Lookahead: followed by · not followed by
(?<=…) (?<!…)Lookbehind: preceded by · not preceded by

Flags

  • g Global: find every match, and replace every match
  • i Case-insensitive
  • m Multiline: ^ and $ match at line breaks
  • s dotAll: . also matches line breaks
  • u Unicode: code-point matching, \p{…} classes, stricter syntax
  • y Sticky: match only at the position where the last match ended

Replacement patterns

  • $1 $2 Numbered group
  • $<name> Named group
  • $& The whole match
  • $` $' Text before · after the match
  • $$ A literal $

Escape these characters with a backslash to match them literally: . * + ? ^ $ { } ( ) [ ] | \ /. Type the pattern without surrounding slashes — the slashes in /abc/g are JavaScript literal syntax, not part of the pattern.

Common regex mistakes

Greedy by default

<.+> on <b>hi</b> matches the whole string. Use the lazy <.+?> or a negated class <[^>]+> to stop at the first closing bracket.

Missing anchors

For validation, wrap the pattern in ^…$. Without anchors, \d{5} also matches inside "123456". With the m flag, the anchors apply to each line instead of the whole text.

Nested quantifiers

Patterns like (a+)+$ or (\w+\s?)*$ can backtrack exponentially. The tool stops them after 750 ms; in production code the same pattern can hang a server. Flatten them to a+$.

This is the dedicated regex tester. The Developer Toolkit has a lighter regex tab with a rule-based pattern breakdown, next to its cron, YAML and .env tools. Use this page when you need capture groups with positions, a replace preview, the s, u and y flags, or large test inputs.

Sources: MDN Web Docs, "Regular expressions" guide and "String.prototype.replace()"; ECMAScript 2025 Language Specification, section 22.2 (RegExp objects). Checked 15 October 2026.

Frequently asked questions

Which regex flavor does this tester use?+

JavaScript (ECMAScript), the same engine your browser and Node.js use. Patterns that rely on PCRE, Python or .NET features — possessive quantifiers, atomic groups, \A and \Z anchors, or (?P<name>…) groups — won't work here. JavaScript writes named groups as (?<name>…).

What do the g, i, m, s, u and y flags do?+

g finds every match instead of the first. i ignores case. m makes ^ and $ match at each line break. s lets . match newlines. u turns on full Unicode mode, needed for \p{…} classes and emoji. y (sticky) only matches at the exact position where the last match ended.

Why is only the first match replaced?+

Without the g flag, JavaScript replaces only the first match. Replacing "cat" with "dog" in "cat, cat, cat" gives "dog, cat, cat" without g and "dog, dog, dog" with it. The match list follows the same rule.

How do I use capture groups in the replacement?+

Use $1, $2 … for numbered groups and $<name> for named ones. $& inserts the whole match and $$ a literal dollar sign. With (?<y>\d{4})-(?<m>\d{2})-(?<d>\d{2}), the replacement $<d>/$<m>/$<y> turns "Due 2026-10-15, paid 2026-11-01." into "Due 15/10/2026, paid 01/11/2026.".

Why does \w not match accented letters?+

In JavaScript, \w only covers A–Z, a–z, 0–9 and underscore, so \w+ matches "caf" in "café". Use \p{L}+ with the u flag to match any letter: it matches "café".

What does "Pattern took too long" mean?+

Each test runs in a separate worker that is stopped after 750 ms. Nested quantifiers such as (a+)+$ can take exponential time on text that almost matches — known as catastrophic backtracking. Remove the nesting, make the quantified parts mutually exclusive or anchor the pattern.

Why are match positions different from what I count?+

Positions are zero-based UTF-16 offsets, as in JavaScript strings. An emoji outside the Basic Multilingual Plane takes two units, so in "😀 hi" the match "hi" starts at index 3, not 2.

How do I make a match lazy instead of greedy?+

Add ? after the quantifier. Quantifiers such as + and * are greedy and take as much text as they can: in say "yes" or "no", ".+" matches “"yes" or "no"” in one go. The lazy ".+?" stops at the first closing quote and matches “"yes"” and “"no"” separately.

How do I match a literal dot or other special character?+

Put a backslash before it. An unescaped . matches any character, so a.b finds “a.b” and “axb” in "a.b axb", while a\.b finds only “a.b”. The characters that need escaping are . * + ? ^ $ ( ) [ ] { } | and the backslash itself.

Do I type the slashes or double the backslashes?+

Neither. Type the pattern without the surrounding /…/ and put flags in their own box. Write each backslash once, as you would in a /…/ regex literal — \d, not \\d. Doubled backslashes are only needed when a pattern is written inside a quoted string, such as new RegExp("\\d+") in code.

Are there size limits?+

Yes: up to 200,000 characters of test text, a pattern of up to 2,000 characters, and at most 1,000 matches listed. The replace preview still covers the whole text.

Is my text sent to a server?+

No. Your pattern and text are processed in a Web Worker inside your browser, then the worker is discarded. Nothing is stored or uploaded, so you can test against logs or data you don't want to share.