What does (?:) mean in regex? Non-capturing groups explained
Parentheses do two things in regex. (?:...) turns off the second one.
The short answer
(?:...) creates a non-capturing group. It groups the contents together (so a quantifier or alternation applies to the whole group) but does NOT save what was matched.
Compare:
(abc)+ grouping + capture — saves "abc" in group 1
(?:abc)+ grouping only — no group saved
What parentheses do — the two jobs
Regular parentheses do two things at once:
- Group — they tell the engine "this is one unit" so quantifiers apply to the whole group.
- Capture — they save what was matched as a numbered group, accessible later.
You always want job 1. Job 2 is only useful if you actually plan to read the captured value back. Non-capturing groups (?:...) let you opt out of job 2.
When you NEED non-capturing groups
1. When you don't want the noise in your capture results
If you're extracting some specific values:
Pattern: ^(?:\w+ ){2}(\w+)$
Input: "Mary had a"
Captures: group 1 = "a"
The first group (?:\w+ ){2} is non-capturing — it groups so the {2} can repeat it, but doesn't pollute your capture list. The single capture group is (\w+), which gets a clean group-1 reference.
2. When alternation needs grouping
Bad: cat|dog food matches "cat" OR "dog food"
Good: (?:cat|dog) food matches "cat food" OR "dog food"
Without the group, the alternation extends to the whole pattern. The non-capturing group scopes it.
3. When you want to reuse a quantifier on a sub-pattern
(?:ab){3} matches "ababab"
(?:\d{3}-){2}\d{4} matches "123-456-7890
When non-capturing doesn't matter
If you don't care about captures and aren't referencing them, the difference between (abc) and (?:abc) is mostly stylistic. The non-capturing form:
- Skips the work of saving the matched text
- Makes intent clearer (you're telling the reader "I'm not capturing this")
- Keeps numbered groups in order if you add captures later
For one-off scripts, this might be over-engineering. For library code or shared patterns, prefer (?:...) when you don't need the capture.
Named groups instead
Modern regex flavors support named groups, which are clearer than numbered ones:
JavaScript / PCRE: (?<year>\d{4})
Python: (?P<year>\d{4})
Match.groups.year // JS
match.group("year") # Python
Named groups still count toward group numbering. If you mix named and unnamed:
(?<area>\d{3})-(\d{3})-(\d{4})
groups: area, 2, 3
Or use non-capturing for the parts you don't want, named for the ones you do.
Performance — does (?:) speed things up?
Slightly. Capturing has some overhead (saving the match positions). For simple patterns this is negligible. For very hot loops on huge inputs, the difference might be measurable, but you're unlikely to notice.
The real reason to use (?:...) is clarity and capture-list cleanliness, not performance.
The takeaway
Use (?:...) when you need to group but don't need to capture. It keeps your capture list clean, makes intent explicit, and avoids renumbering surprises if you later add new captures.
For values you DO want to extract, prefer named groups (?<name>...) — they're self-documenting and don't break when patterns are reorganized.
Related reading
Try this pattern in the explainer
Paste any regex into the live explainer and see what each token means, with example matches in real time.
Open the regex explainer →