Regex Tester
Last reviewed on April 27, 2026.
Type a JavaScript regular expression and a body of text. Matches highlight in the text as you type, capture groups display below, and a replacement preview shows what String.replace would produce. The regex flavor is JavaScript's, which is close (but not identical) to PCRE — see notes below.
Flag reference
| Flag | Effect |
|---|---|
g | Match all occurrences (without it, only the first match). |
i | Case-insensitive matching. |
m | Multiline — ^ and $ match at line boundaries, not just at the start and end of the whole string. |
s | "Dotall" — . matches newlines too. |
u | Unicode — interprets the pattern and input as Unicode code points (needed for surrogate-pair handling). |
y | Sticky — only match at the regex's lastIndex position. |
d | Indices — populates match.indices for each capture group. |
Quick character-class reference
| Class | Matches |
|---|---|
. | Any character except a newline (unless s flag). |
\d | A digit ([0-9]). |
\D | Anything that is not a digit. |
\w | A word character ([A-Za-z0-9_]). |
\W | Anything that is not a word character. |
\s | Whitespace. |
\S | Non-whitespace. |
\b | Word boundary (between \w and \W). |
[abc] | Any one of a, b, or c. |
[^abc] | Anything except a, b, or c. |
(...) | Capture group; referenced as $1, $2… in replacements. |
(?:...) | Non-capturing group. |
(?<name>...) | Named capture group; referenced as $<name>. |
X* · X+ · X? | Zero or more · one or more · zero or one. |
X{n,m} | Between n and m repetitions. |
X*? · X+? | Lazy (shortest-match) variants. |
X(?=Y) | Lookahead — match X only if Y follows. |
X(?!Y) | Negative lookahead. |
(?<=Y)X | Lookbehind. |
(?<!Y)X | Negative lookbehind. |
Worked example: extracting email addresses
The pattern in the box above is (\w+)@(\w+\.\w+). It captures the local part of an email and the domain in two groups. With the g flag, every occurrence in the text matches. Below the highlighted text you will see one row per match, with each capture group labeled. Switch the pattern to (?<user>\w+)@(?<host>\w+\.\w+) and the rows show named groups instead.
Caveat: this pattern extracts emails; it is not a complete email validator. Real email validation is a long-running argument with no winners — the relevant standard (RFC 5322) allows characters most regexes do not handle. For most jobs, "looks like an email" is good enough.
JavaScript flavor vs. PCRE
JavaScript's regex is close to PCRE but differs in a few practical ways:
- No possessive quantifiers (
X*+,X++) — use atomic groups and lookarounds when you need them. - No
\K"reset match start" operator. - Unicode property escapes (
\p{Letter}) require theuflag. - Character class set notation (
[a-z--[ei]]) requires thevflag in modern engines. - Replacement string syntax uses
$1for groups, not\1.
Common mistakes
- Forgetting the
gflag. Without it, only the first match is found. The match list will look truncated; the replace will only replace once. - Greedy quantifiers eating too much.
<.*>on<a>text</a>matches the whole thing. Use the lazy form<.*?>or be explicit:<[^>]*>. - Anchors that do not match what you think. Without the
mflag,^and$match the start and end of the whole string, not of each line. Addmwhen scanning multi-line input. - Catastrophic backtracking. Patterns like
(a+)+bon input that ends without abcan blow up exponentially. If your pattern is slow on certain inputs, look for nested quantifiers and replace them with possessive-style alternatives or atomic groups. - Trying to parse HTML. Use the DOM. Regex on HTML works for the simplest cases and silently fails on the rest. Same for parsing programming language code, JSON, or any nested structure.
Where this fits with the other tools on the site
For testing patterns against URL-encoded data, decode it first with the URL encoder. For matching inside JSON values, format the JSON first with the JSON formatter so that line breaks and indentation are predictable. For escaping a literal string into a regex, every metacharacter (. * + ? ( ) [ ] { } | ^ $ \) needs a backslash in front of it.