Regex Tester — Free Online Tool on Toolpile
Every tool you need, one place
PDF, Image, AI, Dev, and Business tools — free, private, no signup.
Toolpile uses cookies for analytics and ads. The tools themselves keep your files in the browser — that doesn't change. Read the full policy
PDF, Image, AI, Dev, and Business tools — free, private, no signup.
About Regex Tester
Regex is the developer skill where a 30-minute investment saves a week of work over the next decade — and where the cost of getting it wrong silently corrupting data is enormous. A good regex tester isn't about syntax help; it's about seeing exactly what your pattern matches, what it captures, and where it backtracks catastrophically. Here's how this one is set up and the patterns most engineers get wrong.
There is no single regex language. JavaScript regex (ECMAScript), Python `re`, PCRE (Perl-Compatible Regular Expressions, used in PHP and grep), .NET regex, Java `java.util.regex`, Go `regexp`, and Rust `regex` all share a common core but differ on specifics. Lookbehinds, named captures, possessive quantifiers, and Unicode property classes are particularly inconsistent. A pattern that works on regex101.com against the PCRE engine may behave differently in a Node.js script using the JS engine.
This tool runs the **JavaScript regex engine** (V8's RegExp) — same as runs in your browser code, your Node.js backend, your Cloudflare Worker. If you're testing for use in JS, results here match production exactly. If you're testing for Python or PCRE, the syntax overlaps but verify any feature that's not in basic alphanumeric matching: JS lacks possessive quantifiers, has no `(?P<name>...)` syntax (use `(?<name>...)` instead), and has no `\K` operator.
Two specific JS-vs-PCRE traps: (1) JS lookbehinds shipped only in 2018 (Chrome 62, Node 10) — older runtimes don't support them. (2) Unicode property classes (`\p{Letter}`) need the `u` flag in JS; without it, `\p` is a literal `p`. If you're copying regex from Stack Overflow without checking the language tag, both bite hard.
Regex engines work by trying each possible match path. Greedy quantifiers (`*`, `+`) and alternation (`|`) explode the search space when the input is long and the pattern can match the same characters multiple ways. The classic failure mode is patterns like `(a+)+$` against `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!` — the regex engine tries every possible split of the a's between the two `+` quantifiers before deciding the `!` makes the whole thing fail. Time complexity goes from linear to 2ⁿ. A 35-character input that would normally match in microseconds takes minutes; 50 characters takes hours.
The most common production bug: an email-validation regex with nested quantifiers, run against malicious user input, freezes the request thread. Cloudflare's 2019 outage was a regex like this — `.*(?:.*=.*)` matched an attack pattern and ground every request thread to a halt for 30 minutes.
Defences in 2026: (1) avoid nested quantifiers — `(a+)+` should always be `a+`. (2) Make patterns possessive or use atomic groups when the language supports them (PCRE: `(?>a+)`; not in JS). (3) For untrusted input, use `re2`-style engines (Google's re2, Rust's regex crate) that guarantee linear time. (4) Set a regex timeout if your runtime supports it (Node has no built-in; Cloudflare Workers have a CPU limit that effectively caps it).
This tester shows execution time per test. If your pattern takes >100ms on a 1KB input, it's vulnerable to ReDoS (Regular expression Denial of Service). Refactor before shipping.
**Greedy** (default): `.*` matches as much as possible, then backtracks if the rest of the pattern fails. `<.*>` against `<a><b>` matches `<a><b>` (the whole string) — not just `<a>`. Most beginners trip here, write what they think is a tag-matcher, and silently match across whole HTML files.
**Lazy** (with `?` after the quantifier): `.*?` matches as little as possible, expanding only when forced. `<.*?>` against `<a><b>` matches `<a>` first, then `<b>` — the more common intent. Use lazy quantifiers any time you're matching content between delimiters.
**Possessive** (with `+` after the quantifier in PCRE): `.*+` is greedy with no backtracking. Once it matches, the engine doesn't reconsider. Avoids catastrophic backtracking by design. Not available in JavaScript regex; use atomic groups `(?>...)` in PCRE for the same effect, or refactor the pattern to be unambiguous.
The mental model: think of a regex match as a vending machine that takes characters in. Greedy stuffs in as many as it can, then spits some back if needed. Lazy takes the bare minimum, asks for more only when needed. Possessive takes what it takes and refuses to give any back — fastest but rejects valid matches that need flexibility. Match the mode to the data, not just the syntax.
Why doesn't my regex match the way I expect?
Most common causes: (1) you're matching the wrong flavour — JS vs PCRE syntax differs on lookbehinds, named captures, and Unicode property classes. (2) Quantifier is greedy when you wanted lazy — try `.*?` instead of `.*`. (3) `.` doesn't match newlines unless the `s` flag is set — multiline test strings get partial matches. (4) Anchors `^` and `$` mean line-start/end only with the `m` flag, otherwise string-start/end. Check each before assuming the engine is broken.
Should I use regex to parse HTML / JSON / email addresses?
Generally no. HTML and JSON have grammar that nested-element regex can't reliably match — use a real parser (DOMParser, JSON.parse). Email addresses have a famous 6,400-character regex that almost validates RFC 5322; in practice, validate that the string contains an `@` and a `.` after it, and let the SMTP server be the real check. Regex shines on simple lexical patterns: log lines, timestamps, identifiers. It struggles with anything recursive or context-dependent.
What's the difference between [^abc] and (?!abc)?
[^abc] is a character class — matches any single character that is not a, b, or c. (?!abc) is a negative lookahead — asserts that the upcoming three characters are not 'abc' but doesn't consume them. Different scopes: character class is always 1 character; lookahead is a zero-width assertion about the surrounding string. Beginners conflate them; the bug is usually using one when the other is what's needed.
How do I match a literal dot or backslash?
Escape it with a backslash: `\.` for a literal dot, `\\` for a literal backslash (two backslashes in source code because the string itself escapes once before the regex engine sees it). Inside a character class, dot doesn't need escaping (`[.]` and `[\.]` are equivalent), but escaping is harmless and clearer.
Why is my regex slow?
Almost always nested quantifiers or alternation that can match the same characters multiple ways. `(a+)+`, `(\w+)*`, `(.|\s)*` are classic offenders. Refactor: replace `(\w+)*` with `\w*`. Replace `(.|\s)*` with `[\s\S]*` (a single character class is faster than alternation). If the regex is fundamentally ambiguous, possessive quantifiers (PCRE) or atomic groups eliminate the backtracking. JS users without those features should rewrite to make the pattern unambiguous.