Developer

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.

By Makeinfo Team
#regex #phone #javascript #python #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

FormatRegexExample 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-2671
  • 1-415-555-2671
  • 415.555.2671
  • 4155552671

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:

InputExpectedNotes
+14155552671Valid E.164Standard US
+442071234567Valid E.164UK landline
+919876543210Valid E.164Indian mobile
+86 138 0013 8000Valid after cleaningChinese mobile
+1InvalidToo short
+0123456789InvalidCountry code starts with 0
+123456789012345678InvalidToo long (>15 digits)
(555) 123-4567Valid US (flexible)Common format
555.123.4567Valid US (flexible)Dot-separated
not-a-numberInvalidLetters only