Copied!
Back
Developer Tool

JavaScript Regex Tester

Test and debug JavaScript regular expressions with live highlighting, capture groups, and all flags (g/i/m/s/u/y). Uses the native ECMAScript RegExp engine in your browser. No upload, no signup.

Last updated: April 2026
regex-tester.tool
/ / gi
0 characters
Results will appear here...

What is a regular expression?

A regular expression (regex, regexp, or RE) is a sequence of characters that defines a search pattern. Originally formalized by mathematician Stephen Kleene in the 1950s as a way to describe regular languages, regular expressions became a programmer's tool in the 1970s when Ken Thompson built them into the ed editor and later grep. Today every modern programming language ships a regex engine — JavaScript's RegExp, Python's re, PCRE in PHP, Java's java.util.regex, Go's regexp, and Rust's regex crate.

Regex shines for tasks that look easy in English but are awkward in plain code: "find every email address in this log", "extract the version number from a release tag", "validate that a phone number has 10 digits", "split a CSV row that may contain quoted commas." A pattern of 10–30 characters can replace 50 lines of imperative parsing logic. The trade-off is readability — regex is famously write-only. The pattern ^(?:[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*|"...")@ is a real fragment from email validation.

Modern engines support far more than the 1950s formalism. Lookahead, lookbehind, named groups, backreferences, unicode property escapes, possessive quantifiers — each addition makes patterns more powerful but also riskier. The most-cited regex bug in production, catastrophic backtracking, can hang an entire process for seconds on a 100-character input.

How regex matching works under the hood

Regex engines come in two architectures, and the choice affects what your pattern can do and how fast it runs:

Engine typeUsed byProsCons
Backtracking (NFA) JavaScript, Perl, Python re, PCRE, Java, Ruby, .NET Supports lookaround, backreferences, recursion. Most "modern features." Worst-case exponential time. Catastrophic backtracking on adversarial input.
Linear-time (DFA / hybrid) Go's regexp, Rust's regex, RE2, awk, grep, lex Linear O(n) time. Predictable performance. Cannot hang. No backreferences, no lookaround (Go & Rust). Fewer features.

The matching process for a backtracking engine, conceptually:

  • Compile the pattern into a state machine (NFA). Most languages cache compiled regex; recompiling in a hot loop is wasteful.
  • Walk the input character by character, advancing through states. When a quantifier like * is met, the engine greedily consumes as many characters as possible.
  • On mismatch, the engine backtracks — gives up matched characters one at a time and tries alternative paths. This is where pathological patterns hang: a pattern like (a+)+b on input aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa creates 2^n backtracking paths.
  • Report match position and capture groups, or fail.

Regex flavor comparison — JavaScript vs PCRE vs Python

"Regex" is not one language. Each ecosystem has subtle differences. Patterns that work in PHP may fail or behave differently in JavaScript. Knowing the deltas saves hours of debugging.

FeatureJavaScriptPython (re)PCRE (PHP, Perl)Go / Rust (RE2)
Lookahead (?=...) Yes Yes Yes No
Lookbehind (?<=...) Yes (ES2018+) Yes (fixed-width only) Yes (variable-width) No
Named groups (?<name>...) Yes (ES2018+) Yes ((?P<name>...)) Yes Yes (Rust)
Backreferences \1 Yes Yes Yes No
Unicode property \p{L} Yes (with u flag) Yes (Python 3) Yes Yes
Possessive quantifier *+ No No (use atomic groups) Yes No (not needed)
Catastrophic backtracking risk High High High None — guaranteed linear time

This tester uses the JavaScript flavor via the browser's native RegExp object. Patterns tested here will work identically in Node.js and most modern browser-based code. For PCRE-specific features, test in PHP's preg_match; for safety in untrusted input, switch to RE2 / Go.

Pattern anatomy — a regex cheat sheet

Anchors and boundaries

TokenMeaningExample match
^Start of string (or line, with m flag)^foo matches "foo" only at start
$End of string (or line, with m flag)bar$ matches "bar" only at end
\bWord boundary\bcat\b matches "cat" but not "category"
\BNon-word boundary\Bcat matches "cat" inside "concatenate"

Character classes

TokenMeaningEquivalent
.Any character (except newline, unless s flag)[^\n]
\dDigit[0-9]
\DNon-digit[^0-9]
\wWord character[A-Za-z0-9_]
\WNon-word character[^A-Za-z0-9_]
\sWhitespace[ \t\n\r\f\v]
[abc]Custom class — a, b, or c
[^abc]Negated class — anything but a, b, c
[a-z]Range

Quantifiers

TokenMeaningGreedy / lazy
*0 or moreGreedy. Use *? for lazy.
+1 or moreGreedy. Use +? for lazy.
?0 or 1 (optional)Greedy. Use ?? for lazy.
{n}Exactly n
{n,}n or moreGreedy. Use {n,}? for lazy.
{n,m}Between n and mGreedy. Use {n,m}? for lazy.

Groups and lookaround

TokenMeaning
(...)Capture group — captures match for backreferences
(?:...)Non-capturing group — groups without storing
(?<name>...)Named capture group (ES2018+)
(?=...)Positive lookahead — match if followed by
(?!...)Negative lookahead — match if NOT followed by
(?<=...)Positive lookbehind — match if preceded by
(?<!...)Negative lookbehind — match if NOT preceded by
\1, \2...Backreference to numbered capture group

Flags

FlagEffect
gGlobal — find all matches, not just first
iCase-insensitive
mMultiline — ^ and $ match line starts/ends
sDotAll — . matches newlines
uUnicode — full Unicode + \p{...} property escapes
ySticky — match starting at lastIndex only

Common regex patterns — copy-paste ready

Battle-tested patterns for the most-asked validation tasks. Adjust the strictness for your use case — these are pragmatic, not RFC-perfect. Once you have a slug-style pattern dialed in, the URL slug generator applies the same rules end-to-end, and the regex explainer turns any pattern into plain-English documentation for your team.

JS regular expression tester — what makes JavaScript regex different

JavaScript's RegExp is a backtracking NFA engine with a few quirks that trip up developers porting patterns from PHP, Python, or Perl. The g (global) flag is stateful — calling .exec() in a loop advances lastIndex, so reusing a global regex across functions can skip matches. Lookbehind (?<=...) shipped in ES2018 but Safari only added it in 16.4 (March 2023) — patterns that need to support older iOS still need workarounds. matchAll() (ES2020) is the modern way to iterate every match without managing lastIndex yourself. Unicode property escapes (\p{Letter}, \p{Emoji}) require the u flag and unlock proper non-Latin matching. The tester above runs your patterns through this exact engine — if it matches here, it matches in production browsers.

Regexp tester, regex evaluator, regular expression tester — they all mean the same thing

Search-engine variants of the same intent: "regex tester", "regexp tester", "regex evaluator", "regular expression tester", "regex tester javascript", "regex javascript tester", "javascript regex checker", "js regex online" — all five-to-eight-word phrasings ask for the same workflow. Paste a pattern, paste a test string, see matches highlighted, inspect capture groups. The tool above does that and nothing more. The match-count badge updates as you type; named groups appear in the capture-group panel; flag toggles on the right control case sensitivity, multiline behavior, and dotAll mode without rebuilding the regex string by hand. If your pattern has a bug, the error display shows the column where parsing failed — same line/column format Node and modern browsers emit in their stack traces.

JS regex online — what changed in ECMAScript 2024 and 2025

JavaScript regex picked up two new features recently. ES2024 added the v flag ("Unicode sets"), which extends u-flag behavior with set notation — /[\p{ASCII}--[abc]]/v means "ASCII characters except a, b, c". Use it when your pattern needs Unicode property escapes and set difference/intersection. ES2025 finalized RegExp.escape() for safely embedding user input into a pattern (no more manual str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') escape helpers). The tester above runs in your browser's native engine, so you'll see ES2024+ behavior directly — paste a /v-flag pattern and the engine accepts it on Chrome 124+, Firefox 116+, Safari 17.4+.

Regex101 alternative without ads or signup

Regex101 dominates this category but logs your patterns server-side, requires an account to save snippets, and shows ads on free tier. This page does the same job — pattern + flags + test string + capture-group inspection — entirely client-side. No upload, no telemetry on your patterns, no rate limits. If you want a plain-English breakdown of what your pattern matches token-by-token, paste it into the regex explainer next door.

Use casePatternNotes
Email (pragmatic) ^[\w.+-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*$ Catches 99% of real emails. Don't use full RFC 5322 — verify deliverability instead.
URL (http/https) ^https?:\/\/[^\s/$.?#].[^\s]*$ Loose validation; for strict, use new URL().
IPv4 ^(?:(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d?\d)$ Validates each octet 0–255.
UUID v4 ^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$ Add i flag for uppercase support.
Hex color ^#?([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$ 3-digit, 6-digit, or 8-digit (with alpha). Use i flag.
ISO 8601 date (basic) ^\d{4}-\d{2}-\d{2}(?:T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z?)?$ Accepts YYYY-MM-DD or full timestamp.
Strong password (length + 4 classes) ^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^A-Za-z0-9]).{8,}$ Lookahead enforces each character class.
Phone (E.164) ^\+[1-9]\d{1,14}$ International standard. No spaces or dashes.
Slug (URL-safe) ^[a-z0-9]+(?:-[a-z0-9]+)*$ Lowercase, hyphens between alphanumeric runs.

Regex in 8 programming languages

JavaScript / TypeScript

javascript
// Test, match, replace
const re = /(\w+)@(\w+\.\w+)/g;
"send to a@b.com".match(re);          // ['a@b.com']
"a@b.com".replace(re, '[email]');     // '[email]'

// Named groups (ES2018+)
const m = "2026-04-30".match(/^(?<y>\d{4})-(?<m>\d{2})-(?<d>\d{2})$/);
m.groups.y;  // '2026'

// Iterate all matches with positions
for (const m of "abc 123 xyz 456".matchAll(/\d+/g)) {
  console.log(m[0], m.index);
}

Python

python
import re

# search/match/findall/finditer
m = re.search(r'(\w+)@(\w+\.\w+)', 'send to a@b.com')
m.group(0)       # 'a@b.com'
m.group(1)       # 'a'

# Named groups: (?P<name>...)
m = re.match(r'(?P<year>\d{4})-(?P<month>\d{2})', '2026-04')
m.group('year')  # '2026'

# Compile once, reuse many times
pattern = re.compile(r'\d+')
[m.group() for m in pattern.finditer('abc 123 xyz 456')]

PHP (PCRE)

php
// Match (returns 1, 0, or false)
if (preg_match('/^(\d{4})-(\d{2})$/', '2026-04', $m)) {
    echo $m[1];  // '2026'
}

// Find all
preg_match_all('/\d+/', 'abc 123 xyz 456', $matches);

// Replace
$clean = preg_replace('/\s+/', ' ', $messy);

Java

java
import java.util.regex.*;

Pattern p = Pattern.compile("(\\w+)@(\\w+\\.\\w+)");
Matcher m = p.matcher("send to a@b.com");
if (m.find()) {
    System.out.println(m.group(0));  // a@b.com
    System.out.println(m.group(1));  // a
}

// Replace
String clean = "  multiple   spaces  ".replaceAll("\\s+", " ");

Go

go
import "regexp"

// MustCompile panics on invalid pattern (good for static patterns)
re := regexp.MustCompile(`(\w+)@(\w+\.\w+)`)
match := re.FindStringSubmatch("send to a@b.com")
// match[0] = "a@b.com", match[1] = "a"

// All matches
all := re.FindAllString("a@b.com c@d.org", -1)

Rust

rust
use regex::Regex;

let re = Regex::new(r"(\w+)@(\w+\.\w+)").unwrap();
if let Some(caps) = re.captures("send to a@b.com") {
    println!("{}", &caps[0]);  // a@b.com
}

// Iterate all
for m in re.find_iter("a@b.com c@d.org") {
    println!("{}", m.as_str());
}

Ruby

ruby
# =~ returns match position or nil
"send to a@b.com" =~ /(\w+)@(\w+\.\w+)/
puts $~[0]   # 'a@b.com'

# scan for all matches
"a 1 b 2 c 3".scan(/\d/)   # ['1','2','3']

# Named captures via MatchData
m = "2026-04".match(/(?<year>\d{4})-(?<month>\d{2})/)
m[:year]   # '2026'

Bash (grep / sed)

bash
# Extended regex with grep -E
echo "abc 123 xyz" | grep -oE '[0-9]+'

# Capture and replace with sed
echo "2026-04-30" | sed -E 's/^([0-9]{4})-([0-9]{2}).*/\1\/\2/'

# Test from a script
if [[ "$input" =~ ^[0-9]+$ ]]; then echo "all digits"; fi

Catastrophic backtracking — and how to avoid it

The single biggest production bug regex causes is catastrophic backtracking: a pattern that takes milliseconds on a 10-character input takes 30+ seconds on a 30-character input. The classic example: ^(a+)+$ against the string "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!". The engine tries 2^33 possible groupings before giving up.

What causes it

  • Nested quantifiers: (a+)+, (a*)*, (.+)+
  • Overlapping alternations: (a|a)*, (a|aa|aaa)+
  • Greedy quantifiers + backtracking-friendly suffixes: ".*" in ".*"foo when the input has no foo

How to avoid it

  • Use atomic groups or possessive quantifiers in PCRE: (?>a+) or a++ commit to the match and prevent backtracking.
  • Be more specific than .*. If you mean "characters that aren't quotes", use [^"]* not .*.
  • Anchor with ^ and $ when validating fixed-length input. Engine bails out faster on mismatch.
  • Switch engines for untrusted input. Go's regexp and Rust's regex use RE2 — guaranteed linear time, no catastrophic backtracking possible. Lose lookaround & backreferences in exchange for safety.
  • Set timeouts. .NET 7+ supports RegexOptions.NonBacktracking and explicit timeouts. PCRE2 has JIT_STACK limits.
Test in this tool first. Paste your pattern and a long input. If matching takes more than 100ms, redesign the pattern. The browser will eventually time out, but production users won't be so patient.

Regex best practices for 2026

  • Don't validate emails with regex alone. The full RFC 5322 grammar is > 6,000 characters of regex. Use a simple sanity check (.+@.+\..+) and verify by sending a confirmation link.
  • Comment complex patterns. JavaScript: prefix lines with // and concat. Python and PCRE: use the x flag for verbose mode with embedded comments.
  • Compile once, reuse always. In hot loops, compile the regex outside the loop. Most languages cache automatically; Python's re.compile and Java's Pattern.compile are explicit.
  • Use ?: for grouping when you don't need capture. Faster matching, cleaner output. (?:foo|bar)+ not (foo|bar)+.
  • Never use regex to parse HTML or XML. Both are context-free languages. Use a real parser (DOMParser, lxml, BeautifulSoup, jsdom). Regex is fine for finding simple, well-defined patterns inside HTML, just not for parsing structure.
  • Use named capture groups when extracting more than 2 values. Self-documenting and safer if the pattern changes.
  • Test against edge cases: empty string, all whitespace, Unicode, very long input. Most regex bugs surface at the extremes.

How this regex tester compares to popular alternatives

regex101.com has been the de-facto regex testing reference since 2011. Most other regex testers exist in its shadow. The 2026 differentiation is less about features and more about: which regex flavors you need, whether you want a paired explainer for patterns you didn't write, and whether you'd rather work in a single dev-tool catalog instead of jumping between specialized sites. Here's the honest comparison.

CapabilityFreeDevTool /regex-testerregex101.comregexr.comiHateRegex.io
JavaScript regex (ECMAScript)✅ Native browser engine
PCRE / PCRE2 / Boost flavors
Python regex flavor
Java / Golang / Rust regex flavors
Live match highlighting
Capture groups breakdown✅ With group index colors
Substitution / replace mode
Plain-English pattern explainerDedicated /regex-explainer tool✅ Built-in panel✅ Built-in panel⚠️ Visualization only
Catastrophic backtracking warnings✅ Performance tab
Code generation (regex → Python / JS / etc.)❌ Roadmap
Save patterns without an account✅ Browser localStorage⚠️ Account suggested⚠️ Account suggested
Paired with long-form regex referenceRegex Explainer with 4,000-word guide⚠️ Quick cheatsheet⚠️ Cheatsheet
Part of a broader 50-tool catalog✅ Plus 4 in-depth guides❌ Regex only❌ Regex only❌ Regex only
Paid / Pro tier exists❌ Free only✅ ~$5/mo

When to pick which tool

  • Pick FreeDevTool /regex-tester when: you're testing JavaScript regex (the most common case in modern web work), you want a paired explainer tool to understand someone else's pattern, you don't want to create an account, and you'd benefit from being part of a broader 50-tool catalog you already use.
  • Pick regex101 when: you need PCRE / PCRE2 / Python / Java / Go regex flavors, deep optimization analysis (catastrophic-backtracking detection on the Performance tab), or one-click code generation in your target language. regex101 is the gold standard for those use cases — this guide isn't trying to replace it.
  • Pick regexr.com when: you want a friendlier visual learning experience for JavaScript regex with side-by-side cheatsheet.
  • Pick iHateRegex.io when: you want to find a pre-built pattern for a common case (email, phone, URL) without writing your own.

This is an honest comparison, not a marketing pitch. If you're tuning a Python production regex with concern about backtracking, regex101's Performance tab is the right tool. Where FreeDevTool genuinely differentiates is the tester + paired explainer + 4,000-word reference + 50-tool ecosystem combination — useful when regex work is one task in a longer dev workflow, especially in JavaScript codebases.

Frequently compared regex tools

If you're researching regex tester alternatives, you're probably also looking at: regex101.com, regexr.com, iHateRegex.io, pythex.org (Python only), rubular.com (Ruby only). The regex101 dominance reflects 13 years of authority and a team focused entirely on regex; pick whichever specializes in your specific need.

How to use the regex tester

Test regular expressions against real input with live highlighting, capture groups, and match counts. The tester uses JavaScript regex flavor by default — same engine as your browser, Node.js, and most modern web stacks. Patterns and test data stay local; nothing is sent to a server.

Common regex mistakes to avoid

Frequently Asked Questions

How do I test a regular expression online?
Enter your regex pattern in the pattern field and paste your test string below. Matches are highlighted in real time as you type. This tool uses JavaScript's native RegExp engine — the same engine that runs in Chrome, Firefox, Node.js, and Deno. Capture groups are extracted and displayed with their index and position. All processing runs in your browser with zero server calls.
What do the regex flags g, i, m, s mean?
g (global) — find all matches, not just the first. i (case-insensitive) — /abc/i matches "ABC", "Abc", etc. m (multiline) — ^ and $ match start/end of each line, not just the whole string. s (dotAll) — . matches newline characters (\n). u (unicode) — enables full Unicode support and proper handling of surrogate pairs.
What is the difference between greedy and lazy regex matching?
Greedy quantifiers (*, +, {n,}) match as much text as possible. Lazy quantifiers (*?, +?, {n,}?) match as little as possible. Example: on the string <b>hello</b>, the greedy pattern <.*> matches the entire string, while the lazy <.*?> matches only <b>. Use lazy quantifiers when you want the shortest possible match.
How do I validate an email address with regex?
A practical email regex is: ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$. This covers the vast majority of valid email addresses. The full RFC 5322 specification is extremely complex and nearly impossible to match with a single regex. For production applications, use a dedicated email validation library or send a confirmation email rather than relying on regex alone.
What are capture groups in regex?
Capture groups use parentheses () to extract specific parts of a match. For example, the pattern (\d{4})-(\d{2})-(\d{2}) on the string "2026-03-20" creates three groups: "2026", "03", "20". Named groups use (?<name>...) syntax for clearer code. Non-capturing groups (?:...) group patterns without capturing — useful for alternation like (?:cat|dog).

Browse all 50 free developer tools

All tools run in your browser, no signup required, nothing sent to a server.