Tools
Regex Tester
Build and test JavaScript regular expressions live. Type a pattern, toggle flags, and see every match highlighted with its index and capture groups.
hello world and even helo, helllo more hello, Hello again — hello
| # | Index | Match | Groups |
|---|---|---|---|
| 0 | 0 | hello | none |
| 1 | 39 | hello | none |
| 2 | 60 | hello | none |
About the Regex Tester
Regex Tester runs a native JavaScript RegExp against a block of text and shows exactly what matched. Enter a pattern, toggle flags, and type or paste a test string — matches are highlighted inline in yellow and listed in a table with each match's start index, matched text, and capture groups. There's no translation layer: this is the same regex dialect your browser and Node.js already use, so a pattern that matches here matches identically when you drop it into String.prototype.match(), .replace(), or .test() in your own code.
Everything runs client-side — the pattern and test string never leave your browser, which matters if you're testing a regex against real log lines, emails, or other sensitive data. Under the hood, the tool compiles your pattern with new RegExp(pattern, flags) inside a try/catch: a bad pattern (unbalanced parens, an invalid quantifier) surfaces the engine's own SyntaxError message instead of a generic error. To enumerate every match — even for patterns that produce zero-width results like a* or \b — it clones your regex with the g flag forced on and steps through with exec(), manually advancing past empty matches to avoid an infinite loop.
Use it to work out a pattern before committing it to code: confirm capture group order and indices, see immediately whether g or i changes the match count, or figure out why a pattern greedily consumes more than expected. It's also useful for teaching — the side-by-side highlight and match table make it obvious which flag caused which behavior change, which is harder to see from a REPL's console.log(str.match(re)) output alone.
Examples
Pattern: /(\w+)@(\w+\.\w+)/
Flags: g
Input: Contact alice@example.com or bob@test.org for details.
Matches:
#0 Index 8 Match "alice@example.com" $1: alice $2: example.com
#1 Index 29 Match "bob@test.org" $1: bob $2: test.orgThe Groups column lists capture groups in the order they open in the pattern — $1 is the first (...), $2 the second — regardless of how they're nested.
Pattern: /\d+/
Input: order 12, qty 34, total 56
Without g flag → 1 match: "12" at index 6
With g flag → 3 matches: "12" (6), "34" (14), "56" (24)Without g, the tool stops after the first hit, same as calling RegExp.prototype.exec() once. A regex that seems to only match part of the text is usually just missing this flag.
const re = /(\w+)@(\w+\.\w+)/g
const input = 'Contact alice@example.com or bob@test.org for details.'
for (const m of input.matchAll(re)) {
console.log(m.index, m[0], m[1], m[2])
}
// 8 alice@example.com alice example.com
// 29 bob@test.org bob test.orgmatchAll() throws TypeError: String.prototype.matchAll called with a non-global RegExp argument if you forget the g flag — the tool avoids this itself by always matching against an internal clone with g forced on.
Frequently asked questions
What regex flavor does this tool use — PCRE, POSIX, or JavaScript?
It compiles your pattern with JavaScript's native RegExp, so it follows the ECMAScript regex spec — the same one your browser and Node.js use. Named groups ((?<name>...)), lookahead/lookbehind, and Unicode property escapes (with the u flag) all work, but PCRE-only features like possessive quantifiers or atomic groups don't exist. If the pattern is destined for PHP's preg_match, Python's re, or another language, re-test it there too — the syntax overlaps a lot but isn't identical.
Why does my capture group show undefined?
That group matched nothing because the overall match came from a different branch of an alternation — for example (a)|(b) matching "b" leaves group 1 unset. This is standard JavaScript regex behavior: match[1] really is undefined in that case, not a bug in the tool.
Does this tool send my regex pattern or test string to a server?
No. Compilation and matching both happen in your browser using JavaScript's built-in RegExp — nothing you type is transmitted anywhere, so it's fine to test patterns against real log lines, tokens, or other sensitive text.
Why do some matches show an empty Match value?
Patterns that can match zero characters — a*, \b, ^ — match successfully at every qualifying position, even where there's no visible text, which is why you'll see rows with an empty match string. This mirrors what RegExp.prototype.exec() returns if you called it in a loop yourself.
How do I make . match newlines, or make ^/$ match per line?
Enable the s flag (dot-all) to make . match line terminators too, and enable m (multiline) to make ^ and $ match at the start and end of each line instead of only the start and end of the whole string. The two flags are independent and are often combined for parsing multi-line log text.