🧩 Regex Tester

Test JavaScript regular expressions live against your own text. See matches highlighted instantly, with index positions and capture groups for every match.

🧩 Pattern & Test String
Allowed: g (global), i (ignore case), m (multiline), s (dotAll), u (unicode), y (sticky).
🎯 Match Results
Total Matches
Highlighted Test String
Match Details
#IndexMatched TextCapture Groups
⚠️ Uses JavaScript's native RegExp engine (the same one running in your browser). Behavior may differ slightly from PCRE, Python, or .NET regex flavors. Everything runs locally — nothing is transmitted, logged, or stored.
🔍

Enter a pattern and test string to see matches

Guide

About the Regex Tester

Last updated: August 2026 · Reviewed by the NeftCal editorial team

The regex tester at NeftCal is a free, browser-based tool for live-testing JavaScript regular expressions against your own text. Type a pattern and flags, paste a test string, and every match is highlighted instantly, with a details table showing each match's zero-based index and any capture groups it produced. Because it runs on the native JavaScript RegExp engine — the same implementation used by every browser and Node.js — what you see here is exactly what your production code will do. No signup, no uploads, no network calls: the entire tool runs locally on your device.

What This Tool Does

It compiles your pattern with the standard RegExp constructor, validates the flags field (g, i, m, s, u, y — no duplicates), and scans the test string using String.prototype.matchAll() when the g flag is set, exactly mirroring JavaScript runtime behavior. Every match is rendered inline as a highlighted span, and a table beneath lists each match's number, start index, matched text, and capture groups — with (undefined) shown for optional groups that did not participate. Invalid patterns and flags surface a clear error message instead of an uncaught exception.

Who Should Use This Tool

It's built for web and Node.js developers validating form input, parsing logs, or writing search-and-replace routines; data engineers cleaning and extracting fields from messy text; QA engineers sanity-checking patterns against edge cases; and students learning how regex engines think. Because it runs on the same engine your code uses, it doubles as a precise debugging harness — if a pattern behaves one way here and differently elsewhere, the culprit is almost always a flavor difference between JavaScript and PCRE, Python, or .NET.

Why Testing Regex Matters

Regular expressions are notoriously easy to get subtly wrong — an unescaped special character, a missing anchor, or a greedy quantifier that matches far more than intended. Testing a pattern against realistic sample text before dropping it into production code catches these mistakes early, when they're cheap to fix, rather than after they've silently rejected valid input or let bad input through. This mirrors how engineers validate infrastructure decisions with tools like the Code Complexity Estimator or the API Rate Limit Calculator: verify the behavior before you rely on it.

Real-World Applications

  • Validating user input in web forms (email, phone, URL, date) and copying the tested pattern directly into your frontend code
  • Parsing server logs and config files to extract timestamps, error codes, IP addresses, or user identifiers
  • Preparing search-and-replace or data-cleaning scripts before running them on a real dataset
  • Reviewing patterns alongside your codebase with NeftCal's Code Complexity Estimator for maintainability
  • Checking identifier transforms and hashing output with the Hash Generator when normalizing keys

Tips for Accurate Results

  • Always add the g flag when you expect more than one match — without it, JavaScript's engine stops after the first match
  • Anchor validation patterns with ^ and $ so they must match the whole input, not just a substring
  • Test edge cases deliberately: empty strings, whitespace-only input, and strings containing regex metacharacters like . or *
  • Remember JavaScript-specific syntax quirks — some lookbehind and named-group constructs need the u flag
  • If the tester freezes or runs noticeably long on your input, suspect catastrophic backtracking and simplify nested quantifiers
Formula

The Regex Engine, Explained

How this regex tester turns a pattern and a test string into highlighted matches

The Matching Formula
Pattern → compiled RegExp object → executed against the test string at successive positions → yields match(es), each with an index and capture groups

Building Blocks
Literals: a, b, 1, _ match themselves · Metacharacters: . ^ $ * + ? { } [ ] \ | ( ) carry special meaning · Character classes: [a-z], \d, \w, \s · Quantifiers: * + ? {n,m} (greedy) and *? +? ?? {n,m}? (lazy) · Anchors: ^, $, \b · Groups: (capture), (?:non-capture), (?<name>named) · Alternation: a|b

The Global Match Formula
With g flag: matches = [...testString.matchAll(regex)] · Without g: matches = regex.exec(testString) ? [m] : []

The tester wraps compilation and matching in a try/catch, so an invalid pattern shows the engine's own error message and a flag field containing anything outside g/i/m/s/u/y — or a repeated flag — is rejected up front. With the g flag, matching uses matchAll(); without it, a single exec() returns only the first match, matching real runtime behavior.

🔤

Character Classes

\d matches any digit ([0-9]), \w any word character ([A-Za-z0-9_]), \s any whitespace — with negated forms \D, \W, \S and custom sets like [^...] for everything except a list.

⏱️

Quantifiers

* zero-or-more, + one-or-more, ? zero-or-one, {n,m} between n and m repeats. All are greedy by default; adding a trailing ? (*?, +?, ??) makes them lazy.

📍

Anchors & Boundaries

^ matches the start and $ the end of the string (with the m flag, of each line). \b matches a word boundary; the sticky y flag forces a match only at the exact current position.

⚙️ Why This Works

JavaScript engines compile a pattern into an internal automaton and walk the subject string left to right, backtracking when a branch fails until a match is found or the string is exhausted. Because this tester uses the native RegExp object, all of those semantics — leftmost-first matching, greedy backtracking, zero-width anchors, capture ordering — are identical to your runtime, so a pattern that works here will behave the same in your deployed code.

🎯 When to Use It

  • Validating form inputs and API payloads before shipping code
  • Extracting fields from logs, config files, and flat text
  • Debugging search-and-replace and data-cleaning scripts
  • Learning how quantifiers, anchors, and capture groups actually behave

📋 Assumptions

  • Patterns follow JavaScript RegExp syntax (not PCRE/Python/.NET)
  • Matching is leftmost-first and position-sensitive
  • Capture groups are returned in opening-parenthesis order
  • Indices are zero-based character positions, as in String.prototype.indexOf

⚠️ Limitations of the Engine

  • Nested quantifiers like (a+)+ or overlapping alternatives can trigger catastrophic backtracking (ReDoS) that freezes the tab
  • JavaScript has no possessive quantifiers or atomic groups, so some PCRE-safe patterns can't be expressed safely
  • The engine has no built-in timeout — a pathological pattern on a long input can hang the page
  • Without the u flag, some Unicode and astral-plane handling falls back to UTF-16 code-unit semantics
Walkthrough

Step-by-Step: How to Use the Regex Tester

From entering a pattern to reading every match's index and captures

Enter a regex pattern

Type or paste your JavaScript regular expression into the Regex Pattern field. The page defaults to \b[A-Za-z]+\b, which matches letter-only words at word boundaries.

Set your flags

Add g to find every match, plus i, m, s, u, or y as your pattern needs. Invalid or duplicate flags show a clear error instead of a crash.

Paste your test string

Enter or paste the text you want to search — including multiline content, which the field preserves. The tester re-runs live as you type.

Run the match

Click "Calculate Matches" (or simply keep typing, since the tool runs on every keystroke) to compile the pattern and scan the string with the native RegExp engine.

Inspect the highlighted text

Every match is highlighted inline in the test string view. The highlight is built from safe DOM text nodes, so characters like < and > are always shown literally.

Read the match details table

The table lists each match's number, zero-based start index, matched text, and capture groups — with (undefined) shown for optional groups that did not participate.

Example

Worked Example

Using the tester's own default scenario — pattern \b[A-Za-z]+\b with the g flag against the default 71-character test string

Scenario

Suppose you open the regex tester and leave the defaults in place: pattern \b[A-Za-z]+\b, flag g, and the test string "The quick brown fox jumps over the lazy dog. 42 foxes ran past in 2026." — a sentence that deliberately mixes letters, digits, and punctuation to exercise word boundaries.

Default Pattern\b[A-Za-z]+\b
Flagsg (global)
Test String71 characters
Step 1 — Compile: new RegExp('\\b[A-Za-z]+\\b', 'g') creates a global, case-sensitive, word-boundary-aware matcher.
Step 2 — Scan: matchAll() walks the string and returns 13 matches. Word boundaries split the sentence so each pure-letter word is its own match.
Step 3 — Boundaries in action: "The" (index 0), "quick" (4), "brown" (10), "fox" (16), "jumps" (20), "over" (26), "the" (31), "lazy" (35), "dog" (40) all match. "42" at index 45 is skipped — digits are not in [A-Za-z] — then "foxes" (48), "ran" (54), "past" (58), and "in" (63) match, and "2026" at index 66 is skipped for the same reason.
Step 4 — Captures: the pattern contains no parentheses, so every row's Capture Groups column shows (no groups).
Step 5 — Indices: each index is the zero-based character position where the match begins — "The" starts at character 0, the final match "in" at character 63.
Total Matches
13
First Match
"The" @ 0
Last Match
"in" @ 63
Capture Groups
0

Explanation: The \b anchor is what makes this a clean word matcher. It matches at the transition between a non-word character (space, punctuation, digit) and a word character, so the digit-containing words "42" and "2026" are correctly excluded while the surrounding words are all found. The g flag is essential — without it, only "The" at index 0 would be returned, because JavaScript's engine stops after the first match. The index column gives you the exact positions you'd pass to slice() in production code to locate or transform each match.

Interpretation

Understanding Your Match Results

What your match count and details table generally imply

Match CountWhat It Generally MeansRecommended Next Step
0 matchesThe pattern matched nothing in the test stringCheck the g flag, anchors (^...$ for whole-input), and whether metacharacters like . or * are escaped
1 matchWithout g, this is normal first-match behavior; with g, it means exactly one occurrence existsAdd g if you expected more; verify the details row confirms it's the right occurrence
Several matchesThe pattern finds multiple occurrences, as intendedReview the indices to confirm matches land in the right positions with no unintended partial hits
Many matchesEither a genuinely high occurrence count or a very permissive pattern like . or \w+Narrow the pattern with anchors, \b, or more specific character classes
Extremely slow / frozenPossible catastrophic backtracking (ReDoS)Simplify nested quantifiers and test on shorter inputs before trusting the pattern

If your pattern shows zero matches: the most common causes are a missing g flag when you expect multiple hits, an anchor mismatch (e.g., ^...$ vs. substring matching), or a metacharacter you meant literally that the engine treats as syntax. Escape it with a backslash.

If every cell in Capture Groups shows : your pattern has no capturing parentheses, so there is nothing to extract. Add (...) or a named group (?<name>...) around the piece of each match you actually need.

If the details table lists only one match: confirm the g flag is present. This is the single most common reason a pattern "isn't matching" the rest of the text.

ℹ️

This regex tester is an interactive diagnostic tool, not a correctness guarantee. A pattern that matches here still needs validation against your real data — including empty strings, unexpected characters, and malicious input — and a review for catastrophic backtracking before it goes into production code.

Use Cases

Practical Use Cases for the Regex Tester

Where live-testing a JavaScript regular expression genuinely helps

💬

Form validation patterns

Draft and verify email, phone, URL, and date patterns against valid and invalid inputs before wiring them into your forms.

📜

Log parsing and monitoring

Extract timestamps, error codes, IP addresses, and user IDs from log lines to build alerting or dashboards.

🔍

Data extraction

Use capture groups to pull structured fields out of unstructured text — invoices, emails, chat transcripts, CSV rows.

📝

Search-and-replace

Confirm a find-and-replace pattern behaves exactly as intended before running it across a whole codebase or dataset.

🧹

Data cleaning and normalization

Standardize messy user-entered text — spacing, separators, case — and verify the transform against sample rows.

🧪

Pattern unit-testing

Quickly check edge cases (empty strings, metacharacters, newlines) that a pattern may fail on once it's live.

🛡️

Input sanitization

Whitelist acceptable characters or strip disallowed ones, and confirm the pattern only permits what you allow.

🏷️

Syntax highlighting and linting

Build the token patterns behind a highlighter or linter, testing how each token class matches real source text.

🌐

Routing and URL matching

Verify path, query, and host patterns for web routing or middleware before deploying them.

🗂️

Structured text parsing

Parse config blocks, key-value pairs, and delimited records, checking captures against realistic sample files.

🎓

Learning and teaching regex

Watch greedy vs. lazy quantifiers, anchors, and backtracking in action — ideal for tutorials and workshops.

🔁

Refactoring legacy patterns

Re-test old, opaque patterns before touching them, and confirm replacements match the same inputs.

Pros & Cons

Benefits and Limitations

What this regex tester does well, and where it can't replace a full regex toolchain

✅ Benefits

  • Free, instant, and requires no signup or account
  • Runs entirely in your browser — your pattern and test string never leave the device
  • Uses the same native RegExp engine as your production JavaScript
  • Live highlighting plus a match table with indices and capture groups
  • Clear, descriptive errors for invalid flags and invalid patterns
  • Safe rendering — test strings containing HTML are never interpreted as markup
  • Handles multiline input with m/s flag support
  • Fast-loading and mobile-friendly, with no ads blocking the tool

⚠️ Limitations

  • JavaScript flavor only — PCRE, Python, and .NET syntax differences aren't modeled
  • No pattern builder, on-page cheat sheet, or saved-match history
  • No timing or performance diagnostics beyond a visible freeze
  • Capture groups are listed by number, not by name, in the results table
  • Can't validate calendar dates or domain semantics — it checks format, not meaning
  • Not a substitute for unit tests against your real data
Reference

Common Regex Patterns Reference

Battle-tested JavaScript patterns for everyday validation — test each one here before you use it

Use CaseCommon PatternWhat It MatchesCaveats
Email^[\w.+-]+@[\w-]+\.[\w.-]+$Standard email form (alice@example.com)Doesn't enforce full RFC 5322 grammar; good for most form validation
URL^https?://[\w.-]+(?:\.[\w.-]+)+[/\w.-]*$http/https URLs with host and optional pathRequires a scheme; use a URL parser library for complex cases
US Phone^\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}$(555) 123-4567, 555-123-4567, 5551234567US-centric and liberal about separators
Date (YYYY-MM-DD)^\d{4}-\d{2}-\d{2}$2026-08-03Accepts invalid dates like 2026-99-99; validate calendar semantics separately

Common Mistakes and Expert Tips

❌ Common Mistakes

  • Confusing greedy and lazy quantifiers — <.+> matches far too much (the whole <a> <b>), while <.+?> stops at the first >
  • Forgetting the g flag, then wondering why only one match appears
  • Omitting ^ and $ for whole-string validation, letting the pattern match a substring
  • Testing only happy-path inputs and missing empty strings, whitespace, or metacharacters
  • Writing nested quantifiers like (a+)+ that can trigger catastrophic backtracking
  • Assuming another regex flavor's syntax (PCRE, Python, .NET) works identically in JavaScript

💡 Expert Tips & Best Practices

  • Anchor validation patterns with ^...$ and test both valid and invalid inputs before deploying
  • Use capture groups — named where helpful — to extract fields rather than re-parsing matches afterward
  • Escape metacharacters deliberately when you want to match literal text, and prefer specific classes over .
  • Keep patterns simple and readable, and comment the tricky parts in your code
  • Pair this tester with the Code Complexity Estimator and API Rate Limit Calculator when reviewing production pipelines
📝

Summary: The Regex Tester lets you validate and refine JavaScript regular expressions against real text — instantly, privately, and with full visibility into indices and captures. Test the pattern, confirm edge cases, then copy it straight into your code. Pair it with the Code Complexity Estimator to keep patterns maintainable, and with the Password Strength Calculator when building validation rules for authentication.

FAQ

Frequently Asked Questions

Common questions about regex testing, flags, and JavaScript's RegExp engine

Which regex flavor does this tester use?
This tool uses JavaScript's native RegExp engine — the same implementation that runs in every modern browser and in Node.js. Because it compiles patterns with the standard RegExp constructor, the syntax, quantifiers, anchors, and flags behave exactly as they will in your production JavaScript code. That matters because regex flavors differ in real ways: PCRE (used by PHP and Python's re module) supports features like possessive quantifiers and conditional groups that JavaScript lacks, while .NET and PCRE2 support lookbehind of arbitrary length. JavaScript now supports lookbehind and named groups too, but some of those constructs require the u (unicode) flag. Testing in this tool tells you exactly what your target runtime will do.
What do the regex flags g, i, m, s, u, and y mean?
g (global) makes the engine find every match in the string instead of stopping after the first, and it's required for String.prototype.matchAll(). i (case-insensitive) makes matching ignore letter case, so [a-z] matches 'A' too. m (multiline) changes the behavior of ^ and $ so they also match at the start and end of each line, not just the whole string. s (dotAll) lets the . metacharacter match newline characters, which it excludes by default. u (unicode) switches to full Unicode-aware parsing, enabling code-point ranges, \p{...} property escapes, and correct handling of astral characters. y (sticky) anchors matching so the pattern can only match exactly at the current lastIndex position.
Why does my pattern only show one match?
Without the g (global) flag, JavaScript's regex engine returns only the first match by design — that's the documented behavior of RegExp.prototype.exec() and String.prototype.match() without g. The tester mirrors that behavior faithfully: it uses matchAll() when the g flag is present and a single exec() otherwise. If you expect several matches and only see one highlighted, the pattern itself is fine; you simply forgot to add g to the flags field. Add g and re-run to see every match, with each one's start index listed in the details table. This is one of the most common regex gotchas for people coming from flavors that scan globally by default.
Is my test string sent to a server?
No. Everything this regex tester does — flag validation, pattern compilation, matching, and highlight rendering — runs entirely in your browser using the native RegExp object and standard DOM APIs. There is no network request for your pattern or test string, nothing is transmitted, logged, or stored, and the page works identically with your network disconnected. This makes it safe to paste sensitive data such as API keys, tokens, or private log lines for quick pattern experimentation. Because the tool is 100% client-side, your test data never leaves your machine.
How are matches highlighted safely if my test string contains HTML-like text?
The highlighter builds its output with plain DOM text nodes and created elements rather than inserting raw HTML into innerHTML. Each matched span is a real element whose text is assigned via textContent, so characters like <, >, &, and quotes in your test string are always rendered literally and can never be interpreted as markup or script. This matters because regex testers that concatenate highlighted strings into HTML can corrupt output or become an injection vector when the test text contains HTML tags or entity-looking sequences. With this tool, pasting something like '<script>alert(1)</script>' displays exactly that text, with only the matched portions wrapped in a highlight span.
What does the "Index" column in the match table mean?
Index is the zero-based character position in your test string where each match begins — the same value JavaScript exposes as match.index on the object returned by exec() or matchAll(). It tells you where in the string the pattern matched, not the length of the match or its ending position. To slice out the matched text programmatically you'd use testString.slice(match.index, match.index + match[0].length). The index is especially useful for log parsing, syntax highlighting, and find-and-replace tooling where you need to know precisely where each hit occurs so you can transform or annotate the original text.
Why do I get an error about duplicate flags?
JavaScript's RegExp constructor rejects any flags string that repeats a flag character, so patterns like 'gg' or 'gig' throw a SyntaxError. The tester validates the flags field up front: it checks that every character is one of g, i, m, s, u, y and that no character appears twice, showing a clear message instead of letting the browser throw an uncaught exception. This duplicate-flag check mirrors the strictness of the native constructor, which also rejects flags that are not in the allowed set. If you see the duplicate-flag error, remove the repeated letter — flags are a set, and each one only needs to be listed once.
What does an undefined capture group mean in the results?
A capture group displays as '(undefined)' when that group is optional — for example, followed by a ? like (foo)? — and did not participate in the current match. This is normal JavaScript behavior, not an error: exec() and matchAll() set non-participating groups to undefined while participating groups hold their captured substring. The same group can be undefined in one match and populated in the next, which is exactly how optional groups behave in real pattern matching. In code, guard against this with something like match[1] ?? '' or a nullish check before using the captured value.
Can I test multiline text with this tool?
Yes — paste multiline text directly into the Test String box; the field preserves line breaks. By default, ^ and $ only match the very start and end of the entire string, not individual lines, so a pattern like ^foo will only find 'foo' at the beginning of the whole input. Add the m (multiline) flag to make ^ and $ also match at the start and end of each line, which is what you want for parsing logs, config files, or any line-oriented format. If you need a dot to cross line breaks as well, combine m with s (dotAll). The m flag only changes anchor behavior; it never affects how other constructs match.
Why does my pattern show a syntax error even though it looks correct?
JavaScript regex syntax has quirks that differ from other languages, and the browser's error message is your best diagnostic. Common causes: characters like {, }, (, ), [, ], *, +, and ? are metacharacters and must be escaped with a backslash when you want to match them literally; some named-group and lookbehind syntax such as (?<name>...) requires the u (unicode) flag; and lone quantifiers or unclosed groups produce parse errors. The tester catches the compilation error in a try/catch and echoes the engine's own message so you can fix the pattern rather than hitting a silent failure. Try adding the u flag for modern syntax, or escape special characters one at a time to isolate the problem.
Does this tool support named capture groups?
Yes — JavaScript's RegExp supports named capture groups with the syntax (?<name>...), and this tester runs on the native engine, so patterns using named groups work exactly as they do in your runtime. The match details table currently lists every capture group by its numeric position (group 1, group 2, ...) rather than by name, but named groups participate in matching identically to numbered ones — the name is just a more readable reference in code, for example match.groups.name. When a named group is optional and doesn't participate, it appears as undefined, matching standard behavior.
What happens if I leave the pattern field empty?
An empty pattern is technically valid in JavaScript and compiles to a regular expression that matches the empty string at every position. To keep results meaningful, this tester treats a blank pattern field as 'no pattern entered': it clears the highlighted view and match table and shows a total match count of 0 rather than compiling the empty pattern. This avoids the confusing behavior of an empty regex matching at every character boundary. To intentionally match an empty position, you'd enter an explicit pattern like /^/ or /a*/. If you see zero matches unexpectedly, first confirm the pattern field isn't empty.
Can I use this to build a regex for form validation or data extraction?
Yes. The tester is designed to let you iterate on a pattern against realistic sample inputs before you ship it. For form validation, paste valid and invalid examples (empty strings, extra whitespace, unexpected characters) and confirm your pattern anchored with ^...$ passes exactly the values you intend. For data extraction, use capture groups — numbered or named — to pull out the specific pieces you need from each match, then copy the working pattern and flags directly into your code's RegExp literal or constructor. Because the tool runs the same engine as your runtime, a pattern that behaves correctly here will behave the same way in your deployed JavaScript.
How can I tell if my regex is slow or vulnerable to catastrophic backtracking (ReDoS)?
Some patterns — especially nested quantifiers over overlapping alternatives, like (a+)+ or (a|a)* — can force the engine to try an exponential number of backtracking paths on certain inputs, causing the page or server to hang. That's called catastrophic backtracking and is the basis of ReDoS (regular expression denial of service) attacks. Symptoms here: a match that takes far longer than expected, or the tab freezing on a particular test string. To avoid it, prefer simple, unambiguous patterns; avoid nesting quantifiers such as (a+)+ or (a*)*; and for user-supplied patterns, cap input length or run matching in a worker. If the tester freezes on a realistic input, redesign the pattern.
What's the difference between greedy and lazy quantifiers?
By default, quantifiers like *, +, ?, and {n,m} are greedy: they consume as much as possible while still allowing the rest of the pattern to match. Adding a ? after the quantifier (as in *?, +?, ??, {n,m}?) makes it lazy, consuming as little as possible. For example, on '<a> <b>' the greedy <.+> matches the whole '<a> <b>', while the lazy <.+?> stops at '<a>'. Greedy matching is usually what you want for extraction because it maximizes the matched portion; lazy is useful for matching between delimiters like tags or quotes. The difference can be dramatic, and choosing wrong is a common source of 'matches too much' bugs.
Learn More

Authoritative Resources on JavaScript Regex

Official documentation to complement this tester — verify syntax and safety guidance before shipping patterns

Related Calculators

Explore other developer & tech tools