intl-tel-input: International Telephone Input
The `intl-tel-input` library is a robust JavaScript plugin designed for entering, formatting, and validating international telephone numbers. Currently at version 27.0.11, it maintains an active release cadence with frequent bug fixes and feature enhancements, including recent updates for React, Vue, and Svelte components, and fixes for TypeScript type resolution. Key differentiators include automatic country detection via IP lookup, placeholder examples for selected countries, keyboard navigation for the country dropdown, real-time number formatting, and comprehensive validation powered by Google's libphonenumber library. It provides high-resolution flag images, includes TypeScript definitions, and supports extensive customization through options, methods, events, and CSS variables for theming.
Common errors
-
TypeError: iti.isValidNumber is not a function
cause The `utils.js` script, which provides number validation and formatting functions, has not been loaded or has not finished loading before `isValidNumber()` was called.fixCall `intlTelInputInstance.loadUtils('/path/to/utils.js')` and ensure its promise resolves before invoking validation methods. For example: `iti.loadUtils('...').then(() => { if (iti.isValidNumber()) { ... } })`. -
ReferenceError: intlTelInput is not defined
cause The main `intl-tel-input` JavaScript library has not been correctly imported or included in your project.fixFor modern JavaScript modules, use `import intlTelInput from 'intl-tel-input';`. For CommonJS, use `const intlTelInput = require('intl-tel-input');`. For global usage, ensure the script tag for `intl-tel-input.min.js` is present in your HTML before your custom script. -
Failed to compile. Module not found: Error: Can't resolve 'intl-tel-input/styles'
cause The module path for importing the library's CSS styles is incorrect or your bundler configuration is not set up to handle it.fixEnsure you are using `import 'intl-tel-input/styles';` (recommended since v27.0.8). If this still fails or you're on an older version, try `import 'intl-tel-input/build/css/intlTelInput.css';`.
Warnings
- breaking For React, Vue, Angular, and Svelte components, plugin options are now passed as individual props directly to the component instead of being nested within an `initOptions` object.
- breaking The structure of the data returned by `getSelectedCountryData()` and within the `countrychange` event has been simplified, exposing only `name`, `iso2`, and `dialCode` properties.
- gotcha The full validation and formatting features (e.g., `isValidNumber()`, `getNumber()`, `getNumberType()`) rely on a separate `utils.js` script (powered by Google's libphonenumber). This script must be explicitly loaded via `intlTelInput.loadUtils(path)` after the main plugin is initialized.
- gotcha Older versions (prior to v27.0.8) might experience issues with the dropdown separating from the input when placed inside `display: flex` or `display: grid` containers, or incorrect dropdown width when `enableSeparateDialCode` is true.
Install
-
npm install intl-tel-input -
yarn add intl-tel-input -
pnpm add intl-tel-input
Imports
- intlTelInput
const intlTelInput = require('intl-tel-input');import intlTelInput from 'intl-tel-input';
- IntlTelInputOptions
import type { IntlTelInputOptions } from 'intl-tel-input'; - CountryData
import type { CountryData } from 'intl-tel-input';
Quickstart
import intlTelInput from 'intl-tel-input';
import 'intl-tel-input/styles'; // Import default styles
document.addEventListener('DOMContentLoaded', () => {
const inputElement = document.getElementById('phone-input') as HTMLInputElement | null;
if (inputElement) {
const iti = intlTelInput(inputElement, {
initialCountry: 'us',
separateDialCode: true,
preferredCountries: ['us', 'gb', 'ca'],
// `utilsScript` is crucial for validation and formatting functions
// It can be served locally or via a CDN.
utilsScript: 'https://cdn.jsdelivr.net/npm/intl-tel-input@27.0.11/build/js/utils.js',
});
inputElement.addEventListener('countrychange', () => {
const selectedCountryData = iti.getSelectedCountryData();
console.log('Country changed:', selectedCountryData);
});
document.getElementById('validate-btn')?.addEventListener('click', () => {
if (iti.isValidNumber()) {
console.log('Valid number:', iti.getNumber());
alert(`Valid number: ${iti.getNumber()}`);
} else {
const errorCode = iti.getValidationError();
console.log('Invalid number (error code):', errorCode);
alert(`Invalid number. Error code: ${errorCode}`);
}
});
console.log('intl-tel-input initialized and ready.', iti);
}
});
/*
Minimal HTML to run this code:
<input type="tel" id="phone-input">
<button id="validate-btn">Validate Number</button>
*/