How to use this Regex Tester
Enter a regex pattern, choose the flags you want, paste your sample text, and run the test.
The tool shows matched text in a preview panel and lists detailed match information in the
results area.
- Enter your regex pattern.
- Select the flags you want to use.
- Paste or type the test text.
- Click Test Regex.
- Review highlighted matches and detailed results.
Example pattern
[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-z]{2,}
Common use cases
- Email validation patterns
- Log parsing
- Text extraction
- Form input testing
- String matching and cleanup
Catastrophic backtracking: the regex that hangs your server
A regex engine that backtracks (JavaScript's included) can be pushed into exponential time by
a pattern that lets the same text be matched many ways. The classic shape is a quantifier
inside a quantifier: (a+)+$. Against a string of as followed by one
! — which cannot match — the engine tries every possible way to split
the as between the inner and outer + before finally giving up. Each
extra character roughly doubles the work, so a few dozen characters can take seconds and a
hundred can hang the thread for minutes.
This is a real denial-of-service vector, not a curiosity, whenever a regex runs against
attacker-controlled input — validating a form field, parsing a header, filtering a log
line. It is called ReDoS. The tells are nested quantifiers
((x+)+, (x*)*) and overlapping alternations ((a|a)*).
The fixes: avoid nesting quantifiers, make the pieces mutually exclusive so there is only one
way to match, anchor the pattern, or use a non-backtracking engine (like Rust's
regex or Google's RE2) for untrusted input.
Greedy vs lazy quantifiers
By default quantifiers are greedy: .* grabs as much as it can,
then backtracks to give back the minimum needed for the rest of the pattern to match. So
<.*> against <b>hi</b> matches the entire
string, not just <b>, because .* swallows everything and only
retreats to the final >. Add a ? to make a quantifier
lazy — <.*?> — and it takes as little as
possible, matching just <b>. This one character is behind a huge share of
“my regex matched way too much” bugs.
A sharper tool for the same job is a negated character class:
<[^>]*> says “up to the next >” directly,
which is both clearer and faster than lazy matching because it never has to backtrack.
Why you can't parse HTML with a regex
The famous answer is “because HTML is not a regular language,” and it has a
concrete meaning. Regular expressions describe patterns with no arbitrary nesting; HTML nests
to any depth — a <div> inside a <div> inside a
<div> — and a classic regex has no way to count matching open and
close tags. You can approximate for a fixed depth, but real-world markup then defeats you with
comments, CDATA, attributes containing >, unclosed tags browsers happily
accept, and encoding variations.
Regex is fine for a small, well-defined extraction from text you control. For anything
structural — pulling links, rewriting markup, sanitising input — use a real
parser (DOMParser in the browser, an HTML parsing library on the server). The
same caution applies to JSON and other nested formats: parse them, don't pattern-match them.
Anchors, Unicode, and capture groups
Three details that quietly change what a pattern matches:
- Anchors and multiline.
^ and $ mean the start and end of the whole string — until you add the m flag, which makes them match at the start and end of every line. Forgetting this is why a validator sometimes accepts input with a sneaky newline; when validating a single-line field, anchor carefully.
- Unicode. In JavaScript
\w and \d are ASCII-only: \w is literally [A-Za-z0-9_] and never matches é or 数. The u flag turns on proper Unicode handling and unlocks \p{...} property escapes (for example \p{L} for any letter), which is what you want for real international text.
- Capture vs non-capturing. Plain parentheses
(...) capture — they store the match and shift every later group's number. When you only need grouping for a quantifier or alternation, use (?:...); it keeps your capture numbers stable and is marginally faster. Reach for named groups (?<year>\d{4}) when you actually consume the captures.
This tests JavaScript's regex engine specifically
The tool builds a real RegExp from your pattern and flags and runs it in your
browser, so everything stays local — nothing is uploaded. The flip side is that you are
testing JavaScript's regex dialect, which is not identical to PCRE, Python's
re, Java, or Go. Differences that trip people up: JavaScript gained lookbehind
((?<=...)) only relatively recently; it has no possessive quantifiers or
atomic groups (the usual defence against the backtracking above); \w and
\d are ASCII unless you add u; and the s
(“dotall”) flag is needed for . to match a newline. A pattern that
works here can behave differently in your backend language, so test it in the engine that
will actually run it.
Frequently Asked Questions
Why does my regex freeze the browser or server on certain inputs?
Catastrophic backtracking. Patterns with nested quantifiers like (a+)+ or
overlapping alternations explode exponentially against input that almost
matches, so a short string can take minutes. On attacker-controlled input this is a real
denial-of-service (ReDoS); rewrite the pattern or use a non-backtracking engine.
Why does my pattern match more text than expected?
Quantifiers are greedy by default, so .* grabs as much as possible. Make it
lazy with ? (.*?) to take the least, or better, use a negated
class like [^>]* to match up to a delimiter without backtracking at all.
Can I use regex to extract data from HTML?
Not reliably. HTML nests arbitrarily and a regular expression can't track matching tags,
so comments, attributes, and unclosed tags will break it. Use a real parser
(DOMParser or a server-side HTML library) for anything structural; keep regex
for small, flat text extraction.
Why doesn't \w match accented or non-Latin letters?
In JavaScript \w is ASCII only — exactly [A-Za-z0-9_] —
so it skips characters like é or 数. Add the
u flag and use Unicode property escapes such as \p{L} to match
letters in any script.
Will a pattern that works here also work in Python or PCRE?
Not always. This runs JavaScript's regex engine, which differs from PCRE, Python, Java,
and Go in lookbehind support, atomic/possessive quantifiers, Unicode defaults, and the
dotall flag. Test any important pattern in the language that will actually execute it.
Does this tool upload my text or pattern?
No. It compiles your pattern into a native RegExp and runs it against your
text entirely in your browser. Nothing is sent to a server, so it works offline and your
input never leaves the page.