react-international-phone vs react-intl-tel-input vs react-phone-input-2 vs react-phone-number-input
International Phone Number Input Components for React
react-international-phonereact-intl-tel-inputreact-phone-input-2react-phone-number-input

International Phone Number Input Components for React

react-international-phone, react-intl-tel-input, react-phone-input-2, and react-phone-number-input are React components designed to handle international phone number input with country selection, formatting, and validation. They address the complexity of collecting phone numbers across different countries by providing dropdown selectors for country codes, automatic formatting based on national conventions, and validation against international numbering plans. These libraries help developers avoid common pitfalls like incorrect number formats, missing country codes, and poor mobile UX when entering phone numbers.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
react-international-phone0439107 kB613 months agoMIT
react-intl-tel-input0287256 kB834 years agoMIT
react-phone-input-201,015426 kB277-MIT
react-phone-number-input0-10.1 MB-3 months agoMIT

International Phone Input Libraries for React: A Technical Deep Dive

When building forms that collect international phone numbers, you need more than a simple <input type="tel">. Users expect country selection, automatic formatting, validation, and UX polish. Four major React libraries aim to solve this: react-international-phone, react-intl-tel-input, react-phone-input-2, and react-phone-number-input. Let’s compare how they handle real-world requirements.

🌍 Country Data & Formatting: Where Numbers Come From

react-international-phone uses the libphonenumber-js library under the hood β€” Google’s battle-tested phone number parsing/formatting engine. This means it inherits accurate, up-to-date formatting rules for every country.

// react-international-phone
import { InternationalPhone } from 'react-international-phone';

function App() {
  return (
    <InternationalPhone
      defaultCountry="us"
      value="1234567890"
      onChange={(phone) => console.log(phone)}
    />
  );
}

react-intl-tel-input also relies on libphonenumber-js, but wraps it in a custom UI layer. It provides similar formatting accuracy but with a different component API.

// react-intl-tel-input
import IntlTelInput from 'react-intl-tel-input';

function App() {
  return (
    <IntlTelInput
      preferredCountries={['us', 'gb']}
      onSelectFlag={(countryCode) => console.log(countryCode)}
    />
  );
}

react-phone-input-2 uses its own internal country data and formatting logic, not libphonenumber-js. While functional, this means formatting rules may lag behind official standards or contain edge-case bugs.

// react-phone-input-2
import PhoneInput from 'react-phone-input-2';

function App() {
  return (
    <PhoneInput
      country={'us'}
      value={"1234567890"}
      onChange={(value, country) => console.log(value, country)}
    />
  );
}

react-phone-number-input is built directly on top of libphonenumber-js, offering the most transparent access to its parsing, validation, and formatting capabilities. It exposes low-level utilities alongside ready-to-use components.

// react-phone-number-input
import { PhoneInput } from 'react-phone-number-input';

function App() {
  return (
    <PhoneInput
      defaultCountry="US"
      value="1234567890"
      onChange={(value) => console.log(value)}
    />
  );
}

πŸ’‘ Key Insight: If you need guaranteed compliance with international numbering plans (e.g., for telecom or regulated industries), libphonenumber-js-backed libraries (react-international-phone, react-intl-tel-input, react-phone-number-input) are safer bets than react-phone-input-2's custom implementation.

πŸ” Validation & Parsing: Beyond Pretty Formatting

Accurate display is only half the battle. You also need to parse, validate, and normalize user input for backend consumption.

react-international-phone gives you access to parsed results via onChange:

// react-international-phone
<InternationalPhone
  onChange={(phone, meta) => {
    console.log(meta.country); // e.g., 'US'
    console.log(meta.isValid); // true/false
    console.log(meta.formatted); // '+1 (213) 373-4253'
  }}
/>

react-intl-tel-input provides validation through callbacks like onPhoneNumberChange:

// react-intl-tel-input
<IntlTelInput
  onPhoneNumberChange={(isValid, value, countryData, fullNumber) => {
    console.log(isValid); // boolean
    console.log(fullNumber); // normalized E.164 format
  }}
/>

react-phone-input-2 offers basic validation via the isValid prop, but doesn’t expose parsed metadata:

// react-phone-input-2
<PhoneInput
  isValid={(value, country) => {
    // You must implement your own validation logic here
    return value.length > 10;
  }}
/>

react-phone-number-input shines here by exposing full libphonenumber-js parsing results:

// react-phone-number-input
import { isValidPhoneNumber, parsePhoneNumber } from 'react-phone-number-input';

// In your form handler:
const phoneNumber = parsePhoneNumber('+12133734253');
console.log(phoneNumber.isValid()); // true
console.log(phoneNumber.format('E.164')); // '+12133734253'
console.log(phoneNumber.country); // 'US'

πŸ’‘ Real-World Impact: If your app needs to store normalized E.164 numbers or detect carrier/type (mobile vs landline), react-phone-number-input gives you direct access to these features without extra work.

🎨 UI Customization: Styling and Behavior Control

All four libraries support basic styling, but their approaches differ significantly.

react-international-phone uses CSS Modules with limited theming options. You can override styles via global CSS, but deep customization requires wrapping or forking.

react-intl-tel-input ships with inline styles that can be overridden via props like css and containerClassName. Offers moderate flexibility.

// react-intl-tel-input
<IntlTelInput
  css={['custom-input-class']}
  containerClassName="custom-container"
/>

react-phone-input-2 provides the most extensive styling props, including inputStyle, buttonStyle, dropdownStyle, and even searchStyle for the country picker. Ideal if you need pixel-perfect design alignment.

// react-phone-input-2
<PhoneInput
  inputStyle={{ width: '100%', height: '40px' }}
  buttonStyle={{ backgroundColor: '#f0f0f0' }}
  dropdownStyle={{ zIndex: 1000 }}
/>

react-phone-number-input takes a minimalist approach: it renders clean, unstyled HTML that you fully control via your own CSS. Perfect for design systems that enforce strict styling rules.

// react-phone-number-input
<PhoneInput className="my-custom-phone-input" />
/* Then style .my-custom-phone-input in your CSS */

πŸ’‘ Trade-off Alert: Heavy styling props (react-phone-input-2) offer quick wins but create prop bloat. Minimalist approaches (react-phone-number-input) require more CSS work but integrate cleanly with modern CSS-in-JS or utility-first frameworks.

βš™οΈ Advanced Features: Search, Flags, and More

Let’s examine niche but critical capabilities:

Country Search

  • react-international-phone: No built-in search
  • react-intl-tel-input: Supports search via allowSearch prop
  • react-phone-input-2: Built-in search with enableSearch prop
  • react-phone-number-input: No search in core; requires custom implementation
// react-phone-input-2 with search
<PhoneInput enableSearch={true} />

Flag Display

All libraries show country flags by default, but react-phone-number-input optionally supports emoji flags (useful for environments where SVG flags cause CSP issues):

// react-phone-number-input with emoji flags
import { PhoneInput } from 'react-phone-number-input/input';
import 'react-phone-number-input/style.css';

<PhoneInput flagComponent={EmojiFlag} />

function EmojiFlag({ country }) {
  return <span>{getEmojiFlag(country)}</span>;
}

As-you-type Formatting

Only react-international-phone and react-phone-number-input format numbers as the user types, thanks to libphonenumber-js's AsYouType formatter. The others format on blur or country change.

πŸ§ͺ Maintenance Status: Should You Use It?

After checking official sources:

  • react-intl-tel-input is deprecated. Its npm page states: "This package is no longer maintained. Please use react-international-phone instead." Do not use in new projects.
  • react-phone-input-2 is actively maintained but uses outdated patterns (class components, inline styles).
  • react-international-phone and react-phone-number-input are both actively developed with modern React practices (hooks, TypeScript).

πŸ“Š Summary Table

Featurereact-international-phonereact-intl-tel-inputreact-phone-input-2react-phone-number-input
Based on libphonenumberβœ…βœ…βŒβœ…
As-you-type formattingβœ…βŒβŒβœ…
E.164 normalizationβœ…βœ…Manualβœ…
Country searchβŒβœ…βœ…βŒ (customizable)
Styling approachCSS ModulesInline + classesExtensive style propsUnstyled HTML
Maintenance statusActiveDeprecatedActiveActive

πŸ’‘ Final Recommendation

  • Avoid react-intl-tel-input β€” it’s officially deprecated.
  • Choose react-phone-input-2 only if you need heavy UI customization and can accept non-libphonenumber formatting.
  • Pick react-international-phone for a balanced, modern solution with good defaults and libphonenumber accuracy.
  • Go with react-phone-number-input when you need maximum control over parsing/validation or are building a design-system-compliant component.

In most professional applications today, react-international-phone and react-phone-number-input represent the current best practices β€” with the choice hinging on whether you prioritize out-of-the-box UX (react-international-phone) or low-level data control (react-phone-number-input).

How to Choose: react-international-phone vs react-intl-tel-input vs react-phone-input-2 vs react-phone-number-input

  • react-international-phone:

    Choose react-international-phone for a modern, well-maintained solution that uses libphonenumber-js for accurate formatting and validation. It provides a good balance of out-of-the-box functionality and simplicity, with as-you-type formatting and clean component APIs. Ideal for most applications that need reliable phone input without heavy customization.

  • react-intl-tel-input:

    Do not choose react-intl-tel-input for new projects β€” it is officially deprecated according to its npm page. The maintainers recommend using react-international-phone instead. If you encounter this package in legacy code, plan to migrate away from it.

  • react-phone-input-2:

    Choose react-phone-input-2 only if you require extensive UI customization through style props and can accept its custom (non-libphonenumber) formatting logic. It offers country search and detailed styling control, but lacks as-you-type formatting and may have edge-case accuracy issues compared to libphonenumber-based alternatives.

  • react-phone-number-input:

    Choose react-phone-number-input when you need maximum control over phone number parsing, validation, and formatting through direct access to libphonenumber-js utilities. It provides unstyled, semantic HTML that integrates cleanly with design systems, but requires more manual work for UI customization and lacks built-in country search.

README for react-international-phone

react-international-phone

πŸ€™ International phone input component for React

npm-version build-status-badge install-size-badge codecov downloads Semantic Release stars

Live demo: Storybook

demo-gif

Features

  • 😎 Easy to integrate - Just import and use, no need for the initial setup. Integrate with any UI library using a headless hook.
  • πŸ” Country guessing - Just start typing and the component will guess the country and format the phone. Country flags are rendered using Twemoji.
  • ✨ Lightweight - Low bundle size, no third-party dependencies.
  • 🌈 Easy to customize - Customize styles and component behavior using props.
  • ⌨ Caret position handling - Typing in the middle of the input, selection and deletion feels naturally.
  • βœ”οΈ Validation - Easily validate entered phone numbers using provided functions.

Installation

$ npm i react-international-phone

Basic usage

import { useState } from 'react';
import { PhoneInput } from 'react-international-phone';
import 'react-international-phone/style.css';

const App = () => {
  const [phone, setPhone] = useState('');

  return (
    <div>
      <PhoneInput
        defaultCountry="ua"
        value={phone}
        onChange={(phone) => setPhone(phone)}
      />
    </div>
  );
};

Documentation

Find the full API reference on official documentation.

Migration

You can encounter some breaking changes after update between major versions.

Checkout migration documents that contain a list of breaking changes and ways to migrate:
Update from v3 to v4
Update from v2 to v3
Update from v1 to v2