(?:...): grouping without creating a capture
(?:...) groups part of a pattern for the purposes of quantifiers and alternation without recording what it matched, so it takes no group number and appears in no result.
At a glance
- Syntax
- (?:...)
- Captures
- nothing, and it takes no group number
- Use for
- applying a quantifier or an alternation to a sequence of tokens
- Backreferences
- cannot refer to it, there is nothing to refer to
- Replacement strings
- keeps $1 and $2 pointing at the same groups when you add grouping
- Cost
- marginally cheaper than a capturing group
In detail
The two brackets do the same grouping work. /(?:ab)+/ and /(ab)+/ match exactly the same text; the difference is that the second one also hands back the last ab it saw. If nothing is going to read that value, capturing it is pure overhead and, worse, it occupies a number.
That number is why this matters more than it first appears. Group numbers are positional, so wrapping something in parentheses halfway through a pattern shifts every later group up by one. Any $1 in a replacement string, any \1 backreference and any m[2] in the surrounding code now points somewhere else, and none of them raise an error about it.
The worked example below is the shape that bites. A date reformatter using $3/$2/$1 works correctly until someone wraps the month in an extra pair of parentheses for an unrelated reason. The pattern still matches, the replacement still runs, and the output is wrong in a way that looks plausible enough to ship.
The habit worth forming is simple: parentheses capture only when you intend to read the value. Everything else, particularly grouping around an alternation or before a quantifier, gets the non capturing form, and the pattern then survives being edited by someone who was not there when it was written.
Examples
"abab".match(/(?:ab)+/)[0]; // "abab"
"abab".match(/(ab)+/)[1]; // "ab", only the last iteration"2026-03-08".replace(/(\d{4})-(\d{2})-(\d{2})/, "$3/$2/$1");
// "08/03/2026"
// Someone wraps the month for an unrelated reason:
"2026-03-08".replace(/(\d{4})-((\d{2}))-(\d{2})/, "$3/$2/$1");
// "03/03/2026", silently wrongThe new group takes number three, so $3 now points at the month and the day has become group four.
Things that catch people out
- Adding a capturing group renumbers every group after it, and nothing warns you. The replacement string keeps working and starts producing wrong output.
- (?:...) cannot be the target of a backreference or of $1 in a replacement, so converting a group to non capturing breaks any reference that pointed at it.
- The colon is easy to lose when editing. (?...) on its own is a syntax error, but (?=...) and (?!...) are not, so a slip of the finger can turn a group into an assertion that matches nothing.
Try it: Regex Tester
Type a pattern and a test string, watch every match highlight as you go, read a plain English breakdown of each token, and check the numbered and named groups it captured.
Regex Tester
LOCAL · Browser-OnlyTest and debug regular expressions with live matching and highlights
Related Regex syntax
All regex syntax →(...) capturing groups: numbering and what comes back
How capture groups are numbered, what a group that did not participate returns, and why quantifying a group throws away everything but the last pass.
(?<name>...): named capture groups
Named groups survive being reordered, read as documentation and give you $<name> in replacements. They are still numbered underneath.
Alternation: precedence and ordered choice
The pipe has the lowest precedence of any regex operator and the branches are tried in order, so ^cat|dog$ and /a|ab/ both surprise people.
\1: backreferences that match what a group captured
A backreference matches the exact text a group captured, not the pattern that captured it. Inside a character class the same escape means something else.
\k<name>: backreferences to a named group
\k<name> repeats what a named group captured. Get the name wrong and, without the u flag, the escape quietly becomes a literal letter k.
(?=...): positive lookahead for zero width tests
A lookahead asserts what comes next without consuming it, which is how several independent rules can all be checked from the same position.
Tools for this
- Regex Tester Free online regex tester - test and debug regular expressions with live matching and highlights
- Regex Playground Regex playground with live match highlighting, named groups, find and replace, and shareable links