DevLab
.*
Regexadvanced

Lookahead & Lookbehind Guide

learn lookahead and lookbehind assertions with interactive examples

By Bikram NathLast updated

Zero-width assertions let a regex match a position without consuming characters. Feed (?<=\$)\d+(\.\d+)? to this tool and it highlights just the numeric part of $19.99, leaving the dollar sign outside the match -- something a plain capture group cannot do in one step. The color-coded visualization shows at a glance which assertion is gating or passing each position in the input.

Try it now — free, instant, no signup

What is Lookahead & Lookbehind Guide?

This tool lets you write and test all four assertion types -- positive lookahead (?=...), negative lookahead (?!...), positive lookbehind (?<=...), and negative lookbehind (?<!...) -- against live input. Enter hunter2A! with the pattern ^(?=.*[A-Z])(?=.*\d)(?=.*[!@#]).*$ and each assertion lights up a distinct color, making it immediately visible which sub-check passes or fails at a given cursor position.

Reach for this when you are learning the mechanics of zero-width assertions and want a focused environment. regex101 also supports all four types and adds a detailed sidebar breakdown with a community library of saved patterns, which is better for debugging a complex multi-assertion pattern that is already partially working. This tool's narrower scope makes it faster for experimentation when the assertions themselves are still unfamiliar.

Lookbehind support arrived in ECMAScript 2018. Chrome 62+, Edge 79+, and Node.js 8+ all ship it, but Safari only added support in version 16.4, released March 2023. JavaScript engines also reject variable-length lookbehinds: (?<=\d+) throws a SyntaxError in V8 and SpiderMonkey alike. Use a bounded quantifier such as (?<=\d{1,6}) as a workaround when porting patterns from Python or PCRE.

When to use Lookahead & Lookbehind Guide

Validate passwords requiring uppercase, a digit, and a symbol without capturing substrings by stacking multiple lookaheads from position zero.
Extract numeric prices from mixed-currency strings like '$29.99 or €49' using a lookbehind to strip the symbol before matching digits.
Debug why an existing lookahead fails silently by isolating each assertion and watching the color-coded match map update in real time.

Frequently Asked Questions

Why does (?<=\d+) throw a SyntaxError in JavaScript when the same pattern works in Python?
Python's re module has supported variable-length lookbehinds since version 2.4. JavaScript does not: the ECMAScript 2018 specification requires lookbehind patterns to have a fixed or bounded length, and V8, SpiderMonkey, and JavaScriptCore all enforce this at parse time. The workaround is to bound the repetition -- (?<=\d{1,10}) is valid in JavaScript. If the upper bound is genuinely unknown, restructure the pattern so the variable-length part moves into the main expression instead of the lookbehind. This tool runs in the browser, so it inherits that constraint directly.
Can I stack multiple lookaheads in one pattern, and does their order affect which strings match?
Yes, you can stack as many lookaheads as needed from the same anchor. ^(?=.*[A-Z])(?=.*\d)(?=.*[!@#]).{8,}$ runs three separate zero-width checks before consuming any characters. Order does not affect which strings match because each assertion resets to the same position. Order can affect performance: placing the most selective assertion first lets the engine short-circuit earlier when a string fails. In this tool's color display, each stacked assertion gets its own color band, so you can see exactly which sub-check is rejecting a given test string.
What is a zero-width assertion, and why does nothing from the lookahead appear in the match result?
A zero-width assertion checks a condition at the current position without advancing the cursor. Think of it as a gate the engine passes through rather than a tunnel it traverses. When (?=\d) succeeds at position 3, the engine stays at position 3 and continues the main pattern from there. Because no characters are consumed, nothing from the lookahead appears in match[0] or any numbered capture group. That is intentional -- it is what makes it possible to assert a condition while only capturing something else, such as confirming a currency symbol precedes digits without including that symbol in the result.
How do I write a negative lookbehind to match 'px' only when it is not preceded by a digit?
Use (?<!\d)px. The negative lookbehind succeeds at any position where the preceding character is not a digit, so 12px is rejected while margin-px matches. In this tool the failed-assertion color makes it easy to see exactly where the pattern refuses to match. If you need to exclude both digits and letters, chain two assertions: (?<!\d)(?<![a-z])px. Each lookbehind is evaluated independently and both must succeed for the overall position check to pass. Chaining is the standard approach because JavaScript does not support alternation inside a single lookbehind.
Does this tool show what text the lookbehind itself matched, or only whether the assertion passed?
It shows whether the assertion passed, not what it consumed, because lookaheads and lookbehinds consume no characters by definition. The color-coding distinguishes assertion type and pass/fail state at each position in the input. If you also need to capture the text that triggered a lookbehind, add a separate capturing group in the main expression alongside the assertion. For example, (\w+)(?=\s*=) captures a variable name and the lookahead confirms an equals sign follows, but the equals sign itself stays outside the capture group and outside the highlighted match span.

Related Tools