Skip to content

JavaScript Regex Tester

Enter a pattern, flags and some text. You get a numbered table of every match, where each one starts, and what each capture group held.

Runs in your browserFree, no sign-upLast reviewed

Settings

g global · i ignore case · m multiline · s dotall · u unicode

Results update automatically as you type.

Summary

Matches
2
Flags
g
Groups
0

Matches

#MatchIndexGroups
1ada@example.com8—
2grace@navy.mil27—

Quick answers

Which regex flavour does this tester use?
JavaScript, also called ECMAScript. The pattern is compiled by your own browser's RegExp engine, so lookahead, lookbehind, named groups, backreferences and Unicode property escapes (with the u flag) all work in current browsers. Features from other flavours, such as PCRE recursion, atomic groups or inline (?i) modifiers, are reported as errors.
What do the regex flags g, i, m, s, u and y mean?
g finds all matches instead of the first. i ignores case. m makes ^ and $ match at the start and end of each line. s lets the dot match newline characters. u turns on full Unicode mode. y (sticky) only matches starting exactly at the current position.
How do I see what a capture group matched?
Put parentheses around the part you want. The Groups column then lists $1, $2 and so on for each match. The pattern (\d{4})-(\d{2})-(\d{2}) run on 2026-10-08 shows $1=2026, $2=10 and $3=08. A group that took no part in a match is shown empty.
Why does my regex match too much?
Quantifiers are greedy: .+ and .* take as much as they can. On the text <b>bold</b> and <i>italic</i>, the pattern <.+> returns one match covering the whole string. Add a question mark to make it lazy, <.+?>, or use a negated class, <[^>]+>, and you get the four tags separately.
What does the Index column mean?
It is the position of the first character of the match, counted from 0 at the start of the test text. It is the same number as match.index in JavaScript. A newline counts as one character, so matches on later lines have indexes that include every line break before them.
Do I need to escape special characters in the pattern?
Yes, with one backslash, exactly as inside a regex literal. A dot matches any character, so write \. for a literal full stop. Do not double the backslashes the way you would inside a JavaScript string passed to new RegExp.

About Regex Tester

This JavaScript regex tester runs your pattern on the regular expression engine built into your browser, the same one your JavaScript code uses, so what matches here matches in a RegExp. Results come back as a table: one row per match with the matched text, its zero-based index in the test text, and the contents of each capture group as $1, $2 and so on. A summary shows the match count, the flags and how many capture groups the pattern declares. It is a plain match lister. There is no highlighting inside the text, no replace preview and no step-by-step explanation of the pattern, and it tests JavaScript syntax only, not PCRE, Python or .NET.

Regex test examples with real match output

Each result is the table this tester produced for the pattern, flags and text shown.

Email addresses (the default sample)

Pattern \b[\w.]+@[\w.]+\.\w+\b, Flags g, Test text: Contact ada@example.com or grace@navy.mil for details.

Matches 2, Groups 0. Row 1: ada@example.com at index 8. Row 2: grace@navy.mil at index 27.

ISO dates with three capture groups

Pattern (\d{4})-(\d{2})-(\d{2}), Flags g, Test text: Released 2026-10-08, patched 2026-11-02.

Matches 2, Groups 3. 2026-10-08 at index 9 with $1=2026 $2=10 $3=08; 2026-11-02 at index 29 with $1=2026 $2=11 $3=02.

Whole word, any case

Pattern \bcat\b, Flags gi, Test text: Cat, cat, CAT and concatenate

Matches 3: Cat at 0, cat at 5, CAT at 10.

Without the \b word boundaries the same flags return 4 matches, because cat is also found inside concatenate at index 21.

First word of every line

Pattern ^\w+, Flags gm, Test text: three lines reading alpha one, beta two, gamma three

Matches 3: alpha at 0, beta at 10, gamma at 19.

With Flags g alone the result is 1 match, alpha, because ^ then means the start of the whole text.

Repeated words with a backreference

Pattern \b(\w+)\s+\1\b, Flags gi, Test text: This is is a test of the the pattern.

Matches 2, Groups 1. is is at index 5 with $1=is; the the at index 21 with $1=the.

Six-digit hex colours

Pattern #[0-9a-f]{6}\b, Flags gi, Test text: Brand #1D4ED8, accent #f59e0b, not #12345.

Matches 2: #1D4ED8 at index 6 and #f59e0b at index 22. The five-digit #12345 is not matched.

Lookbehind for prices

Pattern (?<=\$)\d+(\.\d{2})?, Flags g, Test text: Cost $45.99, was $60

Matches 2, Groups 1. 45.99 at index 6 with $1=.99; 60 at index 18 with $1 empty.

The dollar sign is required before the number but is not part of the match.

IPv4 octets as four groups

Pattern (\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3}), Flags g, Test text: Requests from 192.168.0.1 and 10.0.0.254 were blocked.

Matches 2, Groups 4. 192.168.0.1 at index 14 with $1=192 $2=168 $3=0 $4=1; 10.0.0.254 at index 30 with $1=10 $2=0 $3=0 $4=254.

JavaScript regex cheat sheet

The syntax you will type most often in the Pattern box.

SyntaxMatchesExample
.Any character except a newline (any character at all with the s flag)a.c matches abc
\d \w \sA digit; a letter, digit or underscore; a whitespace character\d\d matches 42
\D \W \SThe opposite of each of the above\S+ matches a run of non-spaces
[abc] [a-z] [^abc]One character from a set, from a range, or not in the set[^>]+ matches up to the next >
^ $Start and end of the text, or of each line with the m flag^\w+ matches the first word
\bA word boundary\bcat\b does not match in concatenate
* + ?Zero or more, one or more, zero or one of the previous itemcolou?r matches color and colour
{3} {2,5} {2,}Exactly 3, between 2 and 5, 2 or more\d{4} matches 2026
*? +? ??Lazy versions that take as little as possible<.+?> matches one tag
(abc)Capture group, numbered from 1 in order of the opening bracket(\d+)px captures the number
(?:abc)Group without capturing(?:ab)+ matches abab
(?<name>abc)Named capture group(?<year>\d{4})
a|bEither alternativecat|dog
\1 \k<name>Backreference to an earlier group(\w)\1 matches a doubled letter
(?=abc) (?!abc)Lookahead: followed by, not followed by\d+(?=px)
(?<=abc) (?<!abc)Lookbehind: preceded by, not preceded by(?<=\$)\d+
\p{L} \p{Lu}Unicode property escape; needs the u flag\p{Lu} matches an uppercase letter
\. \* \( \/A literal special characterexample\.com

What each flag changes, shown on the same text

Results from this tester. Only the flags differ within each pair.

PatternFlagsTest textResult
catgCat, cat, CAT and concatenate2 matches, at index 5 and 21
catgiCat, cat, CAT and concatenate4 matches, at index 0, 5, 10 and 21
^\w+galpha one / beta two / gamma three on three lines1 match: alpha
^\w+gmalpha one / beta two / gamma three on three lines3 matches: alpha, beta, gamma
a.cgabc, then a and c separated by a line break1 match: abc
a.cgsabc, then a and c separated by a line break2 matches; the second spans the line break
\p{Lu}guÜnïcode Ärger2 matches: Ü at index 0 and Ä at index 8
\d+y12 341 match: 12. Sticky stops at the space

How this tester differs from your own code

  • It always adds the g flag internally so it can list every match. Type i alone and you still get all matches; the Summary shows the flags as you typed them. In your code, a regex without g returns only the first match from match() and exec().
  • Named groups are listed by number. (?<year>\d{4})-(?<month>\d{2}) shows $1 and $2, not year and month.
  • Only g, i, m, s, u and y are accepted. The d (indices) and v (unicode sets) flags are refused with an unsupported flag message.
  • An empty match counts as a match. x* on the text axb returns 4 rows, three of them empty, because zero x's is a valid match at each position.
  • The table stops at Max matches to show, and the Matches figure in the Summary counts the rows shown, not every match in the text. Pattern \d+ on 1 22 333 4444 with the limit set to 2 reports 2.
  • An invalid pattern returns the engine's own message, which varies by browser. In Chrome, (unclosed is reported as Unterminated group.
  • The pattern runs in your browser tab. The text you paste is not uploaded.

Greedy, lazy and catastrophic backtracking

A greedy quantifier grabs as much text as it can and then gives characters back one at a time until the rest of the pattern fits. That giving back is called backtracking. It is why <.+> swallows everything from the first < to the last > on a line, and why the lazy form <.+?> or the negated class <[^>]+> is usually what you meant. The negated class is the better habit: it cannot run past the closing bracket at all, so the engine has nothing to undo.

Backtracking becomes a real problem when quantifiers are nested over text they can divide up in many ways, as in (a+)+$ or (\w+\s?)+$. On input that almost matches and then fails at the end, the engine tries every way of splitting the run, and the number of attempts doubles with each extra character. This is called catastrophic backtracking, and it can hang a browser tab or a server thread. A pattern like that will hang this page too, since it uses the same engine.

JavaScript has no atomic groups or possessive quantifiers to switch backtracking off, so the fix is to reshape the pattern: remove the nested quantifier, make the alternatives mutually exclusive, and anchor the pattern so it fails early. Always test a validation pattern against a long string that should not match as well as short ones that should.

How to get your result

  1. 1

    Type the expression in Pattern without the surrounding slashes: \d+ and not /\d+/g. Slashes typed here are matched as literal characters.

  2. 2

    Set Flags to any combination of g, i, m, s, u and y. The tester always searches for every match, so leaving g out does not limit the list to one row.

  3. 3

    Paste the text to search into Test text.

  4. 4

    Lower or raise Max matches to show (default 50, up to 500) if a broad pattern returns more rows than you want.

  5. 5

    Read Summary for Matches, Flags and Groups, then the Matches table: #, Match, Index and Groups. A No matches note appears when nothing was found.

Frequently asked questions

Does it highlight matches in the text or show a replacement preview?
No. Results are a table of matches with their index and groups. There is no inline highlighting, no substitution box and no plain-English breakdown of the pattern. To try a replacement on real text, the Find and Replace tool on this site accepts regular expressions.
Can I test Python, PHP or Java regex here?
Only where the syntax is the same as JavaScript, which covers most everyday patterns: character classes, quantifiers, groups, alternation, anchors and lookaround. Differences to watch for are inline flags such as (?i), possessive quantifiers, \A and \Z anchors, and Python's (?P<name>...) named groups, none of which work in JavaScript.
Why do I get no matches when the pattern looks right?
Common causes are slashes typed around the pattern, doubled backslashes copied from a string literal, a missing i flag when the case differs, ^ or $ used on multi-line text without the m flag, and an unescaped special character such as a dot, bracket or plus sign.
How do I match across multiple lines?
Two flags do different jobs. m lets ^ and $ match at every line break, which is what you need to test each line separately. s lets the dot match newline characters, which is what you need for a match that spans lines. Many multi-line patterns need both.
What does the Groups number in the summary tell me?
How many capture groups the pattern declares, counted from the pattern itself and not from the text. Non-capturing groups (?:...) and lookarounds are not counted. If the number is higher than you expected, a pair of parentheses you meant as plain grouping is capturing.
Why is one of my groups empty?
The group did not take part in that match. With (a)|(b) on the text ab, the first match shows $1=a and an empty $2, and the second shows an empty $1 and $2=b. Optional groups, such as (\.\d{2})?, are empty when the optional part is absent.
Is there a limit on how much text I can test?
There is no fixed size limit on the test text. The table shows at most the number of rows set in Max matches to show, which can be raised to 500. Very large inputs combined with a slow pattern will take longer because everything runs in the page.
How do I use a tested pattern in JavaScript code?
Write it between slashes with the flags after: /\bcat\b/gi. Then text.match(regex) returns the matched strings, and text.matchAll(regex) gives each match with its index and groups, the same information as the table here. If you build it with new RegExp from a string, double every backslash.

Looking for something else? Browse all developer tools or see every tool.