DEV Community

Stop using regex for phone validation - use this instead

The Problem with Regex for Phone Validation

A regex for "valid phone number" is a trap. International phone numbering isn't regular: number length, valid area codes, and mobile-vs-landline prefixes differ per country and change over time as ranges get reassigned. A regex that's correct today starts silently misclassifying numbers months later, and you won't notice until a support ticket comes in.

The Solution: Use libphonenumber

The actual fix is using the numbering-plan data Google publishes and maintains for Android/Chrome: libphonenumber, or its much smaller JS port libphonenumber-js.

import { parsePhoneNumberFromString } from "libphonenumber-js";

const phone = parsePhoneNumberFromString("+49 30 1234567");
phone?.isValid(); // true - checks length + pattern for that country
phone?.country; // "DE"
phone?.getType(); // "FIXED_LINE" | "MOBILE" | undefined (not always determinable)
phone?.formatInternational(); // "+49 30 1234567", normalized

What Regex Can't Give You

Two things regex can't give you that this does for free:

  • Country-aware validity. "Valid length" isn't one number - it varies by country and sometimes by number type within a country. The library knows the real ranges, and gets updated when they change.
  • Normalization. Users type phone numbers a dozen different ways (spaces, dashes, parens, with or without country code). formatInternational() gives you one canonical form to store and compare against, instead of writing your own normalization pass.

One Gotcha

Without a country hint, a local-format number is ambiguous. 030 1234567 is valid in Germany and might also just be a truncated something-else from another country. If your form is scoped to one country, pass it as the default country rather than relying purely on a + prefix being present.

For Non-JS Backends

If your backend isn't JS (or you don't want the dependency in a small service), I wrapped libphonenumber-js as a hosted endpoint on Validate - same validation logic, plain JSON in and out.

Comments

No comments yet. Start the discussion.