JavaScript RegExp (?!...) Negative Lookahead

Beginner
6 min read
Updated: Oct 2026
3 examples
Live preview

What Is (?!...)?

(?!...) 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)
UsePrefer
Match unless suffix/foo(?!bar)/
http but not https/http(?!s)/
Must follow instead(?=...)

How to Use (?!...)

Place the lookahead right after the text you want to keep.

  1. Write the part you want to match (e.g. foo or \d+).
  2. Add (?!forbidden) immediately after it.
  3. Call test, match, or replace — the forbidden text is checked but not captured.
  4. For whole-string bans, use ^(?!.*bad) at the start, then the rest of the pattern.
PieceRequired?Role
(?!…)YesAssert what must not follow
Text before itUsualWhat actually gets matched / returned
Inner patternYesThe 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

Cheat Sheet

Keep these lookahead facts handy.

TopicDetail
Syntax(?!pattern)
MeaningNot followed by pattern
WidthZero-width (peek only)
vs (?=...)Positive: must follow
Whole-string ban/^(?!.*bad).+$/
Not a quantifierAssertion, not repetition
StandardES3+ (universal)

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 */

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"]
Try It Yourself

How It Works

  1. Match the kept text. The engine first finds foo.
  2. Peek ahead. (?!bar) checks the next characters without consuming them.
  3. Reject foobar. When bar follows, the assertion fails → null.
  4. Allow the rest. foobaz and bare foo pass; the result is only "foo".

Example 2 — Match http but Not https

Exclude the secure scheme with a one-letter lookahead.

JavaScript
const urls = ["http://a.com", "https://a.com"];

for (const url of urls) {
  console.log(url, url.match(/http(?!s)/));
}
// http://a.com  ["http"]
// https://a.com null
Try It Yourself

How It Works

  1. Match http. Both URLs start with those four letters.
  2. Forbid s. (?!s) fails when the next character is s.
  3. https fails. After http comes s → no match.
  4. http succeeds. Next character is :, not s → "http".

Example 3 — Numbers Not Followed by dollars

Keep some numbers and skip others based on what follows.

JavaScript
const text = "5 dollars and 10 euros";

console.log(text.match(/\d+/g));              // ["5", "10"]
console.log(text.match(/\d+(?! dollars)/g));  // ["10"]
Try It Yourself

How It Works

  1. Plain digits. /\d+/g finds both 5 and 10.
  2. Add a filter. (?! dollars) rejects a number followed by that exact phrase.
  3. Skip 5. After 5 comes dollars → assertion fails.
  4. 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.

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 Chrome Supported · Desktop & Mobile
Full support
Mozilla Firefox Supported · Desktop & Mobile
Full support
Apple Safari Supported · macOS & iOS
Full support
Microsoft Edge Supported · Chromium
Full support
Internet Explorer No native support · Use a polyfill
Polyfill
Opera Supported · Modern versions
Full support
Samsung Internet Supported · Android
Full support
Bun Supported · JavaScript runtime
Supported
Deno Supported · JavaScript runtime
Supported
Node.js Supported · Server runtime
Supported
Android WebView Supported · Modern WebView
Full support
(?!...) Excellent

Bottom line: Safe everywhere. Use (?!...) when you must exclude specific following text without consuming it.

Performance Notes

ApproachCostBest for
/token(?!bad)/~match + peekLocal “not followed by” rules
/^(?!.*bad).+$/Extra scan for .*badWhole-string exclusions
Nested lookaheadsCan growKeep 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.

Key Takeaways

  • Role: (?!...) means “not followed by …”.
  • Zero-width: peeked text is not part of the match.
  • Opposite: (?=...) means “must be followed by …”.
  • 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.

Next: + quantifier

Learn how + matches one or more of the previous token.

+ quantifier tutorial →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

8 people found this page helpful