Regex Tester

Type a regular expression and some test text to see matches highlighted instantly, with each match position, capture groups (including named groups) and a replacement preview. Load a verified example pattern with one click. Everything runs in your browser.

//
Flags: g all matches, i ignore case, m multiline, s dot matches newline, u unicode, y sticky. Without g only the first match is shown.

What this regex tester runs, and where

A regular expression (regex) is a compact way of describing the shape of a piece of text so that you can search for it, validate it, pull parts out of it or rewrite it. Instead of writing "an 'a', then one or more digits, then an at-sign", you write a short pattern and let the engine do the matching. Typical jobs are checking form fields, cleaning log files, bulk-editing text and tidying scraped data.

This page uses the regular expression engine built into your browser, which is the JavaScript (ECMAScript) dialect. A pattern that works here can be pasted straight into new RegExp(...) or a /pattern/flags literal in JavaScript or TypeScript. Other languages have their own dialects (PCRE in PHP, Python's re, Java, .NET and so on) that agree on the basics but differ in details, covered in the dialect section below. Everything runs locally: the page builds a RegExp object from what you type and runs it over the test text in your browser tab. Neither the pattern nor the text is sent anywhere, and nothing is stored. Even so, avoid pasting real personal data into test boxes; sample strings are enough.

Syntax cheat sheet

TokenMeaningExample
.Any single character except a line break (with the s flag, line breaks too)a.c matches abc, a1c
\d \w \sDigit / ASCII letter, digit or underscore / whitespace\d\d matches 12
[abc] [^abc]One character from the set / one character not in the set[A-Z] matches a capital letter
* + ?Zero or more / one or more / zero or oneab+ matches ab, abbb
a{2,3}Between 2 and 3 repetitions\d{4} matches exactly four digits
^ $Start / end of the string (of each line with the m flag)^abc$
\bWord boundary (between a word character and a non-word character)\bcat\b
(…) (?:…)Capturing group / non-capturing group(ab)+
a|bAlternation: a or bcat|dog
(?=…) (?!…)Lookahead: followed by / not followed by\d+(?=%)
(?<=…) (?<!…)Lookbehind: preceded by / not preceded by(?<!\d)\d{5}(?!\d)

One trap: \w and \b only know ASCII letters, digits and underscore. In /\w+/ the text "naïve" stops at the ï, and Chinese, Japanese or Korean text contains no word characters at all, so \bcat\b even matches inside "cat猫". To match letters of any language, use a Unicode property escape with the u flag, for example \p{L}.

Flags

Newer engines add d (index ranges for groups) and v (an extended Unicode mode); they work only where your browser supports them. This tool passes whatever flags you type to the browser, so an unsupported or repeated flag shows up as an error message. Without g the tool lists just the first match, mirroring a single exec() call.

Ready-made patterns (each one run and checked in Node.js)

These patterns are in the preset buttons above. For each one, the sample text really does match, or really is rejected, as described.

Email address

\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b with the g and i flags matches alex@example.com and a.b+c@mail.co.uk, and skips bad@x (no top-level domain) and @no.com. The full email grammar (RFC 5322) is far richer than this, so no short pattern accepts every valid address or catches every typo. Use it as a first filter and confirm ownership by sending a message.

US-style phone number

(?:\(\d{3}\)\s?|\b\d{3}[-.\s])\d{3}[-.\s]\d{4}\b matches (555) 123-4567, 555-123-4567 and 555.123.4567, while 55-1234-567 and an unseparated 5551234567 are rejected. It checks the shape only. It says nothing about whether the number exists, and other countries use other layouts.

ISO date (YYYY-MM-DD)

\b(\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])\b limits the month to 01-12 and the day to 01-31 and captures year, month and day. In the sample, 2026-13-01 is rejected but 2026-02-31 passes: a regex sees format, not calendars. Validate real dates with a date library afterwards.

URL, IPv4, hex colour, ZIP code

Greedy versus lazy quantifiers

*, + and a{2,3} are greedy: they take as much text as they can and give back only if the rest of the pattern fails. Adding ? makes them lazy, taking as little as possible. On <b>first</b> and <b>second</b>, the greedy <b>.*<\/b> returns one match covering everything from the first opening tag to the last closing tag, whereas the lazy <b>.*?<\/b> returns two separate matches. The last two presets show the difference in the match count (1 versus 2). A sturdier alternative is a negated class such as [^<]*, which says "anything except the character that closes the match" and also runs more predictably.

ReDoS: when a pattern freezes the page

JavaScript's engine uses backtracking: when a path fails it goes back and tries another. If a pattern has repetition nested inside repetition, the number of paths can explode as the input grows, a problem known as ReDoS (regular-expression denial of service). The classic case is ^(a+)+$. Run against a row of the letter a followed by a b, it has to try every way of splitting the a's among the inner and outer plus before it can give up. I measured it in Node.js: 24 a's took about 0.1 s and 26 about 0.4 s, and each extra a roughly doubles the time (exact figures depend on the machine), so 40 would effectively never finish. The equivalent ^a+$ fails instantly. If this page's tab hangs while you experiment, wait for the browser's prompt or close the tab.

The status line warns when a run takes longer than 100 ms. The tool cannot interrupt a run in progress, so try suspicious patterns on a short test string first.

Groups, named groups and replacement

Parentheses create capture groups, listed per match under the results. A named group such as (?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2}) lets you read values by name, which keeps long patterns maintainable. In the replacement box you may use $1 (group 1), $& (the whole match) and $<name> (a named group). Worked check: load the date pattern, test it on 2026-10-13, and use $3/$2/$1 as the replacement to get 13/10/2026. The named-group preset does the same with $<day>/$<month>/$<year>, giving the same result. A second example: \B(?=(\d{3})+(?!\d)) replaced with a comma turns 1234567 into 1,234,567. A group that did not take part in the match is shown as "(none)".

Pitfalls that catch even experienced users

Dialect differences

When not to use a regex

Nested formats such as HTML, XML or JSON cannot be parsed reliably with a regular expression; use a real parser (the JSON Formatter is the better choice for JSON). Meaning is not a regex job either: whether an email inbox exists, whether a date is on the calendar, whether a phone number is in service. Treat a regex as a format filter and put the semantic checks in separate code.

Frequently Asked Questions

How do I see what each capture group matched?

Put parentheses around the part you want. Each entry in the match list shows the value of every group by number, and named groups appear with their names.

What happens if my pattern is invalid?

The browser reports the syntax error and the status line shows its message. Typical causes are unbalanced parentheses or brackets, an unescaped special character, a quantifier with nothing to repeat, or a bad flag.

Why do I only see one match?

Without the g flag a JavaScript regex stops at the first match. Add g to find all matches and to replace all of them.

Does my text leave my browser?

No. The pattern and the test text are processed by your browser's own regex engine on this page. The tool makes no request with them and stores nothing.

Can a regex fully validate an email address?

No. It can only check the format. Sending a confirmation message is the dependable test; a pattern is a quick filter for obvious typos.

Related tools