Phone Number Regex Patterns for JavaScript, Python & Google Sheets
Copy-paste regex patterns for validating phone numbers in E.164, US, UK, Indian, and international formats across JavaScript, Python, and Google Sheets.
Finding the right regex for phone number validation is frustrating. Formats vary by country, users input numbers inconsistently, and most regex patterns you find online are either too strict or too loose.
This is a practical reference — copy-paste patterns that work, tested across JavaScript, Python, and Google Sheets.
Quick Reference Table
| Format | Regex | Example Match |
|---|---|---|
| E.164 (international) | ^\+[1-9]\d{6,14}$ | +14155552671 |
| US/Canada (NANP) | ^\+?1?[\s.-]?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}$ | (415) 555-2671 |
| UK | ^\+?44[\s]?\d{10}$ | +44 7911 123456 |
| India | ^\+?91[\s]?\d{10}$ | +91 9876543210 |
| Digits only (loose) | ^\d{7,15}$ | 4155552671 |
| With optional + prefix | ^\+?\d{7,15}$ | +4155552671 |
E.164 International Format
The E.164 standard (ITU-T recommendation) is the universal phone number format used by every major SMS API and telecom system.
Rules:
- Starts with
+ - Country code: 1–3 digits (first digit non-zero)
- Total length: 7–15 digits (not counting the
+) - No spaces, dashes, or parentheses
JavaScript
const e164Regex = /^\+[1-9]\d{6,14}$/;
// Test
e164Regex.test("+14155552671"); // true
e164Regex.test("+442071234567"); // true
e164Regex.test("+919876543210"); // true
e164Regex.test("14155552671"); // false (missing +)
e164Regex.test("+0123456789"); // false (country code starts with 0)
Python
import re
e164_pattern = re.compile(r'^\+[1-9]\d{6,14}$')
assert e164_pattern.match('+14155552671')
assert e164_pattern.match('+442071234567')
assert not e164_pattern.match('14155552671')
assert not e164_pattern.match('+123') # too short
Google Sheets
=REGEXMATCH(A2, "^\+[1-9]\d{6,14}$")
Returns TRUE or FALSE for each cell.
US/Canada (NANP) Numbers
The North American Numbering Plan covers the US, Canada, and Caribbean nations. Numbers are 10 digits: 3-digit area code + 7-digit subscriber number.
Strict (E.164 only)
^\+1\d{10}$
Matches: +14155552671
Flexible (multiple input formats)
^\+?1?[\s.\-]?\(?\d{3}\)?[\s.\-]?\d{3}[\s.\-]?\d{4}$
Matches:
+1 (415) 555-26711-415-555-2671415.555.26714155552671
JavaScript
const usFlexible = /^\+?1?[\s.\-]?\(?\d{3}\)?[\s.\-]?\d{3}[\s.\-]?\d{4}$/;
usFlexible.test("+1 (415) 555-2671"); // true
usFlexible.test("415-555-2671"); // true
usFlexible.test("4155552671"); // true
usFlexible.test("+1415555267"); // false (too short)
Python
us_pattern = re.compile(r'^\+?1?[\s.\-]?\(?\d{3}\)?[\s.\-]?\d{3}[\s.\-]?\d{4}$')
assert us_pattern.match('+1 (415) 555-2671')
assert us_pattern.match('415-555-2671')
Google Sheets
=REGEXMATCH(A2, "^\+?1?[\s\.\-]?\(?\d{3}\)?[\s\.\-]?\d{3}[\s\.\-]?\d{4}$")
UK Numbers
UK numbers use country code +44. Mobile numbers are 11 digits starting with 07, landlines vary by area.
Mobile Only
^\+?44[\s]?7\d{9}$
Matches: +44 7911 123456, 447911123456
All UK Numbers
^\+?44[\s]?\d{10}$
JavaScript
const ukMobile = /^\+?44[\s]?7\d{9}$/;
ukMobile.test("+44 7911 123456"); // true
ukMobile.test("447911123456"); // true
ukMobile.test("+44 2071234567"); // false (landline, not mobile)
Google Sheets
=REGEXMATCH(A2, "^\+?44[\s]?7\d{9}$")
Indian Numbers
Indian mobile numbers are 10 digits starting with 6, 7, 8, or 9. Country code is +91.
Regex
^\+?91[\s]?[6-9]\d{9}$
JavaScript
const indianMobile = /^\+?91[\s]?[6-9]\d{9}$/;
indianMobile.test("+91 9876543210"); // true
indianMobile.test("919876543210"); // true
indianMobile.test("+91 1234567890"); // false (starts with 1)
Google Sheets
=REGEXMATCH(A2, "^\+?91[\s]?[6-9]\d{9}$")
Multi-Country Validation
When your data contains numbers from multiple countries, use a cascading approach:
JavaScript
function validatePhone(phone) {
const cleaned = phone.replace(/[\s\-\(\)\.]/g, '');
const patterns = {
e164: /^\+[1-9]\d{6,14}$/,
us: /^\+?1?\d{10}$/,
uk: /^\+?44\d{10}$/,
india: /^\+?91[6-9]\d{9}$/,
generic: /^\+?\d{7,15}$/
};
for (const [format, regex] of Object.entries(patterns)) {
if (regex.test(cleaned)) {
return { valid: true, format, cleaned };
}
}
return { valid: false, format: null, cleaned };
}
console.log(validatePhone("+1 415-555-2671"));
// { valid: true, format: 'e164', cleaned: '+14155552671' }
Python
import re
def validate_phone(phone: str) -> dict:
cleaned = re.sub(r'[\s\-\(\)\.]', '', phone)
patterns = {
'e164': r'^\+[1-9]\d{6,14}$',
'us': r'^\+?1?\d{10}$',
'uk': r'^\+?44\d{10}$',
'india': r'^\+?91[6-9]\d{9}$',
'generic': r'^\+?\d{7,15}$',
}
for fmt, pattern in patterns.items():
if re.match(pattern, cleaned):
return {'valid': True, 'format': fmt, 'cleaned': cleaned}
return {'valid': False, 'format': None, 'cleaned': cleaned}
Google Sheets (Combined)
Use nested IFs to check multiple formats:
=IF(REGEXMATCH(A2,"^\+[1-9]\d{6,14}$"), "E.164",
IF(REGEXMATCH(A2,"^\+?1\d{10}$"), "US",
IF(REGEXMATCH(A2,"^\+?44\d{10}$"), "UK",
IF(REGEXMATCH(A2,"^\+?91[6-9]\d{9}$"), "India",
IF(REGEXMATCH(A2,"^\+?\d{7,15}$"), "Generic", "Invalid")))))
Cleaning Before Validation
Always normalize input before applying regex:
JavaScript
function cleanPhone(input) {
// Remove all whitespace, dashes, dots, parentheses
let cleaned = input.replace(/[\s\-\.\(\)]/g, '');
// Remove common prefixes
cleaned = cleaned.replace(/^(tel:|phone:|call:)/i, '');
return cleaned;
}
Python
def clean_phone(phone: str) -> str:
import re
cleaned = re.sub(r'[\s\-\.\(\)]', '', phone)
cleaned = re.sub(r'^(tel:|phone:|call:)', '', cleaned, flags=re.IGNORECASE)
return cleaned
Google Sheets
=REGEXREPLACE(REGEXREPLACE(A2, "[\s\-\.\(\)]", ""), "^(tel:|phone:|call:)", "")
Common Pitfalls
1. Forgetting to Escape Dashes in Character Classes
In [.\-()], the dash must be escaped or placed at the start/end: [-.()] or [.\-()].
2. Not Accounting for Leading Zeros
Some countries (like Italy +39) have numbers starting with 0 after the country code. The E.164 regex ^\+[1-9]\d{6,14}$ handles the country code correctly, but local formats may start with 0.
3. Being Too Strict
If your users paste numbers from different sources, a strict regex will reject valid numbers. Start with a loose pattern for acceptance, then normalize and validate with a strict pattern.
4. Google Sheets RE2 Limitations
Google Sheets uses RE2 regex engine, which doesn’t support:
- Lookaheads (
(?=...)) - Lookbehinds (
(?<=...)) - Backreferences (
\1)
Stick to basic patterns in Sheets formulas.
Testing Your Patterns
Before deploying, test against these edge cases:
| Input | Expected | Notes |
|---|---|---|
+14155552671 | Valid E.164 | Standard US |
+442071234567 | Valid E.164 | UK landline |
+919876543210 | Valid E.164 | Indian mobile |
+86 138 0013 8000 | Valid after cleaning | Chinese mobile |
+1 | Invalid | Too short |
+0123456789 | Invalid | Country code starts with 0 |
+123456789012345678 | Invalid | Too long (>15 digits) |
(555) 123-4567 | Valid US (flexible) | Common format |
555.123.4567 | Valid US (flexible) | Dot-separated |
not-a-number | Invalid | Letters only |
Related Tools
- E.164 Phone Number Validator — test numbers instantly
- Phone Number Formatter — bulk format to E.164
- Phone Number Validation in Google Sheets — full Sheets guide