devtools

Regex Tester & Debugger

Test and debug regular expressions online in your browser. See every match, numbered and named capture groups, and flag toggles — private, nothing uploaded.

Runs entirely in your browser — your data never leaves your device.

How to use Regex Tester & Debugger

What it does & when you need it

You have a regular expression and a pile of text, and you need to know exactly what it matches before you paste it into code. This tester runs your pattern against the sample text live, highlights how many matches it found, and breaks each match down into its numbered and named capture groups. It uses the same RegExp engine that ships in every JavaScript runtime, so a pattern that works here behaves identically in Node, a browser, or a .replace() call. Everything runs locally — the log lines, API payloads, or customer records you paste to test against never leave your machine.

Reach for it when you are writing a validation rule, extracting fields from log output, building a find-and-replace, or debugging why a pattern that "looks right" matches nothing (or matches far too much).

How to use

  1. Type your expression into the pattern field between the two slashes, and type the text you want to search into the test string buffer — or press Sample to load a worked log-parsing example.
  2. Toggle the flag buttons (g i m s u y) to change how the engine matches; hover any flag for a one-line reminder of what it does.
  3. Results appear in the matches buffer as you type. Press Test or Ctrl/Cmd + Enter to force a re-run, and Copy to grab the breakdown. If the pattern is invalid, the error from the engine is shown instead.

Things worth knowing

Flags change the meaning of the whole match. g (global) finds every match rather than stopping at the first; i makes matching case-insensitive; m (multiline) makes ^ and $ bind to line boundaries instead of the whole string; s (dotAll) lets . match newlines; u switches on full Unicode handling so an astral character like an emoji counts as one code point; and y (sticky) anchors each attempt to the current lastIndex. The behaviour of these flags is specified in ECMA-262; flip one and the same pattern can go from zero matches to hundreds.

Watch out for catastrophic backtracking (ReDoS). A pattern with nested, unbounded quantifiers — the classic being (a+)+ — can force the engine to explore an exponential number of ways to match a long string that ultimately fails. On a 30-character non-matching input it can freeze a tab or take down a server thread. If a pattern hangs, look for a quantifier inside another quantifier and rewrite it (often with an anchored or possessive-style alternative, or by making the inner part more specific).

Prefer named capture groups over counting parentheses. Instead of remembering that the year is group 3 and the month is group 4, write (?<year>\d{4})-(?<month>\d{2}) and read them off match.groups.year. Named groups landed in JavaScript with ES2018 and make patterns self-documenting; this tester lists both the numbered and the named groups for every match so you can see them side by side.

Zero-width matches need special handling. An empty pattern, a lone lookahead, \b, or ^ under the m flag all match a position rather than any characters. Because such a match does not consume input, a naive exec loop never advances lastIndex and spins forever. This tester detects a zero-length match and steps past it automatically, which is why an empty pattern against abc correctly reports four matches (one at each boundary) instead of hanging.

Once you have the right pattern, keep a regex cheatsheet handy for the token syntax, feed matched JSON into the JSON formatter to check it parses, or use the diff checker to compare the text before and after a substitution.

Examples

Parse server log lines

2026-07-01 INFO  server started on :4000
2026-07-01 WARN  cache miss for key user:42
2026-07-02 ERROR upstream timeout after 30s

With the sample pattern (?<date>\d{4}-\d{2}-\d{2})\s+(?<level>INFO|WARN|ERROR) and the g and m flags, each line yields a named date and level.

Grab every email address

Contact ada@example.com or reports+ci@dev.example.co.uk; skip not-an-email@

Try the pattern [\w.+-]+@[\w-]+\.[\w.-]+ with the g flag to extract each address and see the incomplete one is ignored.

Find all numbers

Order #1042 shipped 3 of 12 items — total $58.99

Use \d+ with the g flag to match every run of digits, including the ones inside the order id and price.

Frequently asked questions

Does this regex tester send my text to a server?

No. Your pattern and test string are evaluated locally with your browser's built-in RegExp engine. Nothing you paste — logs, tokens, or customer data — is uploaded, so the tool also works offline once the page has loaded.

Why does my regex only match the first result?

Without the global flag, RegExp stops at the first match. This tester iterates internally so it always lists every match, but in your own code you must add the g flag (or use matchAll) to loop over all of them.

How do I use named capture groups in JavaScript?

Write groups as (?<name>...), for example (?<year>\d{4}). Named groups were added in ES2018 and are read from match.groups.name. They are far clearer than counting parentheses, and this tool lists both the named and numbered groups for every match.

What can make a regex hang or freeze the page?

Catastrophic backtracking, also called ReDoS. Patterns with nested unbounded quantifiers such as (a+)+ can force the engine to try an exponential number of paths on a long non-matching string. Rewrite the inner quantifier to be more specific or anchored.

What do the g, i, m, s, u, and y flags do?

g finds all matches, i ignores case, m makes ^ and $ match line boundaries, s lets . match newlines, u enables full Unicode code-point matching, and y (sticky) anchors each attempt to lastIndex. Toggling one can change your results completely.

Why does an empty pattern report several matches?

An empty pattern (and anchors like ^ under the m flag) produce zero-width matches at each position rather than matching characters. A naive exec loop would spin forever on these; the tester steps past each one, so an empty pattern on 'abc' correctly shows four boundary matches.