Regex Tester — Match, Groups and Positions in Real Time
Test a regular expression against your text with instant results: all matches, their positions, capture groups and flag support — runs locally, nothing sent anywhere.
Last reviewed 2026-10-19. Rates change — verify against the official sources linked below before relying on these figures.
What this is based on
- JavaScript regex engine semantics — mostly compatible with PCRE, but watch for lookbehind support and subtle \b / unicode differences.
- Matches are capped at 100 for display; the engine stops at the first 20 shown with group details.
- Everything runs locally in your browser — pasted content is never uploaded, logged or stored.
The flags that change everything
Most 'my regex works here but not there' bugs are flag differences. Without g, you get only the first match — test() and match() disagree. Without m, ^ and $ anchor only to the string ends, not each line. Without s, the dot stops at newlines — why '.*' fails on multi-line input.
Case-insensitivity (i) is the other trap: it folds more than ASCII in Unicode mode, which is why [a-z] with i can match characters you didn't expect.
Capture groups: what the positions mean
Each match shows its index (0-based character position) and captured groups — the parts in parentheses, in order. Group 0 is always the full match. If a group is optional and didn't participate, it shows as undefined — the classic source of 'group 2 is empty' bugs.
JavaScript regex quirks worth knowing
JS supports lookahead and (in modern engines) lookbehind, named groups (?<name>…), and unicode-aware \p{…} classes. What it lacks vs PCRE: \z anchors (use $ with care), recursive patterns, and atomic groups — a pattern that works in PHP/Python may need adapting here.
Frequently asked questions
- Why does my regex only match once?
- You need the g flag — without it exec() and match() return just the first match. Select 'g — all matches' above.
- What's the difference between match and test?
- test() returns true/false; match() returns the strings (or null). With g, match() returns all matches but loses capture groups — use matchAll() or exec() in a loop for groups.
- How do I match an email?
- For validation that isn't insane: \b\w+@\w+\.\w+\b catches most cases. The 'perfect' RFC email regex is thousands of characters — almost nobody actually needs it.
- Why does '.' not match my newline?
- The dot never matches \n without the s (dotAll) flag. Use [\s\S] or enable 'gs' mode above.
Related calculators
Paste JSON to validate and pretty-print it — with error location (line and column) when it's broken, plus key count, depth and size stats. Runs entirely in your browser.
Paste a JWT and instantly see its header, claims and expiry — decoded entirely in your browser. No upload, no sign-up, nothing leaves your device.
Paste code or a git diff and detect leaked credentials — AWS keys, GitHub and Slack tokens, private key blocks, hardcoded API keys and JWTs. Matched values are masked, never displayed.