npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@arctics/phonify

v1.2.0

Published

A utility library for phone number parsing and validation.

Readme

@arctics/phonify

license npm latest package npm downloads Checks Build CI install size npm bundle size Known Vulnerabilities

Table of Contents

  1. Introduction
  2. Features
  3. Installation
  4. Quick Start
  5. Usage
  6. Examples
  7. API Reference
  8. Advanced Features
  9. Contributing
  10. License

Introduction

@arctics/phonify is a comprehensive, lightweight TypeScript library for parsing, validating, and formatting international phone numbers. Built with extensive phone number metadata from 200+ territories, it provides accurate validation, type detection (mobile, fixed-line, toll-free, etc.), and intelligent formatting support for phone numbers in both national and international formats.

Whether you're building a communication platform, processing bulk phone data, or implementing real-time phone number formatting, Phonify gives you the tools to handle phone numbers with confidence.

Features

Comprehensive Coverage

  • Support for 200+ territories and country codes
  • Accurate validation based on regional phone number patterns
  • Automatic territory detection from international numbers

🎯 Type Detection

  • Identify phone number types: mobile, fixed-line, toll-free, premium rate, VoIP, and more
  • Region-specific pattern matching
  • Unknown type fallback for edge cases

📞 Smart Formatting

  • National and international (E.164) format support
  • Real-time "as-you-type" formatting with intelligent spacing
  • Automatic country code detection for international numbers
  • Tel URI generation for clickable phone links

🔍 Validation

  • Length validation (TOO_SHORT, TOO_LONG, VALID)
  • Pattern-based validation against country-specific rules
  • National prefix handling for complex cases (e.g., Argentina, Germany)
  • Support for incomplete numbers during typing

Developer-Friendly

  • Full TypeScript support with comprehensive types
  • Simple, intuitive API with zero configuration
  • No external dependencies
  • 88%+ code coverage with 68+ test cases

Installation

npm install @arctics/phonify

or

yarn add @arctics/phonify

Quick Start

import {
  parsePhoneNumber,
  isValidPhoneNumber,
  AsYouType,
} from '@arctics/phonify';

// Parse a phone number
const phone = parsePhoneNumber('+442070313000');
console.log(phone?.country); // 'GB'
console.log(phone?.number); // '+442070313000' (E.164)
console.log(phone?.getType()); // 'fixedLine'
console.log(phone?.isValid()); // true

// Quick validation
isValidPhoneNumber('2070313000', 'GB'); // true

// Format as-you-type
const formatter = new AsYouType('US');
formatter.input('2'); // '2'
formatter.input('0'); // '20'
formatter.input('1'); // '201'
formatter.input('5'); // '201 5'
formatter.input('5'); // '201 55'
formatter.input('5'); // '201 555'
formatter.input('0'); // '201 555 0'

Usage

Basic Parsing

import { PhoneNumber, parsePhoneNumber } from '@arctics/phonify';

// International format
const phone1 = PhoneNumber.parse('+12015550123');
// Result: PhoneNumber instance for USA with national number '2015550123'

// National format with country hint
const phone2 = PhoneNumber.parse('2070313000', 'GB');
// Result: PhoneNumber instance for UK

// With national prefix
const phone3 = PhoneNumber.parse('02070313000', 'GB');
// Automatically strips the '0' prefix, result valid for UK

// Legacy function style (still supported)
import { parsePhoneNumber } from '@arctics/phonify';
const phone4 = parsePhoneNumber('+12015550123');

Validation

import {
  isValidPhoneNumber,
  validatePhoneNumberLength,
} from '@arctics/phonify';

// Simple boolean validation
const isValid = isValidPhoneNumber('2015550123', 'US');
// Returns: true if matches country pattern, false otherwise

// Detailed length validation
const lengthResult = validatePhoneNumberLength('201', 'US');
// Returns: 'TOO_SHORT' if below minimum
// Returns: 'TOO_LONG' if exceeds maximum
// Returns: 'INVALID_COUNTRY' if country not found
// Returns: undefined if valid

Type Detection

import { parsePhoneNumber } from '@arctics/phonify';

const phone = parsePhoneNumber('+442070313000', 'GB');
const type = phone?.getType();
// Possible values:
// - 'fixedLine'
// - 'mobile'
// - 'tollFree'
// - 'premiumRate'
// - 'sharedCost'
// - 'voip'
// - 'personalNumber'
// - 'uan'
// - 'pager'
// - 'voicemail'
// - 'shortCode'
// - 'emergency'
// - 'UNKNOWN'

Formatting

import { parsePhoneNumber, PhoneNumberFormat } from '@arctics/phonify';

const phone = parsePhoneNumber('+442070313000');

// Unified Format API
console.log(phone?.format(PhoneNumberFormat.E164));           // '+442070313000'
console.log(phone?.format(PhoneNumberFormat.INTERNATIONAL));  // '+44 207 0313 000'
console.log(phone?.format(PhoneNumberFormat.NATIONAL));       // '207 0313 000'
console.log(phone?.format(PhoneNumberFormat.RFC3966));        // 'tel:+442070313000'

// Legacy methods (still supported)
console.log(phone?.number);               // '+442070313000'
console.log(phone?.formatNational());     // '207 0313 000'
console.log(phone?.formatInternational());// '+44 207 0313 000'
console.log(phone?.getURI());             // 'tel:+442070313000'

Extension Support

The library now supports parsing and formatting of phone number extensions.

Parsing

Extensions are automatically extracted from input strings using common delimiters (ext., x, #, ;ext=).

import { parsePhoneNumber } from '@arctics/phonify';

const phone = parsePhoneNumber('+1 (201) 555-0123 ext. 456');
console.log(phone?.extension); // '456'

Formatting

Extensions are included in formatted output where appropriate.

// International Format
console.log(phone?.formatInternational()); // '+1 201-555-0123 ext. 456'

// RFC3966 (URI)
console.log(phone?.getURI()); // 'tel:+12015550123;ext=456'

Real-Time Formatting with AsYouType

import { AsYouType } from '@arctics/phonify';

const formatter = new AsYouType('GB');

// Simulate user typing
formatter.input('2'); // '2'
formatter.input('0'); // '20'
formatter.input('7'); // '207'
formatter.input('0'); // '207 0'
formatter.input('3'); // '207 03'
formatter.input('1'); // '207 031'
formatter.input('3'); // '207 0313'

// Automatic country detection for international
formatter.reset();
formatter.input('+'); // '+'
formatter.input('4'); // '+4'
formatter.input('4'); // '+44 ' (detects UK)
formatter.input('2'); // '+44 2'
formatter.input('0'); // '+44 20'

Examples

Example 1: Contact Form Validation

import { parsePhoneNumber, isValidPhoneNumber } from '@arctics/phonify';

function validateContactForm(
  phone: string,
  country: string,
): {
  valid: boolean;
  error?: string;
  formatted?: string;
} {
  if (!phone || !country) {
    return { valid: false, error: 'Phone and country are required' };
  }

  if (!isValidPhoneNumber(phone, country)) {
    return { valid: false, error: 'Invalid phone number' };
  }

  const parsed = parsePhoneNumber(phone, country);
  return {
    valid: true,
    formatted: parsed?.number,
  };
}

// Usage
const result = validateContactForm('2070313000', 'GB');
console.log(result);
// { valid: true, formatted: '+442070313000' }

Example 2: Detecting Number Type for Routing

import { parsePhoneNumber } from '@arctics/phonify';

function routeCall(phoneNumber: string) {
  const parsed = parsePhoneNumber(phoneNumber);

  if (!parsed?.isValid()) {
    return { route: 'ERROR', reason: 'Invalid number' };
  }

  const type = parsed.getType();

  switch (type) {
    case 'mobile':
      return { route: 'MOBILE_NETWORK', number: parsed.number };
    case 'fixedLine':
      return { route: 'PSTN', number: parsed.number };
    case 'tollFree':
      return { route: 'TOLL_FREE_SERVICE', number: parsed.number };
    case 'voip':
      return { route: 'VOIP_PROVIDER', number: parsed.number };
    default:
      return { route: 'FALLBACK', number: parsed.number };
  }
}

// Usage
console.log(routeCall('+442070313000'));
// { route: 'PSTN', number: '+442070313000' }

Example 3: Input Masking with AsYouType

import { AsYouType } from '@arctics/phonify';

function createPhoneInput(countryCode: string) {
  const formatter = new AsYouType(countryCode);

  return {
    onInput: (event: any) => {
      const input = event.target.value;
      const formatted = formatter.input(input.slice(-1));

      // Update input display
      event.target.value = formatted;

      return formatted;
    },
    reset: () => {
      formatter.reset();
    },
  };
}

// Usage in React/Vue/etc
const usInput = createPhoneInput('US');
// User types: 2 -> 0 -> 1 -> 5 -> 5 -> 5 -> 0 -> 1 -> 2 -> 3
// Display updates: 2 -> 20 -> 201 -> 201 5 -> 201 55 -> 201 555 -> 201 555 0 -> ...

API Reference

Functions

parsePhoneNumber(input: string, country?: string): PhoneNumber | null

Parses a phone number string and returns a PhoneNumber instance or null if invalid.

Parameters:

  • input - Phone number string (can be international format with +, or national format)
  • country - Optional ISO 3166-1 alpha-2 country code for national format numbers

Returns: PhoneNumber instance or null if parsing fails

Examples:

parsePhoneNumber('+442070313000'); // International
parsePhoneNumber('2070313000', 'GB'); // National with country
parsePhoneNumber('02070313000', 'GB'); // National with prefix

isValidPhoneNumber(input: string, country: string): boolean

Quick validation check for a phone number.

Parameters:

  • input - Phone number string
  • country - ISO 3166-1 alpha-2 country code

Returns: true if valid, false otherwise

Examples:

isValidPhoneNumber('2070313000', 'GB'); // true
isValidPhoneNumber('invalid', 'GB'); // false

validatePhoneNumberLength(input: string, country: string): ValidationResult

Validates phone number length and returns detailed result.

Parameters:

  • input - Phone number string
  • country - ISO 3166-1 alpha-2 country code

Returns: 'TOO_SHORT' | 'TOO_LONG' | 'INVALID_COUNTRY' | undefined

Examples:

validatePhoneNumberLength('201', 'GB'); // 'TOO_SHORT'
validatePhoneNumberLength('2070313000', 'GB'); // undefined (valid)

Classes

PhoneNumber

Represents a parsed and validated phone number.

Properties:

  • nationalNumber: string - Phone number without country code
  • country: string - ISO 3166-1 alpha-2 country code
  • number: string - E.164 format (+CC + national number)

Methods:

isValid(): boolean

Validates the number against country-specific patterns.

getType(): PhoneType | 'UNKNOWN'

Determines the phone number type (mobile, fixedLine, etc.).

formatNational(): string

Formats the number in national format with optional prefix and spacing.

formatInternational(): string

Formats the number in international format with country code.

getURI(): string

Returns a tel: URI for clickable phone links.


AsYouType

Provides real-time formatting as users type phone numbers.

Constructor:

new AsYouType(countryCode: string)

Parameters:

  • countryCode - Default ISO 3166-1 alpha-2 country code for national format numbers

Static Methods

PhoneNumber.parse(number: string, region?: string): PhoneNumber | undefined

Parses a number string into a PhoneNumber object.

isPossibleNumber(): boolean

Lightweight check if the number length is possible for the region (faster than full regex validation).

isMobile(): boolean, isFixedLine(): boolean, etc.

Helper predicates for checking number type.

Methods:

input(text: string): string

Adds a character to the input and returns formatted result.

Parameters:

  • text - Single character or string to add

Returns: Formatted phone number string

reset(): void

Clears the current input state.

Examples:

const formatter = new AsYouType('US');
formatter.input('2'); // '2'
formatter.input('0'); // '20'
formatter.input('1'); // '201'
formatter.reset(); // State cleared
formatter.input('1'); // '1' (fresh start)

Advanced Features

National Prefix Handling

The library automatically handles national prefixes for different countries:

// UK: National prefix '0' is automatically removed
parsePhoneNumber('02070313000', 'GB');
// Equivalent to: parsePhoneNumber('2070313000', 'GB')

// Germany: Complex prefix rules handled automatically
parsePhoneNumber('0301234567', 'DE');
// National prefix removed during parsing

Country Code Detection

International numbers are automatically detected and routed to the correct country:

// Single digit country codes
parsePhoneNumber('+12015550123'); // USA (country code: 1)

// Two digit country codes
parsePhoneNumber('+442070313000'); // UK (country code: 44)

// Three digit country codes
parsePhoneNumber('+882123456789'); // Iridium (country code: 882)

Incomplete Number Support

The library supports incomplete numbers during real-time input:

const formatter = new AsYouType('US');
formatter.input('2'); // '2' - incomplete but accepted
formatter.input('0'); // '20' - still incomplete
// Later validation can check if number is complete

Contributing

Contributions are welcome! Please follow these steps:

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add some AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

License

This project is licensed under the MIT License.