Skip to content
Processing locally — files never leave your device

Regex Tester

Test JavaScript regular expressions with live match highlighting, group capture display, and replacement preview.

//
3 matches
Send mail to alice@example.com or bob@test.org. Try also: charlie@foo.io.
#1 @13 alice@example.com
#2 @34 bob@test.org
#3 @58 charlie@foo.io

How to use Regex Tester

  1. Enter your regular expression in the pattern box.
  2. Add flags (g, i, m, s, u, y) — the global flag is on by default for match-all behaviour.
  3. Paste the text you want to test against in the larger area below.
  4. Matches highlight in real time. Capture groups and named groups appear underneath.

How a regular expression actually matches

A regex is a tiny program. The engine walks your text one position at a time, trying to satisfy the pattern from that point; when a piece of the pattern fails, it backtracks and tries another interpretation. Understanding that walk is the difference between patterns that work and patterns that almost work. Because the engine doing that walk is the very same one shipped in your browser, what lights up here is exactly what will match in Node or any modern browser — no server round-trip, no flavour mismatch.

A real pattern, character by character

Take /^\d{4}-\d{2}-\d{2}$/, a strict ISO-date matcher. ^ anchors the match to the start of the string, so nothing may precede the date. \d{4} demands exactly four digit characters — the year. The literal - must follow. \d{2} takes two digits for the month, another hyphen, two more digits for the day, and $ anchors the end. Against 2026-06-11 every piece consumes its text and the match succeeds; against 2026-6-11 the second \d{2} finds only one digit before the hyphen and the whole match fails. Note what it does not check: 9999-99-99 passes, because regex validates shape, not meaning.

Flag cheatsheet

  • g — global, return all matches instead of just the first
  • i — case-insensitive
  • m — multiline; ^ and $ match at line boundaries
  • s — dotAll; "." also matches newline characters
  • u — Unicode; enables \p{...} property escapes
  • y — sticky; matches only at lastIndex (advanced)

Capture groups: pulling data out of a match

Parentheses do double duty: they group, and they capture. /(\d{4})-(\d{2})-(\d{2})/ matches the same dates as before but also exposes the year, month, and day as groups 1, 2, and 3. Named groups read better in real code: /(?<year>\d{4})-(?<month>\d{2})/ lets you write match.groups.year instead of remembering an index. If you need parentheses only for grouping — say, around an alternation — use a non-capturing group (?:...) so you do not pollute the group numbering.

Catastrophic backtracking: the pitfall that freezes pages

Backtracking is usually cheap, but nested quantifiers can make it exponential. The pattern (a+)+b against a string of 30 a characters and no b forces the engine to try every way of splitting the run between the inner and outer + — roughly 2^30 attempts before it can report failure. The fix is to remove the ambiguity: here, a+b matches the same strings with zero risk. As a rule, never apply a quantifier to a group whose contents can already repeat, and be suspicious of alternations whose branches overlap, like (\w|\d)+. This matters in production because user-supplied input hitting a vulnerable pattern is a denial-of-service vector (ReDoS).

Patterns worth memorizing

Email-ish: /^[\w.+-]+@[\w-]+\.[\w.-]+$/. URL-ish: /https?:\/\/\S+/g. Whitespace squash: /\s+/g. None are perfect — real-world inputs always contain edge cases. Use this playground to confirm before shipping a pattern to production, and prefer an anchored, specific pattern over a clever general one: the next person to read it will thank you.

Related tools

  • Find & Replace — apply a pattern across text and rewrite the matches in one pass.
  • Email Extractor — pull every address out of a blob of text without writing the regex yourself.
  • JSON Formatter — pretty-print the structured data your patterns often parse.
  • URL Encoder — encode or decode the URLs your patterns match against.

Frequently asked questions

Which regex flavour does this use?
JavaScript regex (ECMAScript). It supports lookbehind, named groups, Unicode property escapes (\p{...}), and the y (sticky) flag. Patterns from Python, PCRE, or .NET may not transfer 1:1 — most do, but features like atomic groups and possessive quantifiers do not exist in JS.
How do I match across newlines?
By default, "." does not match newlines. Add the s flag (dotAll) and "." will match \n, \r, and other line terminators. Use the m flag if you need ^ and $ to match at line boundaries inside a multiline string.
My regex hangs the page — why?
Catastrophic backtracking. Patterns like (a+)+b on a long string of "a" characters can take exponential time. Avoid nested quantifiers; if you need them, use atomic-style patterns or anchor your alternations.
Can I safely test against real log data or production strings?
Yes. The pattern is compiled and executed by your browser’s own JavaScript engine, so the sample text — even if it is a chunk of real logs or customer records — is matched locally and never uploaded.
Can I see capture groups?
Yes — every match shows its numbered groups and any named groups (?<name>...). The tool displays them in a table beneath each match.
What is the difference between greedy and lazy quantifiers?
Greedy quantifiers (*, +, {n,}) grab as much text as possible and give back only if the rest of the pattern fails. Adding ? makes them lazy: .*? matches as little as possible. The classic example is <.+> against "<a><b>" — greedy matches the whole string, lazy <.+?> matches just "<a>".
How do I match a literal dot, plus, or question mark?
Escape it with a backslash: \. matches a literal period, \+ a plus sign, \? a question mark. The characters that need escaping outside a character class are . * + ? ^ $ ( ) [ ] { } | \ and /. Inside [...] most of them lose their special meaning, so [.+] matches a dot or a plus with no escaping.
What does \b actually match?
A word boundary — a zero-width position between a word character ([A-Za-z0-9_]) and a non-word character or string edge. It consumes no text. /\bcat\b/ matches "cat" in "a cat sat" but not in "concatenate", which makes it the cheapest way to do whole-word search.

More tools you might find useful in the same flow.

Built by Muhammad Tahir · About