DEVELOPER TOOL

Regex Tester & Debugger

Test regular expressions instantly, highlight matches, inspect capture groups, and extract or replace text directly in your browser.

Examples:
0 matches


                

Replacement uses JavaScript's String.prototype.replace syntax. With the g flag all matches are replaced; without it only the first match is replaced.

0 replacements

            

Validate mode answers the simple question: does this pattern match anywhere in the test text? Use anchors (^…$) if you want to test the entire input.

Regex cheat sheet

Character classes

  • . any char except newline
  • \d digit   \D non-digit
  • \w word char   \W non-word
  • \s whitespace   \S non-whitespace
  • [abc] any of a, b, c
  • [^abc] any except a, b, c
  • [a-z] range a–z

Quantifiers

  • * 0 or more
  • + 1 or more
  • ? 0 or 1 (optional)
  • {n} exactly n
  • {n,} at least n
  • {n,m} between n and m
  • *? lazy — as few as possible

Anchors & assertions

  • ^ start of string / line
  • $ end of string / line
  • \b word boundary
  • \B non-word boundary

Groups & alternation

  • (…) capturing group
  • (?:…) non-capturing group
  • (?<name>…) named group
  • a|b alternation
  • \1 backreference to group 1

Lookarounds

  • (?=…) positive lookahead
  • (?!…) negative lookahead
  • (?<=…) positive lookbehind
  • (?<!…) negative lookbehind

Common flags

  • g global — all matches
  • i ignore case
  • m multiline — ^ $ per line
  • s dotAll — . matches newline
  • u unicode-aware
  • y sticky — match at lastIndex

This is a compact reference, not an exhaustive specification. For full details see the MDN RegExp documentation.

Extract data, then transform it

Pull values out of logs or an API response with regex, then reshape them with the Universal Data Transformer (JSON → CSV, XML, YAML, SQL).

Working with JWTs?

Regex often finds a token in a header or log. Decode it with the JWT Debugger to inspect its header and payload.

Log timestamps

If your regex pulled out Unix epoch values like 1750000000, convert them with the Unix Timestamp Converter.

Comparing extracted JSON?

Once your regex produces JSON, compare two versions field-by-field with the JSON Diff tool.

Testing an API response?

Fetch the response in the API Request Builder, then paste it here to extract values with regex.

JSON vs XML

Choosing a data format? Read the JSON vs XML comparison guide.

What is a regular expression?

A regular expression (regex) is a compact pattern language for describing text. Instead of writing procedural code that loops character-by-character, you describe the shape of the string you're looking for. A pattern like ^\d{4}-\d{2}-\d{2}$ reads "start of string, four digits, hyphen, two digits, hyphen, two digits, end of string" — a date in ISO form. Regex is used everywhere: log parsing, input validation, syntax highlighting, find-and-replace in editors, routing rules, scraping, and linting.

Regex is powerful but famously easy to get wrong. A pattern that looks correct can silently fail to match (because of greediness, missing anchors, or a flag not being set), or it can match far too much (because .* is greedy). That's where a regex tester earns its keep: instead of guessing, you paste the pattern and some sample text, and you see exactly what matches, what doesn't, and which capture groups got filled.

What is a Regex Tester?

A Regex Tester is a developer tool that runs your pattern against sample text and shows the results interactively. The best ones do four things: highlight every match directly in the text, list each match with its index and capture groups, let you toggle flags on and off to see how they change behaviour, and support replacement so you can preview what a find-and-replace would produce before running it in production.

This online regex tester runs entirely in your browser using the JavaScript RegExp engine. That means every result is exactly what your Node.js server, your front-end code, and your Chrome DevTools console would produce — no approximations, no separate regex dialect. Because it never uploads your pattern or your test text, you can safely paste production logs, tokens, emails, or customer data without worrying about leakage.

How to test a regex

The workflow is intentionally simple:

  1. Type or paste the pattern into the top field. Do not type the /…/ delimiters — they're shown as decoration, and typing them inside the field will be handled gracefully.
  2. Choose flags. g is on by default so you see all matches; i for case-insensitive, m for multiline, s for dot-all, and so on.
  3. Paste the test text below.
  4. Matches appear instantly, highlighted, with a numbered list underneath.
  5. Switch to Replace to preview a substitution, or Validate to test whether the pattern matches at all.

There is no send button. Every keystroke re-runs the pattern with a small debounce, so the tool feels immediate without hammering the CPU.

How regex matching works

JavaScript's RegExp engine is a backtracking engine. Given a pattern and a string, it walks the string left to right trying to fit the pattern at each position. When a quantifier like * or + can match more than one way, the engine prefers the greedy interpretation first, then backtracks if the rest of the pattern fails. That's how a+ against "aaa" matches all three as, and why a pattern like (a+)+b on a long run of as with no b can take an exponential amount of time to fail.

The important consequences for day-to-day work:

  • Prefer specific classes ([a-z]) over .* where possible — it's faster and clearer.
  • Use lazy quantifiers (*?, +?) when you want the shortest match instead of the longest.
  • Anchor your pattern (^…$) whenever you're validating input — an unanchored pattern will happily match a substring.

Regex flags explained

Flags change how the pattern is interpreted. This tool detects which flags the current browser actually supports and only enables those — you'll never see a flag silently do nothing.

  • g — global. Find all matches, not just the first. Without g, the engine stops after the first hit. This flag is required for String.prototype.matchAll.
  • i — ignore case. /abc/i matches ABC, Abc, and abc.
  • m — multiline. Makes ^ and $ match at line breaks instead of only at the start and end of the whole string.
  • s — dotAll. Without s, . matches any character except a newline. With s, it matches newlines too.
  • u — unicode. Makes the pattern unicode-aware, so \u{1F600} and code-point ranges work correctly with astral characters.
  • y — sticky. Matches only at lastIndex, and does not skip ahead. Useful for tokenizers and lexers.
  • d — indices. Adds start and end arrays to each match, so you can retrieve exact offsets — including for each capture group.
  • v — unicode sets. A newer superset of the u flag that adds set operations inside character classes. Not available in every browser; the tool hides it when it isn't supported.

If you enable both u and v, the browser will throw — the tool detects this and shows a clear error instead of a stack trace.

Character classes, quantifiers and anchors

A character class matches one character from a set. \d is a shortcut for [0-9], \w for [A-Za-z0-9_], and \s for whitespace. Inside square brackets you can list characters, ranges, and even negate the whole set with [^…].

Quantifiers describe how many times the preceding token may repeat. * means zero or more, + means one or more, ? means zero or one, and {n,m} means between n and m times. Add a trailing ? to make any of them lazy.

Anchors constrain where a match may start or end. ^ anchors to the start of the string (or line with m), and $ anchors to the end. \b is a word boundary — a zero-width assertion that matches between a word character and a non-word character.

A very common bug: forgetting to anchor a pattern used for validation. \d{6} against "abc123456xyz" will happily match the 123456 in the middle. If you mean "the input must be exactly six digits", write ^\d{6}$.

Capture groups and named groups

Parentheses do double duty: they group parts of a pattern together (so a quantifier applies to the whole group) and they capture the matched text so you can refer to it later. In (\d{4})-(\d{2})-(\d{2}) the three groups capture the year, month, and day of an ISO date.

Use (?:…) for a non-capturing group when you want grouping without the overhead (or the numbering side-effect) of a capture. This tool never lists non-capturing groups as capture results.

Named groups ((?<year>\d{4})) make complex patterns much more readable. The captured value shows up as match.groups.year, and you can reference it in a replacement with $<year>. Named groups are strictly better than numbered groups once a pattern has more than two or three groups, because inserting a new group no longer renumbers everything downstream.

Backreferences let a pattern refer to an earlier captured value. (\w)\1 matches any doubled character — aa, bb, 11. Named backreferences use \k<name>.

Lookahead and lookbehind

Lookarounds are zero-width assertions: they check a condition without consuming characters. They're the answer to "match X only if it's followed (or preceded) by Y".

  • (?=…) positive lookahead — match only if followed by this.
  • (?!…) negative lookahead — match only if not followed by this.
  • (?<=…) positive lookbehind — match only if preceded by this.
  • (?<!…) negative lookbehind — match only if not preceded by this.

A classic example: match a number only if it's followed by a currency symbol — \d+(?= USD). The number is captured; the currency symbol is asserted but not consumed. Lookbehind lets you match something that follows a delimiter without including the delimiter in the match — (?<=#)\w+ matches a hashtag body without the leading #.

Lookbehind support is not universal across engines, but it's part of the ECMAScript specification and available in every modern browser that this tool supports.

Regex replacement

JavaScript's String.prototype.replace accepts a replacement string in which $1, $2, etc. refer to capture groups; $& refers to the whole match; $<name> refers to a named group. A common idiom: normalise date formats.

Pattern:     (\d{4})-(\d{2})-(\d{2})
Text:        2026-09-26
Replacement: $3/$2/$1
Result:      26/09/2026

Replace mode in this tool shows the exact output and counts how many substitutions occurred. Without the g flag only the first match is replaced — that surprises people the first time they use String.replace without /g, so the tool makes the current flag state visible right above the result.

Extracting data with regex

Extraction is where regex really shines: pull the parts you care about out of a blob of text without writing a parser. Typical sources are log files, API responses, config exports, and SQL dumps. The workflow is: write a pattern that matches the interesting spans, then use Copy matches or Download to grab the extracted values.

Example — pull order IDs out of a plain-text report:

Text:   Order #1001 / Order #1002 / Order #1003
Regex:  #\d+
Result: #1001
        #1002
        #1003

Once you've extracted the list, the Universal Data Transformer can convert it into JSON, CSV, or another structured format for downstream processing. If your regex produces JSON and you want to compare two versions, the JSON Diff tool shows you exactly which fields changed.

Validating input with regex

Regex validation is either the easiest thing in the world or a trap, depending on the input format. Digits-only, HEX colours, and fixed-length codes are straightforward. Email addresses and URLs are famously not: the official email grammar is enormous, and a "complete" URL parser is closer to a library than a pattern.

A practical rule: use regex to reject obviously invalid input, and use a real parser or a domain-specific validator for anything security-critical. The examples in this tool (email, URL, phone) are practical matchers, not specification validators. They're good enough for form-field UX; they're not good enough to gate access to anything.

Always anchor a validator: ^\d{6}$ not \d{6}. And be mindful of DoS via regex — an unanchored, backtracking-heavy pattern can be exploited to freeze a server. If a pattern is untrusted (user-supplied), run it in a sandbox or set a hard timeout.

Regex for logs and API responses

Log lines are one of the highest-value regex targets. A typical line has a timestamp, a level, a request ID, and a message. A regex can pull out any subset of these in a single pass.

Log:   2026-09-26T10:12:44Z WARN req=abc123 user=42 latency=832ms
Regex: user=(\d+).*?latency=(\d+)
Result: Group 1 = 42, Group 2 = 832

For API responses, regex is a pragmatic alternative to JSON parsing when you only need one value and don't want to load a full parser. For example, extracting a pagination cursor from an HTML-embedded JSON blob. For anything structural, parse the JSON — but for a quick grab during debugging, regex is often faster to write than code.

If the extracted values are Unix timestamps (like 1750000000), paste them into the Unix Timestamp Converter to see them as real dates. If they're JWT-shaped (eyJ…), decode them with the JWT Debugger.

Common regex mistakes

  • Unanchored validation. \d{6} matches a six-digit substring inside a longer string. Use ^\d{6}$.
  • Greedy .*. <div>.*</div> matches from the first opening tag to the last closing tag. Use .*? for the shortest match.
  • Forgetting the g flag in String.replace, resulting in only one replacement.
  • Escaping too little. Inside a character class, ], \, ^, and - all have special meaning.
  • Escaping too much. \- outside a class is redundant; \/ in JavaScript is only needed inside a /…/ literal.
  • Relying on \b for word boundaries around non-word characters. \b is defined in terms of \w, so it behaves unexpectedly near symbols.
  • Assuming lookbehind is universally supported. It's fine in modern JS, but many other engines still lack it.
  • Catastrophic backtracking. Nested quantifiers over ambiguous classes ((a+)+) can take exponential time on non-matching input.

Invalid regex errors

When a pattern can't be compiled, the browser's RegExp constructor throws a SyntaxError with a specific message. This tool surfaces that message verbatim and keeps it close to the pattern field — you'll see things like "Unterminated character class" or "Invalid group" or "Unmatched ')'". A common source of confusion is that a pattern can be valid in one flavour and invalid in another (PCRE vs JavaScript), so if a pattern from another language fails here, the message tells you exactly which construct the JS engine didn't accept.

Performance and privacy

Everything in this tool runs locally in your browser. Your regex pattern, your test text, and your matches are never uploaded, never logged, and never sent to any external service. When you close the tab, all state is discarded.

Live processing is debounced so typing stays responsive even with large inputs. The match list is capped at a few hundred entries and the highlight preview at roughly a couple of hundred kilobytes — you'll see an explicit note when a limit is reached, never a silent truncation. If you feed it a pattern with catastrophic backtracking characteristics, the browser tab can still become unresponsive for the duration of the match; that's a limitation of the underlying JavaScript engine, not something a wrapper can prevent.

Related developer tools

Frequently asked questions

Is this Regex Tester free?

Yes. No signup, no account, no limits, no rate limits. The tool is fully client-side.

Is my regex or test text uploaded anywhere?

No. Everything runs in your browser using the native JavaScript RegExp engine. Nothing is transmitted, logged, or stored.

Which regex flavour does this tool use?

JavaScript (ECMAScript). That's the same engine used by your browser's DevTools console, Node.js, and any front-end code — so results match what you'll get in production.

Do I need to type the /…/ delimiters?

No. Type the pattern only — the delimiters are shown as decoration. If you paste a pattern that includes them, the tool strips them automatically.

Why is the v flag missing?

Because your current browser doesn't support it. The tool detects which flags the runtime actually accepts and only shows those.

How do I match across multiple lines?

Enable s (dotAll) so . matches newlines, or use [\s\S] which always matches any character including newlines regardless of flags.

How do I test that the whole input matches?

Anchor the pattern: ^…$. Without anchors, the regex matches a substring anywhere in the text.

Why does String.replace only replace one occurrence?

Because the pattern doesn't have the g flag. Enable it — the tool shows you the current flag state above the replacement result.

Can I use named groups?

Yes: (?<year>\d{4}). The tool lists them separately from numbered groups, and you can reference them in replacements with $<year>.

Why does my regex hang the tab?

Almost certainly catastrophic backtracking. Patterns with nested quantifiers over ambiguous classes can take exponential time on non-matching input. Simplify the pattern — for example, replace (a+)+ with a+ — or reduce the test text size.

Can I test a regex on a very large text?

Yes, up to the practical limits of your browser. The highlight preview is capped for readability and performance, and the match list is capped at a few hundred entries — you'll see a note when that happens. Matching itself runs on the full text.

Does it support lookbehind?

Yes — modern browsers support (?<=…) and (?<!…). If your browser doesn't, the pattern will fail to compile and you'll see the engine's error.

Is there a cheat sheet?

Yes, at the bottom of the tool. It covers character classes, quantifiers, anchors, groups, alternation, lookarounds, and flags.

Can I save my patterns?

Not in this version. Copy the pattern with the Copy regex button and store it in your own notes or code editor.

Test a regex now

Type a pattern, paste some text, and see matches highlighted instantly — capture groups, named groups, and replacements included. All local, all free.