JavaScript Phone Number Formatting: A Comprehensive Guide

Mateen Kiani

Mateen Kiani

Published on Fri Jun 27 2025·4 min read

phone

Phone numbers power user sign-ups, contact forms, and two-factor auth flows in modern web apps. Yet many developers focus on display widgets and overlook the crucial step of normalization—stripping out spaces, dashes, and parentheses before processing. How do you ensure consistent formatting across your app and avoid validation headaches?

The answer lies in combining simple functions, regex patterns, and proven libraries to standardize numbers at input, before storage, and on display. Understanding these techniques will help you prevent user errors, streamline backend checks, and deliver a polished user experience.

Why Standardize Input

Before formatting, phone numbers must be normalized. Users paste numbers from different sources: “(123) 456-7890”, “123.456.7890”, or even “+1 123 456 7890”. Without stripping out non-digits, your validation logic may fail or store inconsistent data.

A good workflow:

  • Clean: Remove all characters except digits and leading “+”.
  • Validate: Check digit count for country rules (e.g., US is 10 digits plus optional country code).
  • Format: Apply a human-readable pattern (e.g., “(123) 456-7890”).

Standardization helps:

  • Prevent duplicates in your database.
  • Simplify comparisons and lookups.
  • Ensure consistent display across your app.

Formatting with Regular Expressions

One of the quickest ways to format phone numbers is with a regex replace. Here’s a simple US formatter:

function formatUS(number) {
// Remove all non-digit chars
const digits = number.replace(/\D/g, '');
// Apply (XXX) XXX-XXXX format
return digits.replace(/^(1)?(\d{3})(\d{3})(\d{4})$/, (m, country, a, b, c) => {
const prefix = country ? '+1 ' : '';
return `${prefix}(${a}) ${b}-${c}`;
});
}
console.log(formatUS('123-456-7890')); // (123) 456-7890

Key points:

  • Use replace(/\D/g, '') to strip non-digits.
  • Capturing groups help insert separators.
  • An optional country code can be prefixed.

Using Libraries like libphonenumber-js

For global support, roll your own regex isn’t enough. Google’s libphonenumber-js handles countless formats, country codes, and validation rules. It’s the de facto standard in many production apps.

Top options:

  1. libphonenumber-js – Lightweight, focused on formatting and validation.
  2. google-libphonenumber – Official port of Google’s library with full metadata.
  3. awesome-phonenumber – Simple wrapper around libphonenumber with extra utils.

Installation:

npm install libphonenumber-js

Basic usage:

import { parsePhoneNumberFromString } from 'libphonenumber-js';
const phone = parsePhoneNumberFromString('+1 213 373 4253');
console.log(phone.formatInternational()); // +1 213 373 4253
console.log(phone.formatNational()); // (213) 373-4253

Tip: You can auto-detect the user’s locale and format accordingly.

Real-time Formatting on Input

Users love seeing their number take shape as they type. Attach an input listener and reformat on each keystroke:

<input id="phone" type="tel" placeholder="Enter phone number" />
const input = document.getElementById('phone');
input.addEventListener('input', (e) => {
const { selectionStart } = e.target;
const raw = e.target.value.replace(/\D/g, '');
const formatted = raw
.replace(/(\d{3})(\d{1,3})?(\d{1,4})?/, (_, a, b, c) => {
let out = a;
if (b) out += `-${b}`;
if (c) out += `-${c}`;
return out;
});
e.target.value = formatted;
e.target.setSelectionRange(selectionStart, selectionStart);
});

Keep the cursor position by saving and restoring selectionStart. This creates a smooth typing experience.

Validating and Checking Length

After cleaning, ensure the digit count matches your region. For US numbers:

  • Exact length of 10 (without country code).
  • Or 11 with a leading “1”.
function isValidUS(number) {
const digits = number.replace(/\D/g, '');
return /^(1?\d{10})$/.test(digits);
}

Using tools like checking digit count can help you learn patterns for string/array length checks.

Bulletproof validation often combines regex, length checks, and library calls if you support international formats.

Advanced Formats: E.164

E.164 is the international standard for phone numbers. It guarantees global uniqueness and starts with “+” followed by country code and subscriber number, all as digits.

function formatE164(number) {
const digits = number.replace(/\D/g, '');
// Ensure leading '+' and country code
return '+' + digits;
}

Many APIs (Twilio, AWS SNS) require E.164 for sending SMS or calls.

Best Practices and Pitfalls

  • Always sanitize input before formatting.
  • Don’t rely on user-supplied country codes—detect or ask explicitly.
  • Keep formatting logic in one place (a utility module).
  • Test edge cases: extensions, short codes, vanity numbers.
  • Remember that UI formatting differs from stored format.

Proper formatting improves data integrity, user trust, and compliance with telephony providers.

Conclusion

Formatting phone numbers in JavaScript can be as simple as a regex replace or as powerful as a full-blown library. By normalizing input, validating digit counts, and choosing the right display pattern, you’ll reduce errors and streamline your data flow. Real-time formatting boosts user trust, while E.164 ensures seamless integration with global APIs. Start small with regex for your primary region, then adopt a library when you need worldwide support. Consistency is key: centralize your logic, write unit tests, and cover edge cases. Armed with these tips, you’re ready to make phone inputs rock-solid in your next project.



Mateen Kiani
Mateen Kiani
kiani.mateen012@gmail.com
I am a passionate Full stack developer with around 3 years of experience in MERN stack development and 1 year experience in blockchain application development. I have completed several projects in MERN stack, Nextjs and blockchain, including some NFT marketplaces. I have vast experience in Node js, Express, React and Redux.