plato·regex
Open DevTools → Network and type a regex. Zero outbound requests from this tool — all matching runs in JavaScript locally using the browser's native RegExp. View source on GitHub.

Regex Tester

Test JavaScript regular expressions right in your browser. Paste your pattern, add a test string, and see every match highlighted inline. Token-by-token plain-English explanation. Zero library — native RegExp only.

Token explanation

How to use

  1. Pattern: type or paste your regex in the Pattern field. This uses JavaScript's native RegExp — PCRE-specific syntax won't work here.
  2. Flags: toggle any of the six JS flags — g (global), i (case-insensitive), m (multiline), s (dotAll), u (Unicode), y (sticky) — the result updates instantly.
  3. Test string: type or paste the text to match against. Press Enter to add newlines for multi-line testing.
  4. Output: matches are highlighted in yellow. Each match is listed below with its position and any capture group values.
  5. Token explanation: a plain-English breakdown of each metacharacter in your pattern appears at the bottom of the tool card.

Frequently asked questions

What is the difference between greedy and lazy quantifiers?

Greedy quantifiers (*, +, ?) match as much as possible. Lazy quantifiers (*?, +?, ??) match as little as possible. Given the string <b>bold</b>, greedy <.*> swallows the entire string, while lazy <.*?> stops at each tag. Use lazy when you want the shortest match between two delimiters.

Why do I need to escape . but not ,?

A dot is a metacharacter in regex — it matches any character except newline. A comma has no special meaning and matches a literal comma. Characters that must be escaped with \ include: . * + ? ^ $ { } [ ] | ( ) \. Write \. for a literal dot. The token panel below the tool highlights unescaped dots so you can catch this common mistake.

What does the g flag do?

The global flag tells the engine to find all matches, not just the first one. Without g, String.match() returns only the first match. With g, it returns an array of all matches. This tool enables g by default. Toggle it off to match only the first occurrence — the match list then shows full capture group details for that single match.

How do I match across newlines?

Use the s flag (dotAll mode, ES2018+). With s enabled, dot . matches any character including \n. Without s, dot stops at newlines. Alternatively, [\s\S] matches any character because \s (whitespace, including newlines) and \S (non-whitespace) together cover the full character set.

What is a capture group and how do I name one?

A capture group (pattern) isolates part of the match. Named groups use (?<name>pattern). For ISO dates: /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/ gives you match.groups.year, etc. Non-capturing groups (?:...) group without capturing — useful for alternation or quantifiers when you don't need the substring.

How do I write a regex for email validation?

A practical approximation: /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/. The full RFC 5322 spec is thousands of characters. In practice: use a simple format check client-side, then confirm the address is real by sending a verification email — that is the only reliable check.

Why does my regex work in Python but not JavaScript?

Python uses PCRE; JavaScript uses its ECMAScript engine. Key differences: JS lacks possessive quantifiers (*+, ++) and atomic groups. Python uses \A / \Z anchors; use ^ / $ in JS. Named groups differ: Python uses (?P<name>...), JS uses (?<name>...). Python's re.VERBOSE allows inline comments; JS has no equivalent.

What is a lookahead and when do I need it?

A lookahead asserts what follows without consuming characters. Positive foo(?=bar) matches foo only when followed by bar. Negative foo(?!bar) matches foo only when NOT followed by bar. Lookbehinds ((?<=...), (?<!...)) work for what precedes. Use them for context-sensitive matching — a word only at a sentence boundary, or a number not followed by a unit.

Can I use Unicode property classes?

Yes, with the u flag. \p{Letter} matches any Unicode letter in any script, \p{Emoji} matches emoji, \p{Decimal_Number} matches digits in any numeral system. Negate with \P{...}. Example: /\p{Letter}+/u. Far more reliable than \w for international text. Supported since ES2018 (Chrome 64+, Firefox 78+, Safari 11.1+).

How do I test my regex against multiple lines?

Paste text with newlines into the test string field and press Enter to add them. Enable m (multiline) so ^ and $ match per line instead of the whole string. Enable g to highlight all matches. Enable s if your dot needs to cross newlines. All six flags are independently toggleable with live preview.

Examples

Extract IPv4 addresses

Match IPv4 addresses in a log line. Word boundaries prevent partial matches inside larger numbers.

Pattern: \b(\d{1,3}\.){3}\d{1,3}\b
Flags:   g
Input:   blocked 192.168.1.1 and 10.0.0.255

Match 1: 192.168.1.1   (index 8)
Match 2: 10.0.0.255    (index 24)
Groups show each octet via capture group 1

Named capture: ISO date

Use named groups to parse date parts. Toggle g off to see full group details in the match list.

Pattern: (?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})
Flags:   (none)
Input:   Meeting on 2026-05-25 at noon

Match:   2026-05-25
  year → 2026
  month → 05
  day   → 25

Greedy vs lazy HTML tag

Switch between .* and .*? to see the difference in the highlighted output.

Input: <b>bold</b> and <i>italic</i>

Greedy <.*> (g):
→ 1 match — entire string
  from first < to last >

Lazy <.*?> (g):
→ 4 matches — each tag
  <b>, </b>, <i>, </i>

About this regex tester

Most online regex testers — regex101.com, regexr.com — are full single-page applications weighing 500 KB or more. They emulate PCRE and other engine flavors, which is useful for polyglot developers but adds complexity that JavaScript developers don't need. This tool goes the other direction: it uses the browser's own RegExp constructor, delivers results under a millisecond, and ships in under 15 KB gzipped.

Native RegExp, no library. Every match is computed by the JavaScript engine already built into your browser — V8, SpiderMonkey, or JavaScriptCore. There is no PCRE emulation, no transpilation, no WebAssembly. Patterns that work here behave identically in Node.js and in any ECMAScript-conformant runtime. If it matches here, it matches in production.

Privacy by construction. Your regex patterns and test strings are processed entirely in memory. No text is serialized to any server — no fetch, no WebSocket, no beacon. Open DevTools → Network while using the tool and you will see zero outbound requests generated by the tool itself. You can save this page with Ctrl+S and use it completely offline.

Token explanation. The token panel identifies recognized components of your pattern and describes each in plain English. It handles all ECMAScript metacharacters: escaped sequences (\d, \w, \s, \b, and their uppercase negations), character classes ([...]), quantifiers (greedy and lazy), capture groups (numbered and named), non-capturing groups, lookaheads, lookbehinds, alternation, and anchors. The goal is to make regex less opaque for developers who use them occasionally.

Flag reference. JavaScript has six regex flags. g (global): find all matches, not just the first. i (ignoreCase): case-insensitive matching. m (multiline): ^ and $ match start and end of each line. s (dotAll, ES2018): dot matches newline. u (unicode): enables \p{...} property escapes and strict Unicode parsing. y (sticky): matches only from lastIndex, useful for incremental tokenizers and parsers. All six are toggleable here with instant feedback.

Incumbent comparison. regex101.com serves roughly 10 million visits per month and is the gold standard for PCRE-heavy regex work. This tool does not try to replace it for multi-engine testing. The specific gap it fills: a JavaScript developer who wants to quickly validate a pattern they plan to ship in JS code, without loading an 800 KB SPA or dismissing a sign-up modal. Under 15 KB, native engine, works offline. That is the wedge.