Regex Tester
Test JavaScript regex patterns against any text. Capture groups, named groups, flags, replace mode. Browser-only.
Regex Tester
Click Run to execute — avoids re-running on every keystroke. Text is capped at 10,240 chars and execution at 1 second to prevent catastrophic backtracking from freezing the tab. Runs in your browser.
What next?
How it works
Why regex is worth learning (and when not to use it)
Regular expressions are the universal text-parsing tool — every modern language has them, the syntax mostly transfers, and they're the right answer for ~80% of "find this pattern" jobs. The remaining 20%:
- Parsing HTML or XML with regex — don't. Use a real parser (
DOMParserin the browser,cheerioin Node). - Parsing JSON with regex — don't. Use
JSON.parse. - Email validation with regex — usually wrong; use a library or your auth provider's built-in.
- Deeply nested or balanced delimiters — regex can't (formally) match these. Use a parser.
For everything else: extracting URLs, splitting CSV-ish text, validating phone formats, matching log lines, finding TODO comments — regex is the right tool.
The five concepts worth memorizing
You can write 90% of useful regex with these five primitives:
- Character classes:
\d(digit),\w(word char),\s(whitespace), and their uppercase negations. Plus custom classes:[a-z],[^xyz]. - Quantifiers:
*(0+),+(1+),?(0 or 1),{n,m}(between n and m). Add?to make them lazy:*?,+?. - Anchors:
^(start),$(end),\b(word boundary). - Groups:
(…)captures,(?:…)doesn't capture (cheaper),(?<name>…)captures with a name. - Alternation:
a|b—aorb.
Combine these and you can match most things. The rest of regex syntax (lookahead, backreferences, unicode classes, etc.) is occasionally useful but skippable for daily work.
The JavaScript-specific quirks
JS regex (per ECMAScript) is almost PCRE but not quite:
- No
(?#comment)— JS regex has no comment syntax. Comment your code instead. .does NOT match newlines unless you set thesflag (dotAll). Frequent source of "why isn't this matching?".\buses ASCII word boundaries by default. Setting theuflag changes this. Adduwhenever you handle non-ASCII text.- Named groups use
(?<name>…)— Python-style. JS adopted this in 2018; assume modern browsers/Node. - Backreferences in replace use
$1,$2,$<name>— not\1like Perl.
Other languages do things slightly differently. PCRE is a near-superset of JS regex; Python re is similar but uses (?P<name>…) for named groups; Go's regexp package is RE2 (no backreferences, no lookahead, but linear-time guaranteed). Don't paste a Python regex into JS without checking.
Catastrophic backtracking — the one performance trap
A pattern like (a+)+b matched against aaaaaaaaaaaaaaaaaaaaa (no final b) takes exponential time as the input grows. The regex engine tries every possible way to partition the as between the two quantifiers, gives up, then tries the next combination. With 20 as and no b, that's millions of attempts.
This tool sets a 1-second execution cap precisely because pathological patterns can hang a browser tab indefinitely.
Avoidance rules:
- Don't nest quantifiers without thinking.
(a+)+,(a*)*,(a|aa)+are red flags. - Use atomic groups or possessive quantifiers if your engine supports them (JS doesn't — use lookahead tricks).
- Be specific.
[^"]*"matches until the next quote; better than.*"which can backtrack. - Test with adversarial input. A pattern that handles your happy path may explode on input ending in a few mismatched chars.
If a pattern is taking too long, the answer is rarely "add more +" — it's usually "rewrite to be linear", or "use a real parser".
How this tool helps
- Paste a pattern and text; matches highlight live.
- Flags are toggleable; you see them in the pattern preview (
/foo/gi). - Capture groups and named groups appear under each match.
- Replace mode previews the result of
text.replace(pattern, replacement). - 1-second execution cap catches catastrophic backtracking before your tab freezes.
A cheatsheet of patterns that work
| Goal | Pattern |
|---|---|
| Match digits | \d+ |
| Match a word | \w+ |
| Match an email-ish string | [\w.+-]+@[\w-]+\.[\w.-]+ |
| Match a URL-ish string | https?:\/\/[^\s)]+ |
| Match an ISO date | \d{4}-\d{2}-\d{2} |
| Match an IPv4 | \b(?:\d{1,3}\.){3}\d{1,3}\b |
| Match an HTTP status code | \b[1-5]\d{2}\b |
| Strip leading/trailing whitespace | replace ^\s+|\s+$ with `` |
| Collapse multiple spaces | replace \s+ with |
Not bulletproof — the email one accepts plenty of invalid addresses — but good enough for filtering and extraction.
Privacy
All regex matching runs in the browser via the native RegExp engine. We don't send your patterns or text anywhere.
Related tools
- Text Case Converter — change the case of matched text.
- Slugify — turn arbitrary text into URL-safe slugs (a higher-level regex transformation).
- JSON Formatter — when your matches end up needing JSON formatting.
FAQ
What is catastrophic backtracking?
A regex performance pathology where the engine explores exponentially many ways to partition input across nested quantifiers. Patterns like (a+)+b against aaaaaaaa… (no b) hang indefinitely. This tool caps execution at 1 second and reports the issue.
Greedy vs lazy quantifier?
* and + are greedy — they match as much as possible. Add ? (*?, +?) to make them lazy — match as little as possible. For <.*> on <a><b> you get the whole string; <.*?> gives just <a>.
Why is matching HTML hard?
HTML isn't a regular language — it has arbitrary nesting that regex can't (formally) handle. You can match very specific simple cases, but real-world HTML has comments, CDATA, malformed tags, and weird whitespace. Use DOMParser in the browser or cheerio in Node instead.
How do I match Unicode characters?
Add the u flag. Then \w covers more characters, and you can use \p{Letter} / \p{Script=Vietnamese} style Unicode property escapes (Node 10+/all modern browsers).
Difference between (?:…) and (…)?
(…) creates a numbered capture group, accessible as $1 etc. (?:…) groups for the quantifier without capturing. Use non-capturing when you don't need the value — it's slightly faster and keeps your capture indices clean.
What's lookahead and lookbehind?
Zero-width assertions: (?=…) matches if … follows but doesn't consume it; (?!…) matches if … does NOT follow; (?<=…) and (?<!…) are the same for what precedes. Useful for "match X but only when not followed by Y" without consuming Y.
JS regex vs PCRE — what's different?
JS is mostly a subset of PCRE with some differences. No inline comments (?#…), no possessive quantifiers, named groups use (?<name>…) not (?P<name>…) (which is Python). Don't paste random regex from the internet into JS without checking.
Why does my pattern not match newlines?
. doesn't match \n by default. Add the s flag (dotAll) to make . match any character including newline. Alternative: use [\s\S] which always matches anything.