Regex tester and debugger
Test JavaScript regular expressions live with highlighted matches, capture and named group tables, a replace preview, flags, and a built-in cheatsheet.
- Runs in your browser
- Nothing you enter is sent
- Free, no account
Regular expressions are compact, powerful, and occasionally infuriating. Test them here before shipping them into production code.
How to test a regular expression
- Type the pattern without surrounding slashes — it is passed straight to
new RegExp(). - Tick the flags you need.
gis on by default, because without it only the first match is found. - Paste the text to match against. Matches are highlighted as you type, alternating colours so adjacent matches stay distinguishable.
- Read the match table for exact positions and every captured group, numbered and named.
- Turn on the replace preview to see the result of
String.replacewith your replacement string.
Which flavour is this?
The JavaScript (ECMAScript) engine built into your own browser. That means the behaviour you see here
is exactly the behaviour your front-end code, your Node service and your JSON schema validator will
show — including the parts JavaScript does differently from PCRE. Notably, JavaScript has no atomic
groups, no possessive quantifiers, no recursion, no \A or \z anchors, and
lookbehind is variable-length (which most other engines do not allow).
Catastrophic backtracking, and why this page cannot freeze
A regular expression engine that hits a dead end backtracks and tries another path. With nested
quantifiers such as (a+)+$, the number of paths grows exponentially with the length of the
input: 25 characters of a followed by a ! can take longer than the age of the
universe. This is the mechanism behind ReDoS, a real denial-of-service class that has taken down
production services.
A running regular expression cannot be interrupted on the main thread, so this tool evaluates every pattern inside a Web Worker with a two-second budget. If the budget expires the worker is terminated and you get an explanation instead of a locked-up tab. That is also a useful signal in itself: if a pattern trips the guard here, do not ship it anywhere user input can reach.
How to fix a backtracking pattern
- Make sure two parts of the pattern cannot match the same text.
(\s*\w+)*is ambiguous;[\s\w]*is not. - Replace
.*between delimiters with a negated class:"[^"]*"instead of".*". - Anchor the pattern with
^and$so the engine cannot retry from every position. - For deeply structured input, stop using a regular expression and write a parser.
Flags at a glance
| Flag | Name | Effect |
|---|---|---|
g | global | Keep searching after the first match; required for replace-all and for the match list |
i | ignoreCase | Case-insensitive matching |
m | multiline | ^ and $ match at each line break rather than only at the ends of the string |
s | dotAll | . also matches newlines |
u | unicode | Treat the pattern as code points; required for \p{…} property escapes and correct handling of astral characters |
y | sticky | Match only at lastIndex; useful for tokenisers, and it will find far fewer matches than g |
Named capture groups
Write (?<year>\d{4}) and the match table gains a column for
year. In your code you read it as match.groups.year, and in a replacement
string as $<year>. Named groups make a pattern survive editing: adding a group in
the middle renumbers everything after it, but names do not move.
A note on parsing HTML and email
The preset patterns here are pragmatic, not exhaustive. The full grammar for an email address (RFC 5322) permits quoted strings, comments and nested parentheses, and the "correct" regular expression for it runs to several thousand characters while still not proving the address exists. Match loosely, then verify by sending mail. Likewise, HTML is not a regular language — a tag matcher is fine for a quick grep over a log file, and wrong for anything that must be correct.
Your test data stays here
Patterns and subject text are evaluated by your browser's own engine inside a worker. Nothing is transmitted, so production log samples, customer records and unreleased content are safe to paste.
Questions
Which regex flavour does this use?
The JavaScript (ECMAScript) engine built into your browser, so behaviour matches exactly what your front-end or Node code will do. PCRE-only constructs such as atomic groups or recursion are not supported.
What happens if my pattern hangs the browser?
Nested quantifiers can cause catastrophic backtracking. Matching runs under a time budget and a match-count cap; if the budget is exceeded the run is abandoned and you get a warning naming the likely cause instead of a frozen tab.
How do I use named capture groups?
Write (?<name>…) in the pattern and reference it as $<name> in the replacement. Named groups get their own column in the match table alongside the numbered ones.
What does the y (sticky) flag do?
It anchors each attempt at lastIndex, so matching only succeeds if it starts exactly where the previous match ended. It is useful for hand-written tokenisers and will produce far fewer matches than g on the same pattern.
Is my test data sent anywhere?
No. The pattern and the subject text are evaluated by your own browser RegExp engine. Nothing is logged or transmitted, so production log samples are safe to paste.