Phone Number Regex — Validate and Extract Phone Numbers
Phone number regex patterns for validation and extraction. Covers US phone numbers, international E.164 format, extraction from text, and why regex alone isn't enough for...
Phone number regex is notoriously tricky — formats vary by country, carrier, and context. A regex can enforce basic structure, but production phone validation requires a library like libphonenumber.
Use the Email & URL Extractor to extract contact information from text.
US phone number regex
// Matches common US formats:
// (555) 123-4567 555-123-4567 555.123.4567 5551234567 +1 555 123 4567
const US_PHONE = /^(\+1\s?)?(\(?\d{3}\)?[\s.\-]?)(\d{3}[\s.\-]?\d{4})$/;
// Test:
['(555) 123-4567', '555-123-4567', '5551234567', '+1 555 123 4567'].forEach(p => {
console.log(p, US_PHONE.test(p));
});
// Extract digits only (for storage):
function normalizePhone(phone) {
const digits = phone.replace(/\D/g, '');
// US: strip leading 1 if 11 digits
if (digits.length === 11 && digits[0] === '1') return digits.slice(1);
return digits;
}
normalizePhone('(555) 123-4567') // '5551234567'
normalizePhone('+1-555-123-4567') // '5551234567'
E.164 international format
E.164 is the standard format for international phone numbers: + followed by country code and subscriber number, no spaces or dashes, max 15 digits.
// E.164 validation:
const E164_REGEX = /^\+[1-9]\d{1,14}$/;
E164_REGEX.test('+15551234567') // true (US)
E164_REGEX.test('+447911123456') // true (UK)
E164_REGEX.test('+33612345678') // true (France)
E164_REGEX.test('+1234') // true (could be valid, short number)
E164_REGEX.test('15551234567') // false (missing +)
E164_REGEX.test('+1555123456789012') // false (too long)
International phone extraction from text
const PHONE_PATTERNS = [
// E.164 international
/\+[1-9]\d{1,14}/g,
// US format
/(?:\+1[\s\-.]?)?\(?\d{3}\)?[\s\-.]?\d{3}[\s\-.]?\d{4}/g,
// UK: +44 7911 123456 or 07911 123456
/(?:\+44|0)[\s]?\d{4}[\s]?\d{6}/g,
];
function extractPhoneNumbers(text) {
const found = new Set();
for (const pattern of PHONE_PATTERNS) {
const matches = text.match(pattern) || [];
matches.forEach(m => found.add(m.trim()));
}
return [...found];
}
const text = 'Call us: (555) 123-4567 or +44 7911 123456 or +33612345678';
extractPhoneNumbers(text);
// ['(555) 123-4567', '+44 7911 123456', '+33612345678']
Python phone extraction
import re
# Broad pattern for extraction (then validate):
PHONE_PATTERN = re.compile(
r'(\+?[\d\s\-\.\(\)]{7,20})',
re.VERBOSE
)
# E.164 only:
E164_PATTERN = re.compile(r'\+[1-9]\d{1,14}\b')
def extract_phones(text: str) -> list[str]:
return E164_PATTERN.findall(text)
# For production: use phonenumbers library
import phonenumbers
def extract_phones_from_text(text: str, region='US') -> list[str]:
results = []
for match in phonenumbers.PhoneNumberMatcher(text, region):
formatted = phonenumbers.format_number(
match.number,
phonenumbers.PhoneNumberFormat.E164
)
results.append(formatted)
return results
text = "Call +1 555-123-4567 or (800) 555-0199 for support"
extract_phones_from_text(text)
# ['+15551234567', '+18005550199']
Why regex isn’t enough
// This passes regex but isn't a real number:
'+12345678901' // US: area code 234 doesn't exist
// Use google-libphonenumber for full validation:
import { PhoneNumberUtil } from 'google-libphonenumber';
const phoneUtil = PhoneNumberUtil.getInstance();
function isValidPhone(number, regionCode = 'US') {
try {
const parsed = phoneUtil.parseAndKeepRawInput(number, regionCode);
return phoneUtil.isValidNumber(parsed);
} catch {
return false;
}
}
isValidPhone('+15551234567') // false (555 is fictional)
isValidPhone('+16502530000') // true (Google's number)
// Format to E.164:
function toE164(number, region = 'US') {
try {
const parsed = phoneUtil.parseAndKeepRawInput(number, region);
return phoneUtil.format(parsed, PNF.E164);
} catch {
return null;
}
}
Input masking (UI)
// Apply US phone mask as user types:
function maskUSPhone(value) {
const digits = value.replace(/\D/g, '').slice(0, 10);
if (digits.length <= 3) return digits;
if (digits.length <= 6) return `(${digits.slice(0,3)}) ${digits.slice(3)}`;
return `(${digits.slice(0,3)}) ${digits.slice(3,6)}-${digits.slice(6)}`;
}
// Usage in React:
<input
value={phone}
onChange={e => setPhone(maskUSPhone(e.target.value))}
placeholder="(555) 123-4567"
type="tel"
/>
Related tools
- Email & URL Extractor — extract emails, URLs, and phone numbers
- Email Extractor Python — Python contact extraction
- Extract Emails from HTML — HTML contact scraping
Related posts
- Contact Information Extraction — Emails, Phones, and URLs from Text — Extract emails, phone numbers, URLs, and addresses from unstructured text using …
- Email Extractor — How to Pull Email Addresses from Text — An email extractor scans a block of text and finds all valid email addresses. He…
- Email Extractor — Extract Email Addresses from Text — An email extractor finds and pulls all email addresses from a block of text usin…
- Email Extractor in Python — regex, html.parser, and BeautifulSoup — Extract email addresses from plain text, HTML pages, and files using Python. Thi…
- Extract Emails from HTML — Parsing mailto Links and Text — Extract email addresses from HTML pages by scanning mailto: links, data attribut…
Related tool
Extract every email address and URL from a block of text. Regex-based, case-insensitive, deduplicated, sorted output.
Written by Mian Ali Khalid. Part of the Dev Productivity pillar.