Skip to content

Runs entirely in your browser. Nothing you paste leaves this page.

Free / No sign-up

Regex tester for JavaScript.

Write a regular expression and watch it match live, with highlighting, flags and every capture group laid out. Uses your browser's own JavaScript engine.

Flags

Highlighted, 2 matches

Write to support@nexzem.com or sales.team@example.co.in.
Not an email: hello@ or @nexzem.
Capture groups
#Match1: user2: domain
1support@nexzem.comsupportnexzem.com
2sales.team@example.co.insales.teamexample.co.in

JavaScript (ECMAScript) regex syntax, as used by browsers and Node.js. Showing up to 500 matches.

How to use it.

  1. 01

    Type a pattern between the slashes and toggle the flags you need.

  2. 02

    Paste the text to search; matches highlight as you type.

  3. 03

    Read numbered and named capture groups in the table, then copy the matches.

What it does.

Everything this tool handles, all of it inside your browser tab.

  • Live matching and highlighting as you type
  • Toggles for the g, i, m, s, u and y flags
  • Table of numbered and named capture groups
  • Unmatched optional groups shown as undefined
  • The engine's own error message for invalid patterns
  • Up to 500 matches, with zero-length matches handled safely
  • Copy every match in one click
  • Runs in your browser's JavaScript engine, with no upload

Worked examples.

  • Regex for an email address

    /^[^\s@]+@[^\s@]+\.[^\s@]+$/gm
    
    ada@example.com            match
    first.last+tag@mail.co.uk  match
    ada@localhost              no match
    @example.com               no match

    A practical check, not the full RFC 5322 grammar. It requires something, an @, and a domain with a dot. Confirm addresses by sending an email, not with a longer regex.

  • Regex for a date (YYYY-MM-DD) with named groups

    /^(?<year>\d{4})-(?<month>0[1-9]|1[0-2])-(?<day>0[1-9]|[12]\d|3[01])$/gm
    
    2026-10-10  ->  year 2026, month 10, day 10
    2026-13-01  ->  no match
    2026-02-31  ->  year 2026, month 02, day 31

    The pattern checks the format and plausible ranges, but it cannot know that February has no 31st. Validate real dates with a date library after matching.

  • Regex for an IPv4 address

    /\b(?:(?:25[0-5]|2[0-4]\d|1?\d?\d)\.){3}(?:25[0-5]|2[0-4]\d|1?\d?\d)\b/g
    
    Allow 192.168.1.10 and 10.0.0.255, block 256.1.1.1 and 1.2.3
    
    Matches: 192.168.1.10, 10.0.0.255

    Each octet is limited to 0-255, so 256.1.1.1 is rejected, and the three-octet 1.2.3 does not qualify.

  • Password rules with lookaheads

    /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{12,}$/gm
    
    correcthorse    no match (no uppercase, no digit)
    CorrectHorse42  match
    Correct1        no match (shorter than 12)

    Each (?=...) checks one rule from the start of the line without consuming text. Length matters far more than character mix; the password generator makes long random ones.

  • Greedy vs lazy matching

    Text: <b>bold</b> and <i>italic</i>
    
    /<.+>/g    1 match:  <b>bold</b> and <i>italic</i>
    /<.+?>/g   4 matches: <b>  </b>  <i>  </i>

    Adding ? after a quantifier makes it stop at the first possible end instead of the last.

How this regex tester works

The pattern you type is compiled with new RegExp(pattern, flags) by your browser's JavaScript engine and run against your test text on every change. The same engine family powers Node.js, Deno, Bun and front-end code, so a pattern that behaves here behaves the same in your JavaScript or TypeScript project.

Every match is highlighted in place, up to 500 matches. Zero-length matches, such as those from ^ or \b, show as a thin marker and the tester steps past them so a pattern like a* never loops forever. If the pattern has groups, a table lists the full match and each group for the first 50 matches, with named groups labelled by name. When the pattern is invalid, you see the engine's own error message, the same one your code would throw.

Because you type the pattern without surrounding slashes, you do not need to escape forward slashes here. Inside a JavaScript regex literal such as /https?:\/\// you do.

Regex flags explained: g, i, m, s, u and y

g (global) finds every match instead of stopping at the first. i ignores case. m (multiline) makes ^ and $ match at the start and end of each line instead of only the whole string. s (dotAll) lets . match line breaks, which it otherwise never does.

u (unicode) treats the pattern and text as Unicode code points, so an emoji counts as one character, and it enables property escapes such as \p{L} for any letter or \p{Script=Devanagari}. It also makes the syntax stricter, turning some silent mistakes into errors. y (sticky) only matches at the exact position where the previous match ended, which is useful for tokenisers.

JavaScript also has d (match indices) and v (an upgraded Unicode mode with set operations in character classes). They are not toggles in this tester, so test patterns that need them in your own runtime.

JavaScript regex vs PCRE and Python

Most everyday syntax is shared across flavours: character classes, quantifiers, groups, alternation, anchors and lookahead. The differences show up at the edges.

JavaScript has no possessive quantifiers, no recursion and no \A or \Z anchors (use ^ and $ without the m flag). A leading (?i) mode switch from PCRE is a syntax error; use the i flag instead. Named groups are written (?<name>...), where Python's re module uses (?P<name>...). JavaScript allows variable-length lookbehind, which Python's re rejects.

Shorthand classes differ too. In JavaScript, \d means only 0-9 and \w only ASCII letters, digits and underscore, even with the u flag. Python 3 matches Unicode digits and letters with \d and \w by default. If you validate names or numbers in languages other than English, test with real data, and use \p{...} escapes when you mean "any letter".

If your target is PHP (preg_*), Python or Go, use this tester for the shared core and check advanced features against that engine's documentation. For typed front-end code, see TypeScript vs JavaScript.

Capture groups, named groups and lookarounds

Parentheses capture: (\d{4}) stores the year so you can read it as group 1. Non-capturing groups (?:...) group without storing, which keeps the group numbers tidy. Named groups (?<year>\d{4}) are still numbered in order, and the table shows both the number and the name.

Backreferences reuse what a group matched: (\w)\1 finds doubled letters, and \k<name> does the same for a named group. An optional group that did not take part in a match shows as undefined in the table, which is what match[n] returns in code.

Lookarounds test without consuming text. (?=...) and (?!...) look ahead, (?<=...) and (?<!...) look behind. Lookbehind is supported in all current major browsers and Node.js. A common use is checking several rules at once, such as a password that must contain a digit and an uppercase letter.

Common regex mistakes and how to fix them

An unescaped dot matches any character, so example.com also matches exampleXcom. Escape it as \. when you mean a literal dot. The same goes for +, ?, *, (, ), [, {, | and ^ outside a character class.

Greedy quantifiers take as much as they can: <.+> on "<b>bold</b>" matches the whole string. Add ? to make them lazy (<.+?>), or use a negated class such as <[^>]+>, which is usually clearer and faster.

Forgetting anchors lets a validation pattern match part of the input: \d{4} accepts "abc12345". Use ^ and $ to match the whole value. And when you move a pattern into a JavaScript string for new RegExp, double every backslash: "\\d+" in the string becomes \d+ in the regex. That single detail explains most "works in the tester, fails in my code" reports.

Finally, regex is the wrong tool for nested formats such as HTML or JSON. Use a parser for those and keep regex for flat patterns, which is how most web scraping pipelines combine the two.

Catastrophic backtracking and ReDoS

JavaScript uses a backtracking engine. Patterns with nested or overlapping quantifiers, such as (a+)+$ or (\w+\s?)*$, can take exponential time on an input that almost matches. On a server this is a denial-of-service risk known as ReDoS, and it sits squarely in the injection and availability concerns covered by our OWASP Top 10 checklist.

This tester runs on your browser's main thread, so a catastrophic pattern can freeze the tab for a while, just as it would freeze your app. That makes it a useful test bench: try long near-miss strings before shipping any regex that runs on user input. Prefer specific character classes, avoid nesting quantifiers, anchor patterns, cap input length, and let static code analysis tools flag risky patterns in review.

Questions, answered

Something else on your mind? Ask a consultant and get a reply within one business day.

Which regex flavour is this?

JavaScript (ECMAScript), executed by your browser. It is what Node.js, Deno, Bun and front-end code use. Most everyday syntax carries over to other languages, but check advanced features against your target engine.

Why do I only get one match?

Without the g flag a JavaScript regex stops at the first match. Turn on g to find them all.

How do named groups work?

Write (?<name>...) to capture into a named group. It is still numbered in order, and the table shows both the number and the name. In code, read it from match.groups.name.

Do I need to escape forward slashes?

Not here, because you type the pattern without the surrounding slashes. In a JavaScript regex literal such as /a\/b/ you must escape them, and when building a pattern from a string you must double every backslash.

Why does my regex work here but not in my code?

The usual causes are string escaping ("\d" in a JavaScript string is just d, so write "\\d"), a missing flag, or a different engine such as Python or PHP. Copy the flags shown after the closing slash along with the pattern.

What is the difference between greedy and lazy quantifiers?

Greedy quantifiers such as .* match as much as possible, then give back characters if needed. Lazy ones such as .*? match as little as possible. On markup-like text the difference decides whether you get one long match or several short ones.

How do I match across multiple lines?

Turn on s so that . also matches line breaks, or use [\s\S] in place of the dot. Turn on m if you want ^ and $ to match at the start and end of each line.

Does JavaScript support lookbehind?

Yes. Both (?<=...) and (?<!...) work in all current major browsers and Node.js, and unlike Python's re, JavaScript allows variable-length lookbehind.

Why did my browser tab freeze?

The pattern probably triggers catastrophic backtracking, usually from nested quantifiers such as (a+)+. Rewrite it with more specific character classes, and treat it as a warning: the same pattern could stall a server on hostile input.

Is my test text sent anywhere?

No. Matching runs in this tab, so it is safe to test against logs or customer data.

More free tools.

All tools

Need tooling like this inside your product?

We build internal tools, developer platforms and APIs. Tell us what your team keeps doing by hand.