Regex Tester

Test regular expressions safely, with highlighted matches and plain-language explanations.

Runs in your browser. Nothing is uploaded — your input is processed on this device and discarded when you close the tab.

Engine: this tester uses the JavaScript (ECMAScript) regular expression engine built into your browser — not PCRE (the engine behind PHP’s preg_* functions and many other tools). Most everyday patterns behave the same in both, but the engines differ; the notes below explain where, so a pattern that passes here is not silently assumed to pass everywhere.

Type the pattern without the surrounding slashes — the flags are the tick boxes below. Testing runs automatically as you type, inside a background worker with a one-second limit.

Flags

Supports JavaScript substitution tokens: $1–$99 numbered groups, $<name> named groups, $& the whole match, $` text before the match, $' text after it, and $$ for a literal dollar sign.

A share link contains the pattern, flags and test text themselves (encoded in the part of the link after # — it is never sent to a server), so anyone with the link can read your test text. Links are refused when the encoded form would exceed 6,000 characters. Testing itself never uploads anything: it runs in your browser, so avoid pasting live passwords or tokens into any tool, this one included.

Matches, highlighted

Matches will be highlighted here.

Capture groups

One row per match: the full match, each numbered group, and any named groups.

Pattern library

Twelve ready-made patterns for common jobs. Choose one and load it to see the pattern, its flags, a sample text and a plain-language explanation of what it does — and just as importantly, what it does not do.

Cheat sheet: common tokens in plain language

TokenWhat it means
.Any single character except a line break. With the s flag it also matches line breaks.
* + ?Repeat the previous token: * means zero or more, + means one or more, ? means zero or one (optional).
{2,4}Repeat the previous token at least 2 and at most 4 times. {3} means exactly 3; {2,} means 2 or more.
\d \DA digit (0–9 only in JavaScript) / any character that is not a digit.
\w \WA “word” character — A–Z, a–z, 0–9 and underscore / any character that is not one of those.
\s \SA whitespace character (space, tab, line break and friends) / any non-whitespace character.
[abc]One character that is a, b or c. [^abc] means one character that is none of those.
[a-z]One character in the range a to z. Ranges build larger sets, such as [0-9A-Fa-f] for a hex digit.
^ $The start / end of the text. With the m flag they match at the start and end of each line instead.
\bA word boundary — the position between a word character and a non-word character. Consumes nothing.
a|bAlternation: match a or b. The engine tries the left option first.
(...)A capturing group: groups a sub-pattern and remembers what it matched, so you can reuse it in the groups table or a replacement.
(?:...)A non-capturing group: groups for repetition or alternation without remembering a capture.
(?<name>...)A named capturing group: like (...), but the capture can be referenced by name, e.g. $<name> in a replacement.
(?=...) (?!...)Lookahead: requires (or forbids) what follows at this position, without consuming it.
(?<=...) (?<!...)Lookbehind: requires (or forbids) what immediately precedes this position, without consuming it.
\. \\ \+A backslash escapes a special character so it matches literally: \. is a full stop, not “any character”.
\p{L} \p{N}Unicode classes (needs the u flag): any letter / any number in any script, not just ASCII.

How to use the Regex Tester

  1. Type your pattern in the pattern box, without the slashes you may be used to from code — the flags have their own tick boxes underneath. Testing runs automatically as you type.
  2. Paste the text you want to test against. Use realistic text: a pattern that behaves on a tidy example can behave very differently on the ragged data you actually have.
  3. Read the highlights first, then the table. Highlighting shows where matches start and end; the capture-group table shows exactly which characters each group captured in each match, including named groups.
  4. Add a replacement if your goal is a search-and-replace: type it in the replacement box using $1, $<name>, $&, $` , $' or $$ and check the preview before trusting it in your editor.
  5. Short on ideas or debugging a token? Load one of the twelve library patterns to see a working example with an explanation, and keep the cheat sheet open while you edit — most pattern bugs are one wrong token.

Worked example

Select Load sample and the workspace fills with a pattern that pulls email addresses apart: (?<user>[A-Za-z0-9._%+-]+)@(?<domain>[A-Za-z0-9.-]+), with the g flag set and the replacement $<user> at $<domain>. The test text is two lines: “Contact amara.osei@example.com or tom.ellery@riverside-books.co.uk for details.” followed by “Backup address: support@atoztools.pro (replies within one working day).”

The tool finds exactly 3 matches. The first starts at character index 8 and is amara.osei@example.com; its groups table row reads group user = amara.osei and group domain = example.com. The other matches start at indexes 34 and 96 (tom.ellery@riverside-books.co.uk and support@atoztools.pro). The replace preview rewrites each address into words — “amara.osei at example.com”, “tom.ellery at riverside-books.co.uk”, “support at atoztools.pro” — leaving the rest of the text untouched. These results were produced by running the runMatch function from the shipped regex-tester.js on exactly this pattern, text and replacement, and the same function is what the workspace runs (inside its worker) when you select the button.

Pattern:     (?<user>[A-Za-z0-9._%+-]+)@(?<domain>[A-Za-z0-9.-]+)   flags: g
Match 1:     amara.osei@example.com   (index 8)   user=amara.osei   domain=example.com
Replaced:    Contact amara.osei at example.com or tom.ellery at riverside-books.co.uk
             for details. Backup address: support at atoztools.pro (…)

What this tool does, and why it matters

A regular expression is a tiny program for describing text: not “find this exact word”, but “find anything shaped like this” — a date, a product code, an address, a log line with a number in it. Developers use them to validate form input, extract fields from files, clean up data and power the find-and-replace in every serious text editor. They are also famously easy to get subtly wrong. A pattern reads as dense punctuation, its behaviour depends on which characters around it happen to appear in your data, and a mistake usually fails quietly: the pattern simply matches a little too much, a little too little, or — in the worst case — takes minutes over a single string.

That is why testing against real text, with the matches made visible, matters more than writing the pattern carefully. Highlighting shows you the match boundaries your mental model predicted, and the capture-group table shows what each group actually captured — the difference between a group that matched the domain and a group that accidentally swallowed the whole address is obvious in a table and invisible in the pattern itself. The replace preview closes the loop: most real-world regex work is not searching but transforming, and a replacement that expands $1 or $<name> wrongly will corrupt data at exactly the moment you apply it everywhere.

Two honest details define this tester. First, the flavour: it runs the JavaScript engine, and says so. Regular expressions are a family of related dialects, not one language — PCRE, used by PHP and many command-line tools, supports possessive quantifiers, atomic groups and constructs such as \K that JavaScript does not have, while JavaScript offers lookbehind and Unicode property classes in its own spelling. A pattern can be valid in one engine, invalid in another, and quietly different in a third. Testing here tells you the truth about JavaScript behaviour; before shipping a pattern to a PHP, Python or .NET target, test it there too.

Second, the safety limit. A pattern with nested repeats can force the engine into catastrophic backtracking, trying an astronomical number of ways to split a string before giving up — a classic way to freeze a browser tab or hang a server (a failure mode known as ReDoS). Here, evaluation runs in a Web Worker under a hard one-second limit: a runaway pattern is stopped and explained, and the page never freezes. The “classic slow pattern” button loads the textbook example so you can watch that protection work instead of taking our word for it.

Common errors, and the limits of this tool

Invalid patterns. An unclosed group or character class, a quantifier with nothing to repeat, or a trailing backslash all stop the test before it starts. The error box shows the engine’s own message and, where a position can be derived from the pattern — the unclosed bracket, for instance — an approximate character position. It is labelled approximate because the JavaScript engine reports no position of its own; treat it as the neighbourhood of the problem, not a promise.

“Pattern too slow” is information, not a verdict on the pattern alone. Backtracking blow-ups depend on the combination of pattern and text: ^(a+)+$ is instant on matching text and hopeless on a long near-miss. When you hit the limit, simplify the pattern: avoid nesting one repeat inside another over the same characters, bound repetitions with {n,m} where you can, anchor both ends, and make adjacent groups claim disjoint character sets so the engine has fewer ways to divide the string. Note that JavaScript has no atomic groups or possessive quantifiers — the standard PCRE fix — so restructuring the pattern is the available remedy here.

Engine limits. This tester speaks JavaScript regex only: no PCRE-only constructs, no recursion, no conditionals. Match collection stops at 1,000 matches per test (the run tells you when the cap was hit, and the groups table prints the first 200 rows). The sticky y flag anchors matching at the current search position, which for a single test means the start of the text unless the pattern can match there — an empty result with y set is usually that, not a bug. Zero-width matches (from lookaheads or an empty pattern) are shown as thin markers in the highlight and as empty full matches in the table. Very old browsers without Web Worker support run the same code on the main thread instead, where the one-second timeout cannot interrupt a pattern mid-run — the one environment in which a pathological pattern can still stall the page.

Frequently asked questions

Is the text I test uploaded anywhere?

No. The pattern, the test text and the replacement are processed entirely in your browser, in a background worker on this device. Nothing is sent over the network or stored, which is why the tool is safe to use on real log excerpts and data samples — although you should still follow your employer’s rules about pasting production data into any website.

Which regex flavour is this — and why does it matter?

JavaScript (ECMAScript), the engine built into your browser. It matters because “regex” is a family of dialects: PCRE adds possessive quantifiers, atomic groups and \K; Python’s re lacks lookbehind of variable length in older versions; JavaScript requires the u flag for \p{...} Unicode classes. Always confirm a pattern in the engine that will run it in production.

Why did my test say “pattern too slow”?

Your pattern and text together sent the engine into catastrophic backtracking — typically nested repeats such as (a+)+ or (.*)* against a string that almost matches. Rather than let it run (and freeze the tab), the tester stops the worker after one second and says so. Rewrite with bounded repeats, disjoint character classes and firm anchors, then test again.

What is the difference between numbered and named groups?

Both capture part of a match. Numbered groups are referenced by position — $1, $2 — which is compact but fragile: insert a group earlier in the pattern and every reference after it shifts. Named groups, written (?<name>...) and referenced as $<name>, survive reordering and make the pattern readable. This tester shows both in the capture-group table.

Why does the g flag change the results?

Without g, testing stops at the first match and replacement changes only that match. With g, the tester finds every non-overlapping match in the text and the replace preview rewrites all of them. Most of the library patterns set g so you can see every match in their sample text at once; whole-string test patterns such as the slug and password examples deliberately leave it off and use ^ and $ anchors instead.

Can I test a pattern against a very large file?

You can paste large text, but two caps apply: evaluation is limited to one second, and match collection stops at 1,000 matches (with a notice when it does). For bulk work over megabytes of logs, a command-line tool such as grep or ripgrep is the right instrument; this tester is for developing and understanding the pattern, which is the part that actually goes wrong.

Related tools

JSON Studio

Format, validate, minify, query and compare JSON in your browser, with precise line-and-column errors.

Developer Tools

Security Header and DNS Checker

Check HSTS, CSP and other security headers, TLS details, and DNS/email authentication records (SPF, DKIM, DMARC).

Developer Tools

Password Generator

Generate strong passwords with length and character-set controls, an honest entropy estimate and a session-only history.

Developer Tools

Related articles

How to Use Regular Expressions Safely

Regex tokens, groups and flags explained with tested matches — then the safety part most guides skip: catastrophic backtracking measured on a real pattern (0.11 ms at 10 characters, 2,115 ms at 28), why a one-second timeout matters, and the rewrite that makes the same check instant.

By AtoZTools Editorial Team · Last reviewed 2026-10-24

How to Format and Validate JSON

JSON syntax rules in plain language, a formatting workflow, and a gallery of 10 common errors — each one executed in Node against the JSON Studio validator code, with the line, column and hint it returned, and the fix that makes it parse.

By AtoZTools Editorial Team · Last reviewed 2026-10-24

How to Compare Two JSON Files

Structural comparison beats text diff for JSON: key order is not a change, array order usually is, and a number that became a string is a real change. Worked pairs run through a structural differ, with the exact added, removed and changed paths it reported.

By AtoZTools Editorial Team · Last reviewed 2026-10-24