Asterisk Dial Patterns: The Complete Guide
Asterisk Dial Patterns: The Complete Guide
Every exten => line in your dialplan starts with either a literal extension number or a pattern. When someone dials a number, Asterisk walks through the patterns in the current context and picks the one that matches. This is how call routing works. Get the patterns right and calls go where they should. Get them wrong and calls either fail or route to the wrong place silently.
On this page
What makes it a pattern
If the extension starts with an underscore (_), Asterisk treats the rest as a pattern with wildcards. Without the underscore, it's an exact literal match. This is the single most common mistake people make: they write NXXNXXXXXX without the underscore, and nothing ever matches because Asterisk is looking for someone to literally dial the letters N, X, X, N, X, X, X, X, X, X.
; Literal match: only fires when someone dials exactly 100
exten => 100,1,Answer()
; Pattern match: fires for any 3-digit number from 100 to 199
exten => _1XX,1,Answer()
; Pattern match: fires for any 3-digit number from 200 to 999
exten => _NXX,1,Answer()
Pattern characters
Each character in a pattern matches one dialed digit. The exceptions are . and !, which match variable-length sequences at the end.
| Character | Matches | Notes |
|---|---|---|
0-9 |
That exact digit | No underscore needed for all-literal patterns |
X |
Any digit 0 through 9 | The broadest single-digit wildcard |
Z |
Any digit 1 through 9 | Excludes zero. Useful for area codes that never start with 0 |
N |
Any digit 2 through 9 | Excludes 0 and 1. Standard for NANP area codes and exchanges |
[list] |
Any character in the set | [2-4] matches 2, 3, 4. [147] matches 1, 4, 7. Mix ranges and singles: [2-49] |
. (dot) |
One or more of anything | Greedy. Absorbs all remaining digits. Must match at least one. |
! (bang) |
Zero or more of anything | Like dot but matches even if no digits remain. Causes immediate match. |
* |
Literal asterisk | Used in star codes: _*XX matches 72, 73, etc. |
# |
Literal pound/hash | Less common. Used in some feature codes. |
Character classes support ranges and individual characters: [1-5] matches 1 through 5, [147] matches 1, 4, or 7, and [2-49] matches 2, 3, 4, or 9.
Specificity: which pattern wins?
When a dialed number matches more than one pattern in the same context, Asterisk picks the most specific one. It compares patterns character by character from left to right. At each position, the more restrictive match type wins.
The priority order, from most specific to least:
- Literal digit (matches exactly one value)
- Character class
[list](matches a defined set) - N (matches 2-9, eight possibilities)
- Z (matches 1-9, nine possibilities)
- X (matches 0-9, ten possibilities)
- Dot
.(matches one or more of anything) - Bang
!(matches zero or more of anything)
Example: overlapping NANP patterns
Consider a dialplan with these three patterns:
exten => _1NXXNXXXXXX,1,Dial(PJSIP/${EXTEN}) ; 11-digit NANP (specific)
exten => _1XXXXXXXXXX,1,Dial(PJSIP/${EXTEN}) ; 11 digits starting with 1 (broad)
exten => _1.,1,Dial(PJSIP/${EXTEN}) ; anything starting with 1 (catch-all)
When someone dials 18005551234, all three match. Asterisk picks _1NXXNXXXXXX because at position 2, N (matches 2-9) is more specific than X (matches 0-9). The catch-all _1. loses at position 2 where the dot is the least specific of all.
The dot vs the bang
These two wildcards look similar but behave differently:
-
_011.requires at least one digit after 011. It matches01144207946000but not011alone. Use this for international dialing where you always expect a country code and number after the prefix. -
_011!matches011by itself, plus anything longer. Asterisk also stops waiting for more digits immediately when the bang matches. This matters for overlap dialing: if a user dials011, Asterisk routes the call right away instead of waiting for a timeout to see if more digits are coming.
For international dialing, you almost always want the dot. The bang is more useful for things like _9! where you want to match both 9 (the outside line prefix) and 9 followed by more digits.
Real-world pattern sets
North American Numbering Plan (NANP)
exten => _1NXXNXXXXXX,1,Dial(PJSIP/trunk/${EXTEN}) ; 1 + 10-digit long distance
exten => _NXXNXXXXXX,1,Dial(PJSIP/trunk/1${EXTEN}) ; 10-digit (prepend 1)
exten => _NXXXXXX,1,Dial(PJSIP/trunk/1${DEFAULT_AREACODE}${EXTEN}) ; 7-digit local
The N at positions for the area code and exchange enforces that these positions are 2-9. Real NANP numbers never have 0 or 1 in those positions (0 and 1 are reserved for operator and long-distance prefixes). Using X instead of N would still work but could match invalid number formats.
DEFAULT_AREACODE is not a built-in Asterisk variable. Define it in your [globals] context before using it:
[globals]
DEFAULT_AREACODE=415
International dialing
exten => _011.,1,Dial(PJSIP/trunk/${EXTEN}) ; 011 + country code + number
exten => _00.,1,Dial(PJSIP/trunk/${EXTEN}) ; European style (00 prefix)
exten => _+.,1,Dial(PJSIP/trunk/${EXTEN}) ; E.164 format
International patterns use the dot wildcard because the total length varies by country. A UK number dialed from the US is 01144xxxxxxxxxx (15 digits) while a Canadian number is 011xxxxxxxxxx (13 digits).
Emergency and special numbers
; Emergency: always use exact match, never a pattern
exten => 911,1,Dial(PJSIP/trunk/911)
exten => 9911,1,Dial(PJSIP/trunk/911) ; 9 + 911 for outside-line systems
; Directory services
exten => 411,1,Dial(PJSIP/trunk/411)
exten => 311,1,Dial(PJSIP/trunk/311) ; non-emergency government
; Star codes
exten => *72,1,Goto(call-forward,activate,1) ; Call Forward All (implement in target context)
exten => _*XX,1,Goto(star-codes,${EXTEN},1) ; route all 2-digit star codes
Emergency numbers should always be exact matches (no underscore, no wildcards). An exact match has the highest possible specificity and can never be accidentally overridden by a broader pattern. If you have a catch-all like _X. in the same context, 911 as an exact match still wins.
Internal extensions
exten => _XXX,1,Dial(PJSIP/${EXTEN},30) ; 3-digit extensions (100-999)
exten => _XXXX,1,Dial(PJSIP/${EXTEN},30) ; 4-digit extensions (1000-9999)
exten => _[1-4]XX,1,Dial(PJSIP/${EXTEN},30) ; 3-digit, first digit 1-4 only
Be careful with short patterns. _XXX matches any three digits, including 911 and 411. You need to define emergency numbers as exact matches in the same context (they win on specificity), or route emergency calls through a separate context that's checked first via include.
Putting it all together
A typical office dialplan context:
[from-internal]
; Emergency (exact matches, highest priority)
exten => 911,1,Dial(PJSIP/trunk/911)
exten => 9911,1,Dial(PJSIP/trunk/911)
; Internal extensions
exten => _XXX,1,Dial(PJSIP/${EXTEN},30)
; Outside line (9 prefix)
exten => _9NXXNXXXXXX,1,Dial(PJSIP/trunk/${EXTEN:1}) ; 9 + 10-digit
exten => _91NXXNXXXXXX,1,Dial(PJSIP/trunk/${EXTEN:1}) ; 9 + 1 + 10-digit
exten => _9011.,1,Dial(PJSIP/trunk/${EXTEN:1}) ; 9 + international
; Star codes
exten => _*XX,1,Goto(star-codes,${EXTEN},1)
; Timeout and invalid handlers
exten => t,1,Playback(vm-goodbye)
exten => i,1,Playback(pbx-invalid)
The ${EXTEN:1} strips the leading 9 before sending the number to the trunk. This is a common pattern for systems that require dialing 9 for an outside line.
Digit timeouts and overlap dialing
When a user dials 911, Asterisk sees three digits. But _91NXXNXXXXXX also starts with 91. How does Asterisk know the user is done dialing?
Two mechanisms:
-
The
textension (response/digit timeout): If the user stops dialing and the inter-digit timeout fires with no complete match, Asterisk routes to thetextension in the current context. TheTextension (uppercase) is unrelated: it fires whenTIMEOUT(absolute)expires on an already-connected call. -
The digit timeout (
TIMEOUT(digit)): How long Asterisk waits between digits before deciding the user is done. Default is usually 5 seconds.
The exact match 911 helps here. When the user dials 9, 1, 1, Asterisk sees that 911 is an exact match. Since exact matches have higher priority than patterns, Asterisk routes the call immediately without waiting for more digits. This is why emergency numbers must be exact matches, not patterns.
For the _91NXXNXXXXXX pattern, Asterisk knows to wait for more digits because no exact match exists for 91 alone and the pattern requires more characters.
Common mistakes
Missing underscore. NXXNXXXXXX without _ looks for a literal extension called "NXXNXXXXXX". Nothing will ever match it. Always use _NXXNXXXXXX.
Overly broad catch-all. _X. matches everything two digits or longer. It acts as a safety net, but it also catches misdialed numbers, scanner probes, and anything else that hits your dialplan. If you use it, log what it catches so you know what's falling through.
Dot vs bang confusion. _011. requires at least one digit after 011. _011! matches 011 alone. For international dialing, you almost always want the dot.
Conflicting lengths. _NXX (3-digit) and _NXXNXXXXXX (10-digit) both start with N. After dialing 3 digits, Asterisk waits to see if more digits are coming. If the digit timeout is too short, 10-digit numbers get routed as 3-digit extensions. If it's too long, 3-digit extensions feel sluggish. Separating internal and external routing into different contexts (with include) avoids this.
Not testing. Pattern logic is easy to get wrong in your head. Test your patterns by watching the Asterisk verbose log (set verbose 5 in the CLI) while dialing, or use dialplan show <extension>@<context> to inspect what's loaded.
User Notes
Know a tip or gotcha for this topic? Share it below and help others.
Contribute a note
Share a tip, gotcha, or practical example. Keep it under 2000 characters. No questions (use the Asterisk community forums for support). Wrap code in backticks.