Stop Using Bad Regex for Phone Validation: A Guide to E.164
As developers, we've all been there. You need to validate a phone number field, so you Google "phone number regex" and copy the first StackOverflow answer with 500 upvotes from 2012. It looks something like this:
Big mistake. That regex was written for a specific use case (US domestic numbers in a particular format) and has been blindly copied millions of times since. Let's explore why this approach fails and what you should do instead.
The Problem with Simple Regex
Most basic regex patterns assume US-centric formats like (555) 123-4567. They fail spectacularly when users enter:
- UK numbers with spaces:
+44 7700 900000 - Numbers with dots:
555.123.4567 - Chinese mobile numbers:
+8613912345678 - Australian numbers:
+61 491 570 006 - Numbers with country codes but no +:
001 555 123 4567
The fundamental issue is that phone number formats vary dramatically across 200+ countries and territories. A regex that works for US numbers will reject valid UK numbers. A pattern that accepts UK numbers might incorrectly validate gibberish for Chinese numbers.
Why StackOverflow Answers Are Dangerous
The most upvoted phone validation regex on StackOverflow has been viewed over 3 million times. Here's why it's problematic:
- Outdated: The answer was written in 2009. Phone number formats and country codes have changed significantly since then.
- Context-free: The original question was about validating US numbers only, but the answer gets applied globally.
- No maintenance: Unlike a library, a StackOverflow answer doesn't get security patches or updates when numbering plans change.
- False confidence: High upvotes make developers trust it blindly without understanding its limitations.
Real-world impact: A major e-commerce platform lost an estimated $2.3M in sales over 6 months because their checkout form rejected valid international phone numbers. The culprit? A 10-year-old regex copied from StackOverflow.
Enter E.164: The Gold Standard
E.164 is the international standard for public telecommunication numbering plans, defined by the ITU-T (International Telecommunication Union). The format is elegantly simple:
Example: +14155550100
Key characteristics of E.164:
- Maximum 15 digits (including country code)
- No spaces, dashes, or parentheses when stored
- Always starts with + followed by the country code
- Universally parseable by any telecom system worldwide
This is why our DevDataPhone Generator defaults to E.164 format—it's the format that APIs like Twilio, AWS SNS, and Firebase expect.
Country-Specific Complexity
To understand why simple regex fails, consider these real-world formatting rules:
United States (+1)
US numbers follow the NANP (North American Numbering Plan). Area codes cannot start with 0 or 1, and the exchange code (next 3 digits) also cannot start with 0 or 1. A proper US regex needs to account for these rules—most StackOverflow answers don't.
United Kingdom (+44)
UK numbers vary in length from 9 to 10 digits after the country code. Mobile numbers start with 7, London landlines start with 20, and other geographic codes vary by region. A single regex cannot handle all valid UK formats correctly.
China (+86)
Chinese mobile numbers are exactly 11 digits and start with specific prefixes (13x, 14x, 15x, 17x, 18x, 19x). Landlines vary by city. The complexity is immense—China Mobile, China Unicom, and China Telecom each have their own prefix ranges.
Germany (+49)
German phone numbers can range from 7 to 12 digits after the country code, depending on whether it's a landline, mobile, or special service number. There's no fixed length.
The Solution: A Two-Layer Approach
Instead of trying to build one regex to rule them all, implement validation in two layers:
Layer 1: Permissive Frontend Validation
Allow users to input numbers in whatever format they're comfortable with. Your frontend regex should only check for basic sanity:
This accepts any reasonable phone-like input without rejecting valid international formats.
Layer 2: Strict Backend Parsing
On the server side, use a battle-tested library like libphonenumber (Google's phone number parsing library) or its JavaScript port libphonenumber-js. These libraries:
- Understand numbering plans for 200+ countries
- Can parse numbers in any common format
- Validate that the number could theoretically exist
- Convert to E.164 for storage
- Are maintained by Google and updated regularly
Implementation Best Practices
- Allow loose input: Let users type spaces, dashes, parentheses—whatever they're used to.
- Strip non-digits: Before processing, remove everything except digits and the leading + sign.
- Use a library: Validate with
libphonenumber-jsor our regex patterns from the Regex section. - Store in E.164: Always save the normalized E.164 format to your database.
- Display locally: When showing numbers to users, format them according to their locale.
Testing Your Validation
Before deploying phone validation, test it with numbers from multiple countries. Use our DevDataPhone Generator to create valid test numbers for US, UK, China, Australia, and India. This ensures your validation logic handles international formats correctly without risking accidental messages to real users.
Remember: a validation regex that rejects valid customers is worse than no validation at all. When in doubt, be permissive on input and strict on storage format.
Check out our Regex section to get compliant patterns for the US, UK, China, and more—all tested against real-world numbering plan data.