Regex Tester, Visualizer & Builder

Build and test regular expressions safely with a ReDoS watchdog and railroad diagrams.

This tester matches patterns exactly the way a browser's JavaScript engine would, because that is what it actually calls behind the scenes: your pattern and flags go straight into a native RegExp object. That is useful for building and debugging a pattern you intend to run in JS, and it is also the reason the exported Python and Go snippets come with an explicit warning rather than a blanket promise of portability.

How to test a regular expression

  1. Type the pattern into the pattern field without the surrounding slashes, or assemble it from blocks in the visual builder.
  2. Tick the flags you need (g, i, m, s, u, y); an invalid pattern shows the engine's error in red straight away.
  3. Paste sample text into Test string: every match is underlined and the match count in the panel header updates as you type.
  4. Read the plain-English explanation, and hover a capturing group's dashed box in the railroad diagram to highlight exactly what that group captured.
  5. Copy the JavaScript, Python or Go version from Code snippets and test it once more in the target language.

Matching runs off the main thread, with a kill switch

Every match attempt is evaluated inside a dedicated worker rather than on the page itself, because a catastrophically backtracking pattern — the classic case is something like (a+)+ tested against a long run of a characters followed by one character that breaks the match — can hang whatever thread is running it indefinitely.

If a worker hasn't answered within 100 milliseconds, it gets forcibly terminated and a fresh one spawns immediately for your next keystroke. Termination is the only reliable way to stop a thread stuck in a tight synchronous loop, since a message can't interrupt code that never checks its inbox. The page itself never freezes even if the pattern you're testing genuinely would run forever.

The evil-pattern warning is a heuristic, not a guarantee

Before your pattern is ever evaluated against test text, its parsed structure is scanned for two well-known shapes that tend to cause exponential backtracking: a quantified group nested inside another quantifier, like (a+)+ or (a*)*, and an alternation where both branches can match the same text under repetition, like (a|a)+.

This check only recognizes those specific shapes. It will not catch every pattern capable of runaway backtracking, and flagging a pattern doesn't prove it will actually explode on real input — it's a shape match, not a proof. Treat a warning as a reason to look closer, and treat the absence of one as no guarantee the pattern is safe against adversarial input.

Reading your pattern back in plain English

The step-by-step explanation and the railroad diagram are both built by walking the same parsed structure, so a group, an alternation, or a lookaround shows up consistently in both places rather than being described twice by separate code paths that could drift apart.

There's also a visual, no-code block builder for literals, digit runs, letter runs, whitespace, character-class presets, either/or choices, and start/end anchors. Blocks compile forward into the pattern text you see, which is the one source of truth — editing the raw pattern field by hand does not reverse-populate the block list, since reliably recognizing which of many equivalent regex shapes a hand-edited pattern corresponds to isn't something this tool attempts.

Copying a pattern into another language

Where a copied snippet needs a second look

These snippets are written in each target language's own syntax, but the underlying regex semantics are still JavaScript's — this tool's stated scope — not a claim that PCRE, RE2 (which is what Go's regexp package actually runs on), or .NET interpret every construct the same way. The sticky flag has no equivalent at all in Python's re or Go's regexp, so a pattern relying on it needs a different anchoring strategy in either language.

Lookbehind is the other place semantics genuinely diverge: Go's RE2-based engine doesn't support lookbehind assertions in any form, and Python's re only accepts them when every branch matches a fixed width. A pattern built and confirmed here with variable-width lookbehind will compile in this tool and then fail outright the moment it's pasted into a Go regexp.MustCompile call.

Regex flags explained

Regex cheat sheet

Questions people ask about RegEx Visualizer & Builder

Why did my pattern work here but throw an error in Python?
Most often it's a construct JavaScript's engine accepts that Python's re module doesn't, or the reverse — variable-width lookbehind and named-group syntax differences are the usual suspects. This tool evaluates JS semantics specifically; treat the Python snippet as a starting translation to test in Python directly, not a guaranteed drop-in.
What does the catastrophic backtracking warning actually check?
It looks for two specific structural shapes in your parsed pattern: a quantified group nested inside another quantifier, and an alternation whose branches can match the same text under repetition. It's a heuristic shape match, not a backtracking simulation, so it can miss other exponential patterns and can't prove a flagged pattern is actually dangerous on your real input.
Why does testing a huge input against my pattern sometimes cut off early?
The worker caps how many matches it collects at five thousand per run. A pattern with a huge or unbounded number of matches against a large test string — an empty-match pattern is the common trigger — would otherwise take a long time to fully enumerate; the cap keeps every test run responsive regardless of input size.
Can I edit the visual block list and the raw pattern interchangeably?
Blocks always compile forward into the pattern text, so adding or changing a block updates the pattern immediately. Editing the raw pattern field directly does not update the block list, though, since turning an arbitrary hand-written pattern back into the specific blocks that produced it is ambiguous in general.
Does this regex tester support PCRE or Python syntax?
No. Patterns run through your browser's own JavaScript RegExp engine, so PCRE-only constructs such as possessive quantifiers (a++), atomic groups and recursion come back as an invalid pattern, and Python's (?P<name>...) group syntax is rejected too. Write named groups as (?<name>...) here; the exported snippets translate syntax, not engine behaviour.
What do the g, i, m, and s regex flags do?
g returns every match rather than only the first, i makes letter matching case-insensitive, m lets ^ and $ match at each line break, and s lets the dot match newlines as well. Each one is a checkbox under the pattern, and the highlighted matches refresh as soon as you toggle it.
How do I see what each capture group matched?
Hover the dashed group box in the railroad diagram. Its tooltip gives the group number, and the text that group captured turns amber inside every match in the test string, while whole matches stay underlined. There is no separate table of group values, so a group that took no part in a match simply shows no amber.

Related tools on BrakeTools

Content reviewed 2026-09-27.