Download Cheat sheet PDF 12 pages · syntax, editors, patterns, Unicode, performance, debugging
Patterns May 3, 2026

How to validate phone numbers with regex

A pattern that works for US numbers, why international is much harder, and when to reach for libphonenumber instead.

The short answer (US numbers)

^\+?1?[-.\s]?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}$

This accepts US phone numbers in common formats: with or without country code, with or without parentheses, with hyphens / dots / spaces / nothing as separators.

What it matches

  • 555-123-4567
  • (555) 123-4567
  • +1 555 123 4567
  • 555.123.4567
  • 5551234567
  • 1-555-123-4567

What it doesn't match

  • +44 20 7946 0958 — non-US
  • 555-1234 — missing area code
  • 555-123-456 — too short

For E.164 format

E.164 is the international standard: +, country code, then 7-15 digits with no separators.

^\+[1-9]\d{6,14}$

Why international validation is hard

The format of a valid phone number varies wildly by country:

  • US: 10 digits (without country code) — area code + exchange + subscriber
  • UK: varies by region; 020 7946 0958 for London, mobile starts with 07
  • Germany: variable length; area codes from 2 to 5 digits
  • India: 10 digits; mobile starts with 6-9
  • China: mobile is 11 digits; landline area codes vary

A single regex covering all of these would be enormous and still get things wrong. For international numbers, use Google's libphonenumber — it has language ports for almost everything (JavaScript, Python, Java, Go, Ruby, etc.).

Phone numbers are a normalization problem

Before validating, normalize. Strip whitespace and common separators:

JS:  const normalized = input.replace(/[\s\-().]/g, "");
Py:  normalized = re.sub(r"[\s\-().]", "", input)

Then check the normalized form against a simpler pattern:

^\+?1?\d{10}$

This is usually a better approach than trying to write one regex that handles every formatting variation.

Extension support

If you need to accept extensions:

^\+?1?[-.\s]?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}(\s*(ext|x|extension)\s*\d+)?$

The trailing group accepts x123, ext 4567, or extension 89.

What regex CAN'T check

  • Whether the number is currently in service
  • Whether it's mobile vs landline
  • Whether it's a real area code (regex would accept 000-000-0000)
  • Whether SMS verification can reach it

For these, use libphonenumber (which validates that the number could exist under the country's numbering plan) and follow up with an actual SMS or voice call to confirm.

For SMS-based verification flows

  1. Use libphonenumber to parse and validate format
  2. Check it's a mobile number (libphonenumber tells you)
  3. Normalize to E.164
  4. Send an SMS with a verification code
  5. Trust the number only after the code comes back

The takeaway

For US-only forms, the regex above is fine. For international, use libphonenumber. For anything that gates security (account creation, two-factor), the regex is just the first cheap filter — the SMS round-trip is what proves the number is real and reachable.


Related reading


Try this pattern in the explainer

Paste any regex into the live explainer and see what each token means, with example matches in real time.

Open the regex explainer →