Regex Lookahead and Lookbehind Explained — With Practical Examples

Lookahead and lookbehind are "zero-width assertions" — they check that a pattern exists before or after the current position without including it in the match. They are the tool that unlocks a huge category of regex problems, from password strength rules to inserting commas into large numbers. This guide breaks down all four variants with working examples.

The Four Assertion Types

  • Positive lookahead (?=...) — asserts that the pattern DOES follow, without consuming it
  • Negative lookahead (?!...) — asserts that the pattern does NOT follow
  • Positive lookbehind (?<=...) — asserts that the pattern DOES precede, without consuming it
  • Negative lookbehind (?<!...) — asserts that the pattern does NOT precede

Positive Lookahead — Password Requirements

The classic use case: requiring a password to contain a digit, a lowercase letter, an uppercase letter, and a special character — in any order, anywhere in the string.

const strongPassword = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*]).{8,}$/;

strongPassword.test('Passw0rd!');   // true
strongPassword.test('password');    // false — missing uppercase, digit, special char
strongPassword.test('PASSWORD1!');  // false — missing lowercase

Each (?=.*X) is checked from the same starting position — it peeks ahead for "any characters, then X" without moving the match pointer. That's why you can stack four of them and still only "consume" the final .{8,}.

Negative Lookahead — Excluding a Word

// Match "foo" only when NOT followed by "bar"
const notFooBar = /foo(?!bar)/g;

'foobar foobaz foo'.match(notFooBar);
// ['foo', 'foo']  — matches 'foobaz' and standalone 'foo', but not the 'foo' in 'foobar'

Positive Lookbehind — Currency Formatting

Lookbehind is perfect for inserting thousands separators into a number without consuming the digits it's checking against:

// Insert a comma every 3 digits from the right (Western/US grouping)
function formatNumber(num) {
  return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}

formatNumber(1234567);  // '1,234,567'

// Extract the amount after the ₹ symbol using lookbehind
const priceText = 'Total: ₹4599';
const amount = priceText.match(/(?<=₹)\d+/)[0];
console.log(amount);  // '4599'

The \B(?=(\d{3})+(?!\d)) pattern combines several ideas: \B avoids inserting a comma at the very start, the lookahead checks for groups of exactly 3 digits remaining, and the nested negative lookahead (?!\d) ensures we stop at the correct boundary.

Negative Lookbehind — Avoiding False Matches

// Match "$100" but not "US$100" (avoid matching when preceded by "US")
const notUsDollar = /(?<!US)\$\d+/g;

'Price: $100, US$100'.match(notUsDollar);
// ['$100']  — only the standalone $100, not the one preceded by "US"

When to Use Lookaround vs Capture Groups

  • Use a normal capture group when you need to extract or reuse the surrounding text
  • Use lookaround when you need to assert context exists but must NOT include it in the match (e.g. splitting text without losing the delimiter)
  • Lookaround assertions add processing overhead, especially nested ones — for very hot code paths (parsing large logs), benchmark against a simpler two-step approach (match, then filter)

Frequently Asked Questions

What is the difference between lookahead and lookbehind in regex?

Lookahead (?=...) checks what comes after the current position without consuming it, while lookbehind (?<=...) checks what comes before the current position without consuming it. Both let you match based on surrounding context without including that context in the final match.

What is a negative lookahead used for?

A negative lookahead (?!...) asserts that a pattern does NOT follow at the current position. It is commonly used in password validation to require multiple character types, e.g. requiring at least one digit anywhere without fixing its position.

Is lookbehind supported in all JavaScript environments?

Lookbehind is supported in all modern JavaScript engines (V8/Chrome/Node.js, and recent versions of Firefox and Safari) but was historically missing in older Safari versions. If you need to support very old browsers, avoid lookbehind or use a polyfill/alternative approach.

Try the Free AI Regex Generator

Describe any validation rule in plain English and get a working regex instantly — no signup required.

Related articles