Regex for a US phone number
^(?:\+?1[-. ]?)?\(?([2-9]\d{2})\)?[-. ]?([2-9]\d{2})[-. ]?(\d{4})$ accepts 10-digit US numbers written as 555-867-5309, (555) 867-5309, 555.867.5309 or +1 555 867 5309, and captures the area code, exchange and line number.
JavaScript ✓PCRE ✓
No catastrophic-backtracking patterns found. (A heuristic check: nested and adjacent repeats, overlapping alternatives.)
^Start of the stringanchor(?:…)Non-capturing group: groups without rememberinggroup\+The character '+' (escaped, so it is literal)literal?Repeat it optionally (zero or one time)quantifier1The character '1' literallyliteral[-. ]One character: '-', '.' or a spacecharacter class?Repeat the class optionally (zero or one time)quantifier?Then repeat the whole group optionally (zero or one time)quantifier\(The character '(' (escaped, so it is literal)literal?Repeat it optionally (zero or one time)quantifier(…)Capturing group #1: remembers what it matchedgroup[2-9]One character: '2' to '9'character class\dA digit (0-9)character type{2}Repeat it exactly 2 timesquantifier\)The character ')' (escaped, so it is literal)literal?Repeat it optionally (zero or one time)quantifier[-. ]One character: '-', '.' or a spacecharacter class?Repeat the class optionally (zero or one time)quantifier(…)Capturing group #2: remembers what it matchedgroup[2-9]One character: '2' to '9'character class\dA digit (0-9)character type{2}Repeat it exactly 2 timesquantifier[-. ]One character: '-', '.' or a spacecharacter class?Repeat the class optionally (zero or one time)quantifier(…)Capturing group #3: remembers what it matchedgroup\dA digit (0-9)character type{4}Repeat it exactly 4 timesquantifier$End of the stringanchor
3 capturing groups.
Examples
Checked at build time in JavaScript and in Python's re.
| Input | Matches? |
|---|---|
555-867-5309 | ✓ match |
(555) 867-5309 | ✓ match |
+1 555 867 5309 | ✓ match |
5558675309 | ✓ match |
155-867-5309 | ✗ no match |
555-067-5309 | ✗ no match |
867-5309 | ✗ no match |
555-867-5309 x12 | ✗ no match |
(555-867-5309 | ✓ match |
+44 20 7946 0958 | ✗ no match |
Try your own text
One string per line: each line is tested on its own (the m flag is added here).
How it works
Under the North American Numbering Plan, area codes and exchange codes both start with 2-9. A leading 0 or 1 is never valid there, because those digits were used for operator and long-distance dialing. That is why the pattern uses [2-9]\d{2} instead of \d{3}.
The best practice is to strip everything except digits first, then check the result. s.replace(/\D/g, "") turns every format into a plain digit string, which you can test with ^1?[2-9]\d{2}[2-9]\d{6}$ and store in one canonical form (E.164: +15558675309). Users then type the number however they like.
Variants
/^1?[2-9]\d{2}[2-9]\d{6}$/Test after stripping non-digits withs.replace(/\D/g, ""). Simpler and stricter./^\+[1-9]\d{1,14}$/E.164 shape for any country: a plus, then up to 15 digits. Checks format only.
Gotchas
- The parentheses are independently optional, so
(555-867-5309with one bracket passes. Normalizing to digits first avoids the issue. - Extensions like
x12orext. 12fail. Collect them in a separate field. - NANP covers Canada and several Caribbean countries too, so a match does not mean a US number.
- For international numbers, do not write a regex. Google's libphonenumber (ported to JavaScript as
libphonenumber-js) knows the length and prefix rules of every country.
Related explainers
- Regex for digits only, integers and decimalsRegexes for digits only, signed integers and decimal numbers, with the edge cases: leading zeros, a bare...
- Regex for a US ZIP codeA regex for 5-digit US ZIP codes and ZIP+4, why ZIP codes must be stored as strings, and what a format...
- Regex to trim leading and trailing whitespaceHow ^\s+|\s+$ with the g flag trims a string, why String.prototype.trim() is better, and the 2016 Stack...