DEV Community

Amanda Jayathilaka
Amanda Jayathilaka

Posted on

Clean and Validate US Phone Numbers in JavaScript (and Catch Broken Data

Normalize messy phone numbers, flag invalid ones, and generate tel links with plain JavaScript.

Scraped or hand-entered phone data is messy. While building a directory of bank branches, I found numbers that were one digit short. Users would have tapped a tel: link and reached nothing.

Here is a small toolkit to prevent that.

Normalize

function normalizeUS(raw) {
  let digits = String(raw).replace(/\D/g, "");
  if (digits.length === 11 && digits.startsWith("1")) digits = digits.slice(1);
  return digits.length === 10 ? digits : null; // null = invalid
}

normalizeUS("(281) 646-6600");  // "2816466600"
normalizeUS("+1 281-646-6600"); // "2816466600"
normalizeUS("281-646-660");     // null  (only 9 digits)
Enter fullscreen mode Exit fullscreen mode

Format for display and links

function formatUS(digits) {
  return `${digits.slice(0, 3)}-${digits.slice(3, 6)}-${digits.slice(6)}`;
}

function telHref(digits) {
  return `tel:+1${digits}`;
}
Enter fullscreen mode Exit fullscreen mode

Audit a whole dataset

function auditPhones(rows) {
  return rows
    .map((r) => ({ ...r, clean: normalizeUS(r.phone) }))
    .filter((r) => r.clean === null);
}

const broken = auditPhones([
  { name: "Branch A", phone: "281-646-6600" },
  { name: "Branch B", phone: "972-690-860" },
]);
console.log(broken); // [{ name: "Branch B", ... }]
Enter fullscreen mode Exit fullscreen mode

Go further

For international support or strict validation, use libphonenumber-js:

import { parsePhoneNumberFromString } from "libphonenumber-js";

const p = parsePhoneNumberFromString("281-646-6600", "US");
console.log(p?.isValid(), p?.format("E.164"));
Enter fullscreen mode Exit fullscreen mode

Takeaways

  • Validate at import time, not at render time.
  • Store the clean digits and format on output.
  • Log invalid rows so you can fix the source.
  • A US number is exactly 10 digits after removing the country code.

Top comments (0)