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
- Type the pattern into the pattern field without the surrounding slashes, or assemble it from blocks in the visual builder.
- Tick the flags you need (g, i, m, s, u, y); an invalid pattern shows the engine's error in red straight away.
- Paste sample text into Test string: every match is underlined and the match count in the panel header updates as you type.
- Read the plain-English explanation, and hover a capturing group's dashed box in the railroad diagram to highlight exactly what that group captured.
- 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
- JavaScript, as a regex literal with your chosen flags attached directly
- Python, as a raw string passed to re.compile with an equivalent re.IGNORECASE-style flags expression
- Go, as a raw string passed to regexp.MustCompile, with case-insensitivity folded into an inline (?i) prefix since Go's regexp package has no separate flags argument
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
- g (global): report every match instead of stopping at the first. With it unticked this tester highlights one match only; Python and Go have no flag for it, you call findall/finditer or FindAllString instead.
- i (ignore case): letters match regardless of case. The Python snippet turns it into re.IGNORECASE and the Go snippet prefixes the pattern with (?i).
- m (multiline): ^ and $ also match at every line break, not just at the ends of the input. Python gets re.MULTILINE; the Go snippet leaves it out, so add (?m) yourself.
- s (dotAll): the dot also matches newline characters. Python gets re.DOTALL; for Go, prefix the pattern with (?s) by hand.
- u (unicode): enables \u{1F600}-style code point escapes and \p{L}-style property classes, treats emoji as single characters, and rejects sloppy escapes. The Python and Go snippets drop it, since both languages already work on Unicode text.
- y (sticky): each match must start exactly where the previous one ended, with no skipping ahead. Neither Python's re nor Go's regexp has an equivalent.
Regex cheat sheet
- Character classes: \d digit, \w letter, digit or underscore, \s whitespace, . any character except a line break (unless s is set); \D, \W and \S match the opposite.
- Sets: [abc] one of a, b or c; [^abc] any other character; [a-z0-9] ranges; most symbols lose their special meaning inside brackets.
- Anchors: ^ start of input, $ end of input (of each line with m), \b word boundary, \B anywhere that is not a word boundary.
- Quantifiers: * zero or more, + one or more, ? optional, {3} exactly three, {2,5} two to five, {2,} two or more.
- Greedy versus lazy: quantifiers grab as much as they can by default; add ? after one (*?, +?, {2,5}?) to take as little as possible.
- Groups: (abc) captures, (?:abc) groups without capturing, (?<year>\d{4}) captures under a name, and \1 or \k<year> repeats what was captured.
- Alternation: cat|dog matches either side; wrap it in a group, as in (cat|dog)s, to limit how far the choice reaches.
- Lookarounds: (?=x) followed by x, (?!x) not followed by x, (?<=x) preceded by x, (?<!x) not preceded by x; none of them consumes text.
- Escapes: put a backslash before . * + ? ^ $ { } ( ) [ ] | \ to match the character itself; \n is a newline and \t a tab.
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
- JSON Formatter & Type Generator — Format, minify, and generate types from JSON payloads up to 100MB+, no freeze.
- Cron Expression Builder — Build or explain UNIX, Quartz, and AWS EventBridge cron expressions in plain English.
- API Request Builder & Tester — Build HTTP requests, inspect timing, headers, and responses, and copy cURL without sending request data through BrakeTools.
Content reviewed 2026-09-27.