Regex Tester
Test JavaScript regular expressions with live match highlighting — in your browser.
About Regex Tester
A regex tester lets you check a regular expression against sample text and see exactly what it matches, with live match highlighting as you type. Enter a pattern and flags, paste your text, and every match highlights in real time with numbered and named capture groups and each match's index broken out in a table. Invalid patterns are reported instead of throwing, and everything runs in your browser.
Greedy and lazy quantifiers
By default quantifiers are greedy: they take as much as they can and then give characters back only if the rest of the pattern fails. Running the pattern for an HTML tag against a line containing two tags will match from the first opening bracket all the way to the last closing one, swallowing everything between, because the greedy part grabbed the whole line before backtracking to find a closing bracket.
Adding a question mark after the quantifier makes it lazy — take as little as possible, then expand only if needed. That gives you the two separate short matches most people expect. When a pattern matches far more text than intended, greediness is the first thing to check, and a lazy quantifier is usually the fix.
The flags that change everything
The global flag changes what happens after the first match: without it you get one match, with it you get all of them. Case-insensitive matching is self-explanatory, but the multiline flag is regularly misunderstood — it does not let the dot match newlines. It changes the caret and dollar anchors so they match at the start and end of each line rather than only the whole string.
The flag that lets the dot match a newline is the dotall flag, which is separate. So a pattern intended to capture across several lines usually needs dotall, not multiline. Getting these two the wrong way round is one of the most common reasons a pattern works on a single line and fails on a paragraph.
Capture groups, and when not to use them
Parentheses do two jobs at once: they group part of a pattern so a quantifier applies to all of it, and they capture what matched for later use. When you only want the grouping, a non-capturing group keeps the numbering clean — otherwise inserting a group early in a pattern silently renumbers every group after it and breaks whatever code reads them by index.
Named groups solve that permanently. Referring to a match by name rather than by position means the pattern can be rearranged without touching the code that consumes it, and the pattern documents itself. For anything that will be maintained rather than thrown away after one use, named groups are worth the few extra characters.
Catastrophic backtracking
A regex can hang a program. When a pattern contains nested quantifiers — a repeated group that itself contains a repetition, with an alternation that can match the same text more than one way — the number of paths the engine explores can grow exponentially with input length. A pattern that returns instantly on twenty characters can take minutes on forty. Attackers exploit this deliberately against input validation, and it has a name: regular expression denial of service.
The defences are straightforward. Avoid nesting one quantifier inside another. Make the alternatives inside a group mutually exclusive so there is only one way to match. Anchor patterns so the engine cannot retry from every position. And when testing, paste in a long, deliberately awkward sample rather than only the short example you had in mind — that is when the problem shows up.
Frequently asked questions
- Which regex flavor does this use — is it JavaScript regex?
- Yes, it uses JavaScript's regular expression engine, including flags g (global), i (case-insensitive), m (multiline), s (dotall), u (unicode), and y (sticky). Patterns you test here behave the same in Node and browser JS.
- Does it show capture groups and named groups?
- Yes. Each match lists its position and every capture group; named groups like (?<year>\d{4}) are captured and shown alongside the numbered ones.
- Why does my global pattern only match once elsewhere?
- Under the global flag, a shared lastIndex and zero-length matches can loop or skip in your own code. This tester advances safely past zero-length matches so every match is found without hanging.
- Is my pattern and text private?
- Yes. The regex runs locally in your browser — nothing you type is sent to a server.

