A practical guide to validating phone numbers the right way — when a quick regex is enough, when you need a real library, and how to get valid test data to check your logic against.
For a fast "does this look like a phone number" check — say, on a form field before submit — a regex is fine. The most useful one is E.164:
// E.164: + then 1-15 digits, first digit non-zero
const e164 = /^\+[1-9]\d{1,14}$/;
e164.test("+14155550132"); // true
e164.test("(415) 555-0132"); // false — not normalizedStrip formatting first so users can type naturally:
const digits = input.replace(/\D/g, ""); // keep digits only
const us = /^(\+?1)?[2-9]\d{2}[2-9]\d{6}$/; // loose US/NANP checkThe catch: regex only checks shape, not whether the number is real for its country (valid area codes, lengths, mobile vs landline). For anything user-facing, use a library.
Google's libphonenumber encodes every country's numbering rules and is ported to most languages. It is the industry standard.
import { parsePhoneNumberFromString } from "libphonenumber-js";
const p = parsePhoneNumberFromString("(415) 555-0132", "US");
p.isValid(); // true / false
p.number; // "+14155550132" (E.164)
p.country; // "US"
p.getType(); // "FIXED_LINE", "MOBILE", ...import phonenumbers
n = phonenumbers.parse("(415) 555-0132", "US")
phonenumbers.is_valid_number(n) # True / False
phonenumbers.format_number(n, phonenumbers.PhoneNumberFormat.E164) # "+14155550132"use libphonenumber\PhoneNumberUtil;
$util = PhoneNumberUtil::getInstance();
$num = $util->parse("(415) 555-0132", "US");
$util->isValidNumber($num); // true / false
$util->format($num, \libphonenumber\PhoneNumberFormat::E164); // "+14155550132"To unit-test a validator you need numbers that match each country's real format. Our tools generate exactly that:
Pull bulk valid-format numbers per country (E.164, national, plain) and feed them straight into your tests.