(*ACCEPT) is a regex backtracking control verb. When the matching engine reaches it, the match succeeds immediately. Everything in the pattern after (*ACCEPT) is never processed: the engine stops, declares the match a success, and returns whatever has been consumed so far.
It is a niche feature, but a genuinely useful one once you understand it. This article covers exactly what (*ACCEPT) does, how it behaves inside capturing groups, which engines support it (the short answer: PCRE, and not much else), and the situations where reaching for it actually makes a pattern simpler.
What (*ACCEPT) does
A normal regex succeeds only when the engine runs off the end of the pattern with everything matched. (*ACCEPT) short-circuits that. It is an early exit.
Take this pattern:
foo(*ACCEPT)bar
Against the input foozzz, a normal foobar pattern would fail (no bar). But foo(*ACCEPT)bar matches foo and stops. The engine consumes foo, hits (*ACCEPT), and reports success right there. The bar after the verb is dead pattern: it is never even looked at.
That is the whole idea. (*ACCEPT) means "stop here, the match is good, do not process the rest."
The syntax
The verb is the literal text (*ACCEPT), written inline anywhere in the pattern. It takes no quantifier and matches no characters of its own (it is zero-width). In PCRE2 it can optionally carry a name, (*ACCEPT:NAME), which is passed back to the caller the same way a (*MARK:NAME) is. The name is informational; it does not change the matching behavior.
(*ACCEPT) is one of PCRE's backtracking control verbs, a family that also includes (*FAIL), (*SKIP), (*PRUNE), (*COMMIT), (*THEN), and (*MARK). They are covered briefly at the end of this article.
How it behaves inside capturing groups
This is the part worth understanding properly, because it is what makes (*ACCEPT) useful rather than just a curiosity.
When (*ACCEPT) is reached inside one or more capturing groups, those groups are closed as if they had matched normally, capturing whatever they had consumed up to that point. The capture is not discarded just because the group's closing parenthesis was never reached.
foo(bar(*ACCEPT)baz)qux
Against foobarXXX:
- The engine matches
foo, enters group 1, matchesbar, and hits(*ACCEPT). - The overall match succeeds and equals
foobar. - Group 1 is set to
bar, even though the engine never reached the group's). bazandquxare never processed.
So (*ACCEPT) does not throw away your captures. It commits whatever has been captured so far and exits cleanly. That is what lets you use it as a deliberate "the answer is good, take it now" signal in the middle of a complex pattern.
Where (*ACCEPT) is actually useful
The honest answer is that most patterns never need it. But there are a few recurring situations where it earns its place.
Early exit from one branch of an alternation
When a pattern has several alternative branches and matching any one of them means the whole match is complete, (*ACCEPT) lets a branch declare victory without you having to factor the "rest of the pattern" out of every branch.
^(?:cache-hit(*ACCEPT)|cache-miss|cache-stale)\s+\d+ms$
Here a line of cache-hit is considered a complete, valid match on its own. The other two branches still require the \s+\d+ms$ timing suffix. Without (*ACCEPT) you would either duplicate the suffix or restructure the alternation. The verb keeps the special-case branch self-contained.
Stopping a pattern once you have matched "enough"
If you only need to confirm that input starts a certain way and you do not care what follows, (*ACCEPT) ends the pattern as soon as the prefix is confirmed.
^https?://[^/\s]+(*ACCEPT)
This succeeds as soon as a scheme and host are present. The path, query, and fragment are irrelevant to the question being asked, so the pattern simply does not describe them.
Recursion and DEFINE blocks
In recursive patterns and (?(DEFINE)...) subroutine definitions, (*ACCEPT) is a common way to terminate a recursive descent once a base case is satisfied. That is an advanced use, but it is the place where (*ACCEPT) stops being optional and becomes the natural tool.
A caveat on the flip side: do not reach for (*ACCEPT) when an ordinary pattern would do. A clear foo is better than a clever foo(*ACCEPT). The verb is for the cases where the alternative is genuinely more tangled, not for showing off.
(*ACCEPT) is not the "exclude" idiom
People often arrive at (*ACCEPT) looking for the famous "match X but not Y" trick. That trick does not use (*ACCEPT). It uses (*SKIP)(*FAIL):
Y-to-ignore(*SKIP)(*FAIL)|X-to-keep
The pattern matches the thing you want to ignore, then (*SKIP)(*FAIL) deliberately fails it and tells the engine to jump past it, so the X-to-keep branch only ever sees the input you care about.
(*ACCEPT) is the opposite polarity: it forces success, not failure. Keep the two straight. (*ACCEPT) says "this is a match, stop." (*FAIL) says "this is not a match, backtrack."
Engine support
This is the catch. (*ACCEPT) is a PCRE feature, and it is not portable.
| Engine / language | (*ACCEPT) supported |
|---|---|
| PCRE and PCRE2 | Yes |
PHP (preg_match, preg_replace, etc.) | Yes (PHP uses PCRE) |
| Perl 5.10+ | Yes |
R (with perl = TRUE) | Yes |
Python, third-party regex module | Yes |
Python built-in re module | No |
JavaScript (RegExp) | No |
Java (java.util.regex) | No |
.NET (System.Text.RegularExpressions) | No |
Go (regexp, RE2) | No |
If your code runs on JavaScript, Python's standard re, Java, .NET, or Go, (*ACCEPT) is not available and will be a syntax error or a literal-text mismatch. In those environments you restructure the pattern, or you split the logic into two steps in the host language. Before using it, confirm your stack is on PCRE. The most common place it is safe is PHP.
The backtracking control verb family
(*ACCEPT) is one of seven. Here is the whole set, from the PCRE2 documentation, so you can see where it sits:
| Verb | Effect |
|---|---|
(*ACCEPT) | Force an immediate successful match. |
(*FAIL) or (*F) | Force a failure, triggering backtracking. |
(*MARK:NAME) | Set a named marker, passed back to the caller after the match. |
(*COMMIT) | On backtracking, fail the whole match with no further start positions tried. |
(*PRUNE) | On backtracking, fail and advance the start to the next character. |
(*SKIP) | On backtracking, fail and advance the start to the current matching position. |
(*THEN) | On backtracking, fail locally and move to the next alternative. |
(*ACCEPT) and (*FAIL) act immediately when reached. The other backtracking-triggered verbs only do something when the engine backtracks onto them. All of them can carry an optional :NAME; (*MARK) is the one that requires it.
Common mistakes
Expecting it to work in JavaScript or Python re. This is the big one. (*ACCEPT) is PCRE. A JavaScript RegExp treats (*ACCEPT) as an error or as literal characters, not as a control verb. Check the engine first.
Thinking it discards captures. It does not. Capturing groups open at the point (*ACCEPT) fires are closed and keep their captured text. If you wanted those captures empty, (*ACCEPT) is the wrong tool.
Using it where a plain pattern is clearer. (*ACCEPT) is an early exit, and early exits make patterns harder to read. Use it when it genuinely simplifies an alternation or a recursion, not by reflex.
Confusing it with (*SKIP)(*FAIL). (*ACCEPT) forces success. The exclude-this-text idiom forces failure. They are not interchangeable.
FAQ
See also
- Regex Cheat Sheet: the full syntax reference, including the PCRE features that surround the control verbs
- Regex Anchors: the other position-related constructs (
^,$, and word boundaries) that often appear alongside control verbs - Regex Lookaheads and Lookbehinds: zero-width assertions, the more portable way to express conditional matching
- Regex Capturing Groups and Backreferences: how capturing works, which matters because
(*ACCEPT)closes open groups when it fires - How to Use Regex in .htaccess: Apache
mod_rewriteruns on PCRE, so the control verbs are available there
External references: the PCRE2 pattern documentation is the authoritative source for the backtracking control verbs, with the syntax summary in pcre2syntax. Test patterns at regex101.com with the PCRE2 flavor selected, which is the easiest way to watch (*ACCEPT) short-circuit a match in the debugger.





