Skip to content
d.devtul.fun
中文
Regex · Phone

Phone Number Regex

A phone number validation pattern you can copy, plus the honest reason you should usually not validate phone numbers with regex at all.

The pattern

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

Matches an E.164 international number: a plus sign, a country code that does not start with 0, and up to 14 more digits. No spaces, parentheses, or dashes.

Test this pattern

Edit the text below — matching happens locally, nothing is uploaded.

Variants

Loose international with separators
^\+[1-9]\d{1,14}(?:[ \-.]?\d)*$

Tolerates spaces, hyphens, and dots between digit groups. More forgiving for human input, but it cannot tell a valid number from a well-formed fake.

North American (NANP) strict
^\(?([2-9]\d{2})\)?[-. ]?([2-9]\d{2})[-. ]?(\d{4})$

Constrains US/Canada/Caribbean numbers precisely. Useless outside NANP, which is exactly the trap: every region needs its own rule.

The one regex worth copying

If you only need to catch obvious garbage and you are willing to accept that "looks right" is not "is right", this is the pattern to use:

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

It implements the E.164 standard, the format every carrier and messaging provider ultimately stores. A number in this shape can be sent to an SMS gateway or a telephony API without further translation. Everything below explains why that is the easy 10% of the problem.

What the E.164 pattern actually matches

Read it left to right:

  • ^\+ — the string must begin with a single plus sign. That plus is the international prefix and is non-negotiable in E.164.
  • [1-9] — the first digit after the plus is the country code, and no country code starts with 0. Leading zeros belong to national dialing plans, not to E.164.
  • \d{1,14} — between one and fourteen more digits follow: the national destination code and subscriber number combined. The ITU caps the entire number at 15 digits including the country code.
  • $ — nothing else is allowed. No spaces, no dashes, no parentheses.

So +14155552671 passes and +0123456789 fails, correctly, because a country code cannot start with 0.

Why national formats refuse to agree

The moment you step away from E.164, the world fractures. The same seven digits mean completely different things depending on the country:

  • United States (NANP): a number is three digits of area code, three of exchange, four of subscriber. The area code and exchange each must start with 2–9; 212, 415, and 312 are real, while 012 or 114 are not.
  • United Kingdom: the area code length varies (London is 20, while many towns use 4 or 5 digits), and mobile numbers begin with 07. A single fixed-width regex cannot model this without becoming unreadable.
  • China: mobile numbers are exactly 11 digits starting with 1 followed by 3–9, while landlines embed variable-length area codes. 13912345678 is a mobile number; 01012345678 is a Beijing landline.

None of these rules is stable. Carriers retire and reassign ranges, new number blocks open, and country codes shift. A regex frozen in your codebase today is quietly wrong in eighteen months.

A precise North American (NANP) regex

If your product only serves the US, Canada, and a handful of Caribbean nations, the NANP rule is worth knowing:

^\(?([2-9]\d{2})\)?[-. ]?([2-9]\d{2})[-. ]?(\d{4})$

The critical detail is [2-9] at the start of both the area code and the exchange. The NANP prohibits 0 and 1 as the first digit of either block — 0 was reserved for operator and 1 for long-distance access. The optional \(? and \)? let callers write either (415) 555-2671 or 415-555-2671. This pattern is correct and tight, and that is precisely the danger: it is correct for one region and catastrophically wrong everywhere else.

Why you should not validate phone numbers with regex

This is the core point of the page. A regular expression checks shape, not validity. Google's libphonenumber library exists because shape-checking is the part that is easy and mostly pointless. The library carries the full, frequently updated metadata for every country: which number lengths are legal, which prefixes are assigned, how to normalize local formats into E.164, and how to detect a likely typo. When a country renumbers, you run a library upgrade instead of shipping a regex patch and hoping nobody noticed.

Use the library to parse and format. If you need to be certain a number is live, send a one-time code over SMS or a voice call — that is the only check that has ever meant anything.

What regex still gets wrong

  • Hardcoding a country code: writing ^\+1\d{10}$ locks you to the US and silently rejects every international user. E.164 with no leading country assumption is safer.
  • Banning separators: users type +44 20 8366 1177 with spaces. Strip non-digits before testing, or accept separators in the pattern, or you will reject valid input.
  • Eating the extension: business numbers often carry x1234 or ext. 1234. A narrow regex discards that part and your call never reaches the right desk.
  • Trusting the result: a perfect-shaped number can still be unassigned. Regex can never know that.

Format check versus real existence

Keep these two questions separate, because conflating them causes bugs:

  • "Is this string shaped like a phone number?" — regex or libphonenumber can answer this. It is cheap and useful for catching typos at form-submit time.
  • "Does this number belong to a real, reachable person?" — only a verification message answers this. No static pattern can, because assignment is a live fact owned by carriers.

Spend your effort on the second question through verification, and use a lightweight shape check only as a first gate.

Real examples: accepted and rejected

InputResultWhy
+14155552671AcceptedValid E.164, US number, 11 digits after +
+442083661177AcceptedValid E.164, UK number
+8613912345678AcceptedValid E.164, Chinese mobile
+0123456789RejectedCountry code cannot start with 0
14155552671RejectedMissing the required + prefix
+1415555RejectedToo few digits for any real NANP number

What to use instead

Hand the problem to a maintained library. In Python:

from phonenumbers import parse, is_valid_number

try:
    n = parse("+14155552671", None)
    if is_valid_number(n):
        print("looks real")
except Exception:
    print("not even a number")

In JavaScript, the libphonenumber-js package offers the same idea. Parse first, validate second, verify through a message third. Your regex is a doormat, not a bouncer.

Frequently asked

Is a regex enough for phone number validation?

No. A regex only checks shape. Use libphonenumber to validate and an SMS code to confirm the number is real.

What is the correct regex for E.164?

Use ^\+[1-9]\d{1,14}$ — a plus, a non-zero country code, and up to 14 more digits, with no separators.

Why does my phone regex reject valid international numbers?

You probably hardcoded a country code or banned spaces and dashes. Strip non-digits, then test against E.164.

Can a regex tell if a phone number is active?

Never. Only sending a verification code proves a number reaches a real person.

Related regex guides

Open the full Regex Tester