Regex Works in Regex101 but Not in JavaScript — Why?
Every developer who uses regex long enough eventually experiences this moment:
You test a pattern in Regex101. It matches perfectly. You paste it into JavaScript.
And suddenly:
- no matches
- syntax errors
- broken capture groups
- unexpected behavior
- partial results
At first it feels irrational.
“But it literally worked five seconds ago.”
The problem is that regex behavior is NOT universal across languages and runtimes.
Regex101 is incredibly useful, but many developers unknowingly test patterns against a regex engine that behaves differently from JavaScript.
This article explains why regex works in Regex101 but fails in JavaScript, the most common causes developers encounter in real projects, and how to debug these problems systematically.
If you want to experiment while reading, the Regex Tester runs patterns directly with JavaScript-compatible behavior
The Core Problem: Regex Engines Are Different
This is the most important concept to understand.
Regex is NOT one single universal language.
Different runtimes use different regex engines.
Examples:
| Platform | Regex Engine |
|---|---|
| JavaScript | ECMAScript Regex |
| Python | re engine |
| PHP | PCRE |
| Go | RE2 |
| Java | Java Pattern |
| .NET | .NET Regex |
Regex101 often defaults to:
- PCRE (PHP)
But JavaScript uses:
- ECMAScript regex
These engines support different:
- syntax
- features
- flags
- lookbehinds
- Unicode handling
- backtracking behavior
This is the root cause of most “works in Regex101 but not JS” bugs.
Problem #1: Lookbehind Support
This is one of the most common issues.
Pattern:
(?<=\$)\d+
Works perfectly in:
- modern PCRE
- Regex101
But older JavaScript environments fail completely.
Why?
Lookbehind support was added relatively late to JavaScript.
Older browsers and runtimes do not support it.
Example Error
Invalid regular expression
Safer Alternative
Instead of:
(?<=\$)\d+
Use capture groups:
\$(\d+)
Then extract:
- group 1
Much more compatible.
Problem #2: Escaping Rules in JavaScript Strings
This causes endless confusion.
Regex101 lets you write:
\d+
But JavaScript strings require DOUBLE escaping.
Broken JavaScript Example
const regex = "\d+";
This does NOT work correctly.
JavaScript interprets:
\das:- escaped string character
Correct Version
const regex = "\\d+";
Or better:
const regex = /\d+/;
Regex literals avoid many escaping problems.
Real Production Bug Example
Developers commonly build regex dynamically:
const input = "\\w+";
const regex = new RegExp(input);
This becomes extremely error-prone with:
- backslashes
- Unicode
- nested escaping
Dynamic regex generation is harder than most people expect.
Problem #3: Flags Behave Differently
Regex101 may automatically apply flags.
JavaScript may not.
Example:
hello
Regex101:
- matches globally
- ignores case
- handles multiline automatically
JavaScript:
/hello/
may behave differently.
Important JavaScript Flags
| Flag | Meaning |
|---|---|
g | global |
i | case-insensitive |
m | multiline |
s | dotAll |
u | Unicode |
Missing flags are a huge source of regex bugs.
Problem #4: Dot Does Not Match Newlines
A classic issue.
Regex:
ERROR:.*
Input:
ERROR:
Database failed
Regex101 may appear to work depending on settings.
JavaScript often fails because:
.does NOT match newlines by default.
Fix
Use the s flag:
/ERROR:.*/s
Or:
/ERROR:[\s\S]*/
Older JS runtimes relied heavily on [\s\S].
Problem #5: Greedy Matching Behaves Unexpectedly
Regex often matches WAY more text than developers expect.
Example:
<div>.*</div>
Input:
<div>Hello</div><div>World</div>
Result:
<div>Hello</div><div>World</div>
because:
.*is greedy.
Related reading: Regex Greedy vs Lazy Matching Explained Simply
Fix
Use lazy matching:
<div>.*?</div>
This issue appears constantly in:
- HTML extraction
- markdown parsing
- AI output parsing
Problem #6: Unicode Handling Differences
Regex101 and JavaScript may treat Unicode differently.
Example:
^\w+$
This may fail for:
こんにちは
because:
\wbehavior varies.
Proper Unicode Support
Use:
/^\p{L}+$/u
The u flag matters enormously.
Without it:
- Unicode property escapes fail.
Problem #7: JavaScript Lacks Some PCRE Features
PCRE is more feature-rich than JavaScript regex.
Features missing or limited in JS:
- atomic groups
- recursion
- conditional expressions
- advanced backtracking controls
Example unsupported syntax:
(?(1)yes|no)
Works in PCRE. Fails in JavaScript.
Problem #8: Regex101 Uses Different Modes
Regex101 has configurable engines:
- PCRE
- ECMAScript
- Python
- Golang
Many developers accidentally test with:
- PCRE
then run code in:
- JavaScript
Always verify the selected engine.
This mistake is incredibly common.
Problem #9: Invisible Whitespace
Regex debugging often fails because input is not what developers think it is.
Example:
const text = "hello ";
Regex:
/^hello$/
Fails because:
- trailing space exists.
Useful Debugging Trick
console.log(JSON.stringify(text));
This exposes:
- tabs
- spaces
- newlines
Invisible characters cause a shocking number of regex bugs.
Problem #10: Browser Compatibility
Modern JavaScript regex features may work in:
- Chrome
but fail in:
- older Safari
- older Node.js
- embedded browsers
Especially:
- lookbehind
- Unicode property escapes
- named capture groups
Example
/(?<year>\d{4})/
Named groups are unsupported in older environments.
Safer Alternative
/(\d{4})/
Less elegant. More compatible.
Real Developer Workflow for Regex Debugging
Experienced developers debug regex systematically.
Step 1: Verify the Regex Engine
Make sure:
- Regex101 engine matches your runtime.
For JavaScript:
- use ECMAScript mode.
Step 2: Simplify the Pattern
Reduce complexity first.
Start with:
hello
Then gradually rebuild.
Step 3: Check Escaping
Especially when using:
new RegExp()
Escaping bugs are extremely common.
Step 4: Inspect Flags
Many regex failures come from:
- missing
g - missing
m - missing
s - missing
u
Step 5: Test Real Input
Toy examples often hide production problems.
Especially:
- multiline content
- Unicode
- HTML
- AI-generated text
Regex in AI-Generated Code
AI-generated regex often works in testing tools but fails in production JavaScript.
Why? Because generated patterns frequently:
- assume PCRE support
- overuse lookbehinds
- rely on unsupported syntax
- ignore escaping differences
Developers increasingly need to:
- simplify generated regex
- validate runtime compatibility
- reduce engine-specific dependencies
Common Real-World Example
This works in Regex101:
(?<=#)\w+
Fails in older JS runtimes.
Safer JS-compatible version:
#(\w+)
Then extract:
- capture group 1
Simple transformations like this improve compatibility dramatically.
Useful Related Tools
While debugging regex issues, these tools are often useful:
Common Regex Debugging Mistakes
Testing with the Wrong Engine
This is the biggest issue.
Always match:
- test environment to:
- production runtime
Copy-Pasting Stack Overflow Regex Blindly
Many patterns assume:
- PCRE
- advanced engines
- unsupported features
Overcomplicating Patterns
Huge regex patterns become:
- fragile
- unreadable
- hard to debug
Ignoring Browser Support
Modern syntax is not universally available.
Especially in enterprise environments.
FAQ
Why does regex work in Regex101 but not JavaScript?
Usually because:
- Regex101 is using a different regex engine than JavaScript.
PCRE and ECMAScript behave differently.
Does Regex101 support JavaScript regex?
Yes.
But you must select:
- ECMAScript mode
Otherwise results may differ.
Why does lookbehind fail in JavaScript?
Older JS runtimes do not support lookbehind assertions.
Why does \d fail in JavaScript strings?
Because JavaScript strings require escaping:
"\\d+"
Why does dot (.) not match newlines?
JavaScript excludes line breaks unless:
sflag is enabled.
Why does regex work in Chrome but fail in Safari?
Browser regex support differs, especially for newer features.
What is the safest way to build regex in JavaScript?
Regex literals are usually safer:
/\d+/
instead of:
new RegExp("\\d+")
Final Thoughts
Regex problems are frustrating partly because the pattern often looks correct.
And technically… it may BE correct.
Just not for the regex engine your application actually uses.
That is why experienced developers eventually stop asking:
“Does this regex work?”
and start asking:
“Does this regex work in THIS runtime?”
That distinction changes everything.
Once you understand:
- engine differences
- escaping rules
- flag behavior
- runtime compatibility
regex debugging becomes much less mysterious.
And honestly, using a Regex Tester early saves an enormous amount of wasted debugging time
You may also find these developer tools useful while debugging structured text and encoded data: