Regex Pattern for Phone Numbers

Phone number validation is notoriously difficult with regex because no single pattern can correctly validate every phone number format used globally. North American numbers follow NANP (North American Numbering Plan) with a predictable 10-digit structure, but even within that system users enter numbers in half a dozen different ways: (555) 123-4567, 555-123-4567, 555.123.4567, 5551234567, and +1-555-123-4567 are all the same number written differently. This example pattern uses optional groupings for each punctuation variant, allowing parentheses around the area code, spaces, dashes, or dots as separators, and an optional + prefix for international dialing code. The {4,6} quantifier on the last group accommodates European numbers where the subscriber number may be longer than four digits. The test cases demonstrate the key scenarios: an E.164 international format, the two most common US formats, the dot-separated format common in French-style notation, a variant with no separators (all digits run together), a missing digit (should fail), and a clearly non-numeric string (should fail). The critical professional advice for phone handling is to separate validation from normalization. A permissive regex that accepts any plausible-looking phone number is better for UX than a strict one that rejects valid numbers because of an unexpected format. After accepting the number, normalize it programmatically by stripping all non-digit characters and storing it in E.164 format (+15551234567). This makes comparison, SMS delivery, and display formatting straightforward. For international phone validation beyond North America, the complexity explodes: German numbers can have 3-11 digit subscriber numbers, Australian numbers look different from UK numbers, and many countries have special formatting rules for landlines vs mobiles. The libphonenumber library (available for JavaScript, Python, Java, and other languages) handles this correctly using Google's comprehensive database of phone number formats by country. Real-world scenario: a checkout form accepts phone numbers in any format the user is comfortable with, immediately strips all formatting, validates the digit count for the user's selected country code, stores in E.164, and displays it back in the user's locale-specific format — giving a polished experience without making users re-enter their number. Tips: if you're building a two-factor authentication system, use E.164 format for SMS delivery and always verify numbers with an actual SMS before relying on them for security-critical flows.

Example
/^[+]?[(]?[0-9]{3}[)]?[-s.]?[0-9]{3}[-s.]?[0-9]{4,6}$/

# Test cases:
+1 (555) 123-4567
555-123-4567
555.123.4567
5551234567
(555)123-4567
123
not-a-phone
[ open in Regex Tester → ]

FAQ

Should I normalize phone numbers before storing them?
Yes. Strip all non-digit characters and store in E.164 format (+15551234567). This makes comparison, formatting, and SMS delivery much easier.
How do I handle international phone numbers?
International formats vary widely by country. Consider using a library like libphonenumber instead of regex for production international phone validation.
Can I match extension numbers?
Add an optional group like (\s?(ext|x)\s?\d{1,4})? at the end of your pattern to capture common extension formats.

Related Examples