react-intl-tel-input, react-phone-input-2, and react-phone-number-input are React components designed to handle international phone number input in web forms. They provide country selection via flag dropdowns, automatic formatting as users type, and varying levels of validation. These libraries help developers collect correctly formatted phone numbers from users worldwide while improving UX through visual cues and real-time feedback.
When building forms that collect phone numbers from users around the world, you need more than a basic <input type="tel">. You need country-aware formatting, validation, and a clean UX. The three main React libraries for this — react-intl-tel-input, react-phone-input-2, and react-phone-number-input — each take a different approach. Let’s compare them in real-world terms.
react-intl-tel-input shows a flag dropdown next to the input. Users pick a country, and the input auto-formats as they type based on that country’s rules.
import IntlTelInput from 'react-intl-tel-input';
import 'react-intl-tel-input/dist/main.css';
function MyForm() {
return (
<IntlTelInput
preferredCountries={['us', 'gb']}
onPhoneNumberChange={(isValid, value, countryData) => {
console.log('Phone:', value, 'Valid:', isValid);
}}
/>
);
}
react-phone-input-2 also uses a flag dropdown but includes search functionality inside the dropdown. It updates the input with the selected country code and formats as you type.
import PhoneInput from 'react-phone-input-2';
import 'react-phone-input-2/lib/style.css';
function MyForm() {
const [phone, setPhone] = useState('');
return (
<PhoneInput
country={'us'}
value={phone}
onChange={setPhone}
enableSearch={true}
/>
);
}
react-phone-number-input (by catamphetamine) takes a minimalist approach. It renders a standard input with optional country selector, but focuses heavily on correctness using Google’s libphonenumber under the hood.
import { PhoneInput } from 'react-phone-number-input';
import 'react-phone-number-input/style.css';
function MyForm() {
const [value, setValue] = useState();
return (
<PhoneInput
placeholder="Enter phone number"
value={value}
onChange={setValue}
/>
);
}
react-intl-tel-input uses an older version of libphonenumber via intl-tel-input (its jQuery-based inspiration). It validates and formats based on the selected country, but doesn’t always handle ambiguous or incomplete numbers robustly.
react-phone-input-2 does not use libphonenumber. Instead, it relies on its own internal list of country codes and basic regex patterns. This means it can format numbers nicely but cannot validate them accurately — especially for countries with complex numbering plans.
// react-phone-input-2 gives you the raw string
// You must validate separately if you need accuracy
<PhoneInput
onChange={(value, country) => {
// value = "1234567890" (unformatted, no validation)
// country = { name: "United States", dialCode: "1", ... }
}}
/>
react-phone-number-input is built directly on top of Google’s libphonenumber (via libphonenumber-js). It parses, validates, and formats numbers according to official telecom standards. It returns E.164 formatted numbers by default, which are ideal for backend storage.
// react-phone-number-input gives you a validated, normalized number
<PhoneInput
onChange={(value) => {
// value = "+12133734253" (E.164 format, guaranteed valid if present)
}}
/>
// You can also check validity explicitly
import { isValidPhoneNumber } from 'react-phone-number-input';
console.log(isValidPhoneNumber('+12133734253')); // true
All three support customizing the list of countries, but with different APIs.
react-intl-tel-input uses preferredCountries and onlyCountries:
<IntlTelInput
onlyCountries={['us', 'ca', 'mx']}
preferredCountries={['us']}
/>
react-phone-input-2 uses onlyCountries and preferredCountries (same names, different format):
<PhoneInput
onlyCountries={['us', 'ca', 'mx']}
preferredCountries={['us']}
/>
react-phone-number-input uses the countryOptionsOrder and countries props, but more commonly you control availability via the defaultCountry and user input:
<PhoneInput
defaultCountry="US"
// To restrict countries, you'd need to pass a custom list
// See docs for advanced usage with countrySelectComponent
/>
Note: react-phone-number-input also supports disabling the country selector entirely if your app only serves one region.
react-intl-tel-input requires manual wiring because it doesn’t expose a standard value/onChange API. You’ll need to manage state carefully.
react-phone-input-2 works out of the box with most form libraries because it uses a familiar value/onChange pattern.
// With React Hook Form
const { register, setValue } = useForm();
<PhoneInput
{...register('phone')}
onChange={(value) => setValue('phone', value)}
/>
react-phone-number-input integrates cleanly because it behaves like a controlled input and returns standardized values:
// With React Hook Form
<Controller
name="phone"
control={control}
render={({ field }) => <PhoneInput {...field} />}
/>
As of 2024:
react-intl-tel-input is deprecated. Its npm page states: “This package is no longer maintained. Please use react-phone-number-input instead.” Do not use it in new projects.react-phone-input-2 is actively maintained and widely used, but lacks deep validation.react-phone-number-input is actively maintained, follows modern React practices, and is recommended by experts for correctness-critical applications.react-phone-number-inputlibphonenumber for true validation.react-phone-input-2react-intl-tel-input, plan a migration to react-phone-number-input.| Feature | react-intl-tel-input | react-phone-input-2 | react-phone-number-input |
|---|---|---|---|
| Maintenance Status | ❌ Deprecated | ✅ Active | ✅ Active |
| Validation Engine | Older libphonenumber | Custom regex (no validation) | Google’s libphonenumber |
| Output Format | Raw or formatted string | Raw international string | E.164 (standardized) |
| Form Library Friendly | ❌ Manual integration | ✅ Yes | ✅ Yes |
| Country Search | ❌ No | ✅ Yes | ✅ (via prop) |
| Recommended for New Apps | ❌ Never | ✅ For simple use cases | ✅ For validation-critical apps |
If you care about correctness — especially for features like two-factor authentication, SMS notifications, or user identity — use react-phone-number-input. It’s the only one that guarantees your phone numbers are valid and properly formatted according to global standards.
If you’re building a marketing contact form where perfect validation isn’t critical and you want something that looks good fast, react-phone-input-2 is a reasonable choice.
And never start a new project with react-intl-tel-input — its deprecation notice is clear, and better alternatives exist.
Do not use react-intl-tel-input in new projects — it is officially deprecated according to its npm page. If you encounter it in legacy code, plan a migration to a maintained alternative like react-phone-number-input. Its outdated dependencies and lack of active maintenance make it unsuitable for modern applications.
Choose react-phone-input-2 when you need a visually polished, easy-to-integrate phone input with country search and minimal setup. It’s well-suited for non-critical forms like contact pages where strict validation isn’t required. However, avoid it if you need guaranteed phone number correctness, as it lacks true validation based on telecom standards.
Choose react-phone-number-input when data accuracy and compliance matter — such as for SMS login, user verification, or any system requiring E.164-formatted numbers. It leverages Google’s libphonenumber for robust parsing and validation, integrates cleanly with modern React form libraries, and is actively maintained. It’s the best choice for production applications where phone number integrity is essential.
Rewrite International Telephone Input in React.js.
Due to the long commuting time, I do not have much time to maintain this project often. 😣
So if anybody else is willing to take on the work of bug fixes, integrating pull requests, etc, please let me know. 🙌
I hope we can maintain the project together, and make this project better! 💪
Live demo: patw0929.github.io/react-intl-tel-input
To build the examples locally, run:
yarn
yarn website:start
Then open localhost:3000 in a browser.
yarn add react-intl-tel-input
react-intl-tel-input ships with official type declarations out of the box.
import IntlTelInput from 'react-intl-tel-input';
import 'react-intl-tel-input/dist/main.css';
<IntlTelInput
containerClassName="intl-tel-input"
inputClassName="form-control"
/>
Please see the Demo Page
src and the build process)To build, watch and serve the examples (which will also watch the component source), run yarn website:start.
You can prepare a distribution build using yarn build.
Any kind of contribution including proposals, doc improvements, enhancements, bug fixes are always welcome.
To contribute to react-intl-tel-input, clone this repo locally and commit your code on a separate branch. Please write tests for your code, and run the linter before opening a pull-request:
yarn test # if you are enhancing the JavaScript modules
yarn test:ts # if you are enhancing the TypeScript type declarations
yarn lint
Also, please let us know if you encounter any issue by filing an issue.
International Telephone Input - @jackocnr
MIT
Copyright (c) 2015-2019 patw.