/ developer & network toolbox
← all tools

$ re

runs locally

Regex Tester

Test a JavaScript regular expression against sample text with live match highlighting and capture groups.

regex — invoker.tools

2 matches

foo@bar.com and info@example.com
@0foo@bar.com
@16info@example.com

JavaScript RegExp engine, runs in your browser.

About the Regex Tester

This regex tester lets you write a regular expression, set its flags and run it against sample text with live match highlighting. As you type, it shows how many matches were found, highlights each one in the text, and breaks out every capture group so you can see exactly what your pattern grabs and where it grabs it from.

Use it to build and debug patterns before they end up in code: form validation, log parsing, search-and-replace, scraping, routing rules or a data-cleaning script. Writing a regex blind and only finding out it is wrong when a test suite or a production log fails is slow. Testing it live against real sample text first catches off-by-one anchors, wrong quantifiers and unescaped metacharacters before they cost you anything.

The engine behind this tester is the same ECMAScript RegExp engine your browser already runs, a backtracking NFA implementation that supports character classes, quantifiers, groups, backreferences, lookarounds and named captures. There is no separate parser or reimplementation involved, so whether a pattern matches at all agrees exactly with `new RegExp(pattern, flags)` in your own JavaScript code, whether that runs in a browser or in Node. One difference: this tester always scans for every match internally, similar to `matchAll`, so the count and highlighting stay complete whether or not you type the g flag yourself; a single call like `String.prototype.match` or `RegExp.prototype.exec` in your own code still needs g to return more than the first match.

Everything happens client-side. The pattern and the sample text are evaluated entirely in your browser's own JavaScript engine and are never sent to a server, logged or stored. That makes it safe to paste real log lines, real email addresses or other sensitive test data while you iterate on a pattern.

If you specifically need to reason about how a pattern behaves in Python's `re` module, in .NET's `Regex` class, or want a deeper JavaScript-specific reference on flags and lookbehind support, see the dedicated Python,NET and JavaScript regex tester pages, which use this same engine but call out where each flavor's syntax and semantics diverge from it.

How to use it

  1. Enter your regular expression pattern in the pattern field, without the surrounding slashes.
  2. Set flags such as g (global), i (case-insensitive), m (multiline) or s (dot matches newline).
  3. Paste or type the sample text you want to test the pattern against.
  4. Watch the match count, the highlighted matches and any capture groups update live as you type, with no submit button to press.
  5. Open a match's capture groups to confirm each parenthesized part of the pattern grabbed the value you expected.
  6. Adjust the pattern, quantifiers or flags and re-check until every match (and non-match) is correct.
  7. Copy the finished pattern into your code once the test text covers the edge cases you care about.

Examples

  • Pattern ^\d{4}-\d{2}-\d{2}$ with no flags matches an ISO date like 2026-07-29 only if the whole line is exactly that date, because ^ and $ anchor to the full string without the m flag.
  • Pattern (\w+)@([\w.-]+) with flag g run against "foo@bar.com, admin@example.co.uk" reports two matches, each with group 1 as the local part and group 2 as the domain.
  • Pattern \bcolou?r\b with flags gi matches both "color" and "colour" in a document regardless of case, because the u? makes the u optional.
  • Pattern (?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2}) shows named groups year, month and day for each date, instead of numbered group 1, 2, 3.
  • Comparing <.+> against <.+?> on the text "<b>bold</b> and <i>italic</i>" shows the difference between greedy and lazy: the greedy version matches the entire string from the first < to the last >, the lazy version matches <b> and <i> as two separate, shorter matches.
  • Pattern \d+(?=px) with flag g against "width: 640px; height: 480px;" matches 640 and 480 but not the px itself, because a lookahead checks for px without including it in the match.

Character classes and quantifiers

Character classes decide which single characters a position in the pattern can match. The shorthand classes \d, \w and \s (and their negations \D, \W, \S) cover digits, word characters and whitespace. A custom class in square brackets, like [aeiou] or [^0-9], matches any one character in (or, with ^, not in) that set; ranges such as [a-z] and [A-Z0-9] combine several ranges in one class.

Quantifiers control how many times the preceding token may repeat. By default they are greedy: they try to match as much text as possible and only give characters back if the rest of the pattern would otherwise fail. Adding a trailing ? to a quantifier makes it lazy, matching as little as possible instead.

  • * matches zero or more of the preceding token, greedy by default
  • + matches one or more of the preceding token, greedy by default
  • ? matches zero or one of the preceding token, and also marks a quantifier as lazy when it follows one
  • {n} matches exactly n repetitions, {n,} matches n or more, {n,m} matches between n and m
  • *?, +?, ??, {n,m}? are the lazy variants of the four quantifiers above, matching as few characters as the pattern allows

Greedy vs lazy matching in practice

Greedy quantifiers are the reason a pattern like <.+> against HTML text tends to span far more than one tag: .+ first grabs everything to the end of the string, then backtracks character by character until a trailing > lets the rest of the pattern succeed. Against "<b>bold</b> and <i>italic</i>" that means the match runs from the very first < to the very last >, swallowing the two closing tags and the text between them.

Switching to <.+?> makes the quantifier lazy: it tries to match as little as possible first and only extends when forced to, so it stops at the first > it can reach. Run with the g flag that now produces two short matches, <b> and <i>, instead of one long one. As a rule of thumb, prefer a negated character class such as <[^>]+> over a lazy dot when the content you are excluding is known (in this case, anything but >), because it is both clearer and immune to accidentally matching across a boundary the lazy quantifier would have skipped past on unusual input.

Lookarounds: lookahead and lookbehind

Lookarounds assert that something does or does not appear next to a position, without consuming it as part of the match. A positive lookahead (?=...) requires what follows to match without including it; a negative lookahead (?!...) requires it not to match. Lookbehind works the same way but checks backwards: (?<=...) for positive, (?<!...) for negative. Lookbehind is a newer addition to JavaScript (ECMAScript 2018) and is supported by all current evergreen browsers, but it is worth testing directly rather than assuming support if your code has to run in an older environment.

They are most useful for validating context around a value without capturing the context itself: matching a price only when preceded by a currency symbol, matching a word only when not immediately followed by a colon, or requiring a password to contain a digit somewhere without pinning down its exact position.

  • (?=...) positive lookahead, matches only if followed by ...
  • (?!...) negative lookahead, matches only if NOT followed by ...
  • (?<=...) positive lookbehind, matches only if preceded by ...
  • (?<!...) negative lookbehind, matches only if NOT preceded by ...

Common mistakes, including catastrophic backtracking

Most broken patterns come down to a handful of recurring mistakes: forgetting to escape a literal dot or dollar sign, anchoring only one end of the pattern and being surprised the other end is unbounded, or forgetting the g flag and wondering why only the first match ever shows up. A subtler and more serious mistake is writing a pattern with nested or overlapping quantifiers, which can trigger catastrophic backtracking: on certain non-matching input, the number of ways the engine can try to backtrack grows exponentially, and the match can take seconds, minutes or effectively forever to fail. Because this tester runs the pattern in your browser's own regex engine with no separate timeout, a genuinely pathological pattern can make the tab unresponsive the same way it would in your own code, which is itself a useful, honest warning sign before that pattern ever reaches production.

  • Nested quantifiers like (a+)+ or (a*)* against input that almost, but does not quite, match
  • Overlapping alternation inside a repeated group, such as (a|a)+ or (a|ab)+c
  • Unanchored patterns with .* on both ends run against very large blocks of text
  • Forgetting to escape special characters (. * + ? ( ) [ ] { } ^ $ | \\) that appear literally in the target text

Frequently asked questions

What is a regex tester?

A regex tester is a tool that runs a regular expression against sample text and shows you what it matches, so you can build and debug the pattern interactively instead of guessing and re-running your own code every time.

What is the difference between this and a regex checker?

A checker usually only validates that a pattern is syntactically valid. This tool goes further: it actually runs the pattern against your sample text and shows every match, its position, and its capture groups, so you see behavior, not just validity.

What regex flavor does this online tester use?

It uses JavaScript (ECMAScript) regular expressions, the same RegExp engine your browser runs. That makes it a direct match for JS and Node code, and a close but not identical reference if you are really writing Python or .NET regex, since those flavors differ in places.

How do I test a regular expression online without installing anything?

Paste the pattern into the pattern field on this page, set any flags you need, and paste sample text into the test field. Results update live in the browser as you type, with nothing to install and nothing sent to a server.

Why is my global (g) flag not finding every match?

In your own code, yes: without g a single call like String.prototype.match or RegExp.prototype.exec only returns the first match. This tester is more forgiving, it always scans for every match internally so the count and highlighting are complete regardless of whether you typed g. Still add g when you copy the pattern into real code, since match() and exec() need it there to return more than the first result.

Can I use named capture groups and lookbehind here?

Yes. Named groups like (?<year>\d{4}) and lookbehind assertions like (?<=\$) are both part of modern JavaScript and work here exactly as they would in your browser's own JS engine, since that is what this tester runs on.

Is my test text uploaded anywhere?

No. The pattern and sample text are evaluated entirely client-side in your browser and are never transmitted to a server, so it is safe to test against real log lines or other sensitive sample data.

How do I test a regex against multiple lines of text?

Add the m (multiline) flag so ^ and $ match the start and end of each line rather than only the start and end of the whole string. Add the s (dotAll) flag as well if you also need . To match newline characters.

Why did my browser tab freeze while testing a pattern?

That is almost always catastrophic backtracking: a pattern with nested or overlapping quantifiers can force the regex engine into exponential work on certain non-matching input. If a pattern hangs here, rewrite the quantifiers (often by replacing a lazy dot with a specific negated character class) before it ever reaches production code.

Does this tester support Unicode property escapes like \p{Emoji}?

Yes, as long as the u (or v) flag is set, since Unicode property escapes are only enabled under that flag in JavaScript. Without it, \p is treated as a literal p rather than a property escape.

More text tools