(?!...) is a negative lookahead assertion. It succeeds only when the text right after the current position does not match the inner pattern. It is zero-width—it peeks ahead without consuming characters or including them in the match.
Remember
(?!pattern) → "not followed by pattern"
/foo(?!bar)/
"foobaz" → "foo" ✓
"foobar" → null ✗
"foo" → "foo" ✓
zero-width: match result never includes the lookahead text
contrast: (?=...) positive lookahead (MUST follow)
Place the lookahead right after the text you want to keep.
Write the part you want to match (e.g. foo or \d+).
Add (?!forbidden) immediately after it.
Call test, match, or replace — the forbidden text is checked but not captured.
For whole-string bans, use ^(?!.*bad) at the start, then the rest of the pattern.
Piece
Required?
Role
(?!…)
Yes
Assert what must not follow
Text before it
Usual
What actually gets matched / returned
Inner pattern
Yes
The forbidden following text
Pseudocode
Pseudocode
re = /token(?!bad)/
find "token" in input
peek at the next characters (do not consume them)
if next characters match "bad":
fail this attempt
else:
succeed with match = "token" only
Reference
Cheat Sheet
Keep these lookahead facts handy.
Topic
Detail
Syntax
(?!pattern)
Meaning
Not followed by pattern
Width
Zero-width (peek only)
vs (?=...)
Positive: must follow
Whole-string ban
/^(?!.*bad).+$/
Not a quantifier
Assertion, not repetition
Standard
ES3+ (universal)
Try it
Live Preview
Run common negative-lookahead patterns and see what matches.
Browser demo of (?!...) — same idea as the examples below.
Result
/foo(?!bar)/.exec("foobaz")
→ "foo"
/* "baz" is not "bar" → lookahead passes */
Code
JavaScript Examples
Short, copy-ready snippets. Open DevTools Console, or use Try It Yourself for a live editor.
Example 1 — Match foo Not Followed by bar
Use (?!bar) to reject only the foobar case.
JavaScript
const words = ["foobar", "foobaz", "foo"];
for (const w of words) {
console.log(w, w.match(/foo(?!bar)/));
}
// foobar null
// foobaz ["foo"]
// foo ["foo"]
Add a filter.(?! dollars) rejects a number followed by that exact phrase.
Skip 5. After 5 comes dollars → assertion fails.
Keep 10. After 10 comes euros → assertion passes.
Edge Cases & Pitfalls
Check these before relying on negative lookahead.
result
Lookahead text is never captured
/foo(?!bar)/ returns "foo", never "foobaz". The peek is only a condition.
name
Not a quantifier
(?!...) does not repeat characters. For repetition use +, *, or ?.
placement
^(?!.*x) vs mid-pattern
At the start, ^(?!.*bad) bans a substring anywhere. Mid-pattern (?!bad) checks only what comes next at that position.
contrast
Need the opposite? Use (?=...)
Positive lookahead (?=...) requires the following text to match.
Compatibility
Browser & Runtime Support
Negative lookahead (?!...) is part of core JavaScript regular expression syntax (ES3+).
✓ Baseline · ES3+
RegExp (?!...) lookahead
Supported in every browser and Node.js version. No polyfill needed for negative lookahead assertions.
99%Universal syntax
Google ChromeSupported · Desktop & Mobile
Full support
Mozilla FirefoxSupported · Desktop & Mobile
Full support
Apple SafariSupported · macOS & iOS
Full support
Microsoft EdgeSupported · Chromium
Full support
Internet ExplorerNo native support · Use a polyfill
Polyfill
OperaSupported · Modern versions
Full support
Samsung InternetSupported · Android
Full support
BunSupported · JavaScript runtime
Supported
DenoSupported · JavaScript runtime
Supported
Node.jsSupported · Server runtime
Supported
Android WebViewSupported · Modern WebView
Full support
(?!...)Excellent
Bottom line: Safe everywhere. Use (?!...) when you must exclude specific following text without consuming it.
Analysis
Performance Notes
Approach
Cost
Best for
/token(?!bad)/
~match + peek
Local “not followed by” rules
/^(?!.*bad).+$/
Extra scan for .*bad
Whole-string exclusions
Nested lookaheads
Can grow
Keep short; test on real input
A simple peek is cheap. Whole-string rules like ^(?!.*forbidden) re-scan the input—fine for forms, avoid stacking many heavy lookaheads on huge strings.
Not repetition: it is an assertion, not a quantifier like +.
One line: use (?!...) when you need a match only if something specific does not come next.
Frequently Asked Questions
(?!...) is a negative lookahead assertion. It succeeds when the text immediately after the current position does NOT match the pattern inside. It is zero-width—it checks ahead without consuming characters.
No. (?!...) is an assertion (a condition on what follows). Quantifiers like +, *, and ? repeat or optionalize the previous token. Lookahead never includes the peeked text in the match result.
(?=...) is positive lookahead—it requires the following text to match. (?!...) is negative lookahead—it requires the following text NOT to match. Both are zero-width.
Yes. Write /foo(?!bar)/. In the constructor use new RegExp('foo(?!bar)'). Negative lookahead has been supported since ES3.
Use (?!...) when you want to match part of a string only if a specific suffix is absent—without including that suffix in the match. Alternation lists allowed forms; lookahead states a rule: match foo unless bar follows.
Negative lookahead is core JavaScript regex syntax since ES3. It works in every browser and Node.js version.