libphonenumber-js
A simpler and smaller rewrite of Google Android's libphonenumber library in javascript/TypeScript.
Parse and format personal phone numbers.
If you’re trying to build a React component with it, take a look at react-phone-number-input.
LibPhoneNumber
Google's libphonenumber is an ultimate phone number formatting and parsing library developed by Google for Android) phones. It is written in C++ and Java, and, while it has an official autogenerated javascript port, that port is tightly coupled to Google's closure javascript framework, and, when compiled into a bundle, weighs about 550 kB (350 kB code + 200 kB metadata).
With many websites today asking for user's phone number, the internet could benefit from a simpler and smaller library that would just deal with parsing or formatting personal phone numbers, and that's what libphonenumber-js is.
Differences from Google's libphonenumber
Smaller footprint:
145 kB(65 kB code + 80 kB sufficient metadata) vs the original Google's550 kB(350 kB code + 200 kB full metadata).Comes with TypeScript definitions.
Can search for phone numbers in text. Google's autogenerated javascript port doesn't provide such feature for some reason.
Focuses on parsing and formatting personal phone numbers while skipping any other "special" cases like:
Emergency phone numbers like
911."Short codes" — short SMS-only numbers like
12345.Numbers starting with an
*. For example,*555is used in New Zeland to report non-urgent traffic incidents. Or, in Israel, certain advertising numbers start with a*.Australian
13-smart numbers, which are a "catchy" "short" form of regular "landline" numbers and are mainly used in advertisement.Alphabetic phone numbers like
1-800-GOT-MILK. People don't input their phone numbers like that. It was only used in advertisement in the days of push-button telephones."Two-in-one" phone numbers with "combined" extensions like
(530) 583-6985 x302/x2303. Phone numbers like that actually represent two separate phone numbers, so it's not clear which one to pick or how to return both at the same time.Local numbers with the "area code" omitted. For example, when dialing phone numbers within the same "area", people sometimes skip the "area code", and dial, say, just
456-789instead of proper(123) 456-789. This all is considered a relic of the past. In the modern world, there're no "local areas" and anyone could call everyone else around the world.
Doesn't provide "geolocation" feature when it can tell a city by a phone number.
Doesn't use hyphens or brackets when formatting phone numbers in international format. Instead, whitespace is used. The rationale is that brackets aren't relevant in international context because there're no "local areas", and hyphens aren't used because whitespace just looks cleaner.
Doesn't set
.countryto"001"when parsing "non-geographic" phone numbers, like mobile satellite communications services. Instead,.countryis set toundefinedin those cases, and instead a developer can call.isNonGeographic()method of thePhoneNumberinstance to find out whether the parsed phone number is a "non-geographic" one.Doesn't provide the equivalent of
libphonenumber'sformatNumberForMobileDialing()function that formats a number for dialing from a mobile phone within the same country. This feature may be required for dialing local numbers from a mobile phone in some countries like Brazil or Colombia where they require adding "carrier codes" when making such calls. Sincelibphonenumber-jsis not a dialing library (we're not Android phone operaing system), it doesn't prepend any "carrier codes" when formatting such phone numbers, though it does parse such "carrier codes" correctly.Fixed a small bug when Canadian numbers
+1310xxxxwheren't considered possible.<!--
- Doesn't use "carrier codes" when formatting numbers: "carrier codes" are only used in Colombia and Brazil and only when dialing within those countries from a mobile phone to a fixed line number.
(
.formatNumberForMobileDialing()method is not implemented therefore there's no need to format carrier codes) -->
Install
via npm
$ npm install libphonenumber-js --savevia yarn
$ yarn add libphonenumber-jsAlternatively, one could include it on a web page directly via a <script/> tag.
Use
If you'd like to create an issue, see bug reporting instructions.
Parse phone number
Parses a complete phone number.
import parsePhoneNumber from 'libphonenumber-js'
const phoneNumber = parsePhoneNumber(' 8 (800) 555-35-35 ', 'RU')
if (phoneNumber) {
phoneNumber.country === 'RU'
phoneNumber.number === '+78005553535'
phoneNumber.isPossible() === true
phoneNumber.isValid() === true
// Note: `.getType()` requires `/max` metadata: see below for an explanation.
phoneNumber.getType() === 'TOLL_FREE'
}
Format phone number
Formats a complete phone number.
import parsePhoneNumber from 'libphonenumber-js'
const phoneNumber = parsePhoneNumber('+12133734253')
if (phoneNumber) {
phoneNumber.formatInternational() === '+1 213 373 4253'
phoneNumber.formatNational() === '(213) 373-4253'
phoneNumber.getURI() === 'tel:+12133734253'
}
"As You Type" formatter
Parses and formats an incomplete phone number.
import { AsYouType } from 'libphonenumber-js'
new AsYouType().input('+12133734')
// Returns: '+1 213 373 4'
new AsYouType('US').input('2133734')
// Returns: '(213) 373-4'Validate phone number
Validates a complete phone number.
import {
isPossiblePhoneNumber,
isValidPhoneNumber,
validatePhoneNumberLength
} from 'libphonenumber-js'
isPossiblePhoneNumber('8 (800) 555-35-35', 'RU') === true
isValidPhoneNumber('8 (800) 555-35-35', 'RU') === true
validatePhoneNumberLength('8 (800) 555', 'RU') === 'TOO_SHORT'
validatePhoneNumberLength('8 (800) 555-35-35', 'RU') === undefined // Length is valid.isPossiblePhoneNumber() only validates phone number length, while isValidPhoneNumber() validates both phone number length and phone number digits.
validatePhoneNumberLength() is just a more detailed version of isPossiblePhoneNumber() — if the phone number length is invalid, instead of just returning false, it returns the actual reason why the phone number length is incorrect: TOO_SHORT, TOO_LONG, etc.
Full-text search
Finds complete phone numbers in text.
import { findPhoneNumbersInText } from 'libphonenumber-js'
findPhoneNumbersInText(`
For tech support call +7 (800) 555-35-35 internationally
or reach a local US branch at (213) 373-4253 ext. 1234.
`, 'US')
// Outputs:
//
// [{
// number: PhoneNumber {
// country: 'RU',
// countryCallingCode: '7',
// number: '+78005553535',
// nationalNumber: '8005553535'
// },
// startsAt : 22,
// endsAt : 40
// }, {
// number: PhoneNumber {
// country: 'US',
// countryCallingCode: '1',
// number: '+12133734253',
// nationalNumber: '2133734253',
// ext: '1234'
// },
// startsAt : 86,
// endsAt : 110
// }]"min" vs "max" vs "mobile" vs "core"
This library provides different "metadata" sets, where a "metadata" set is a complete list of phone number parsing and formatting rules for all possible countries.
As one may guess, the complete list of those rules is huge, so this library provides a way to optimize bundle size by choosing between max, min, mobile or "custom" metadata:
min— (default) The smallest metadata set- Is about
80 kilobytesin size (libphonenumber-js/metadata.min.jsonfile) - Choose this when:
- You don't need to detect phone number type — "fixed line", "mobile", etc — via
.getType() - You're fine with just validating phone number length via
.isPossible()and you don't need to strictly validate phone number digits via.isValid()
- You don't need to detect phone number type — "fixed line", "mobile", etc — via
- Is about
max— The complete metadata set- Is about
145 kilobytesin size (libphonenumber-js/metadata.max.jsonfile) - Choose this when:
- The basic
.isPossible()phone number length check is not enough for you and you need the strict phone number digits validation via.isValid() - You need to detect phone number type — "fixed line", "mobile", etc — via
.getType()
- The basic
- Is about
mobile— The complete metadata set for dealing with mobile numbers only- Is about
95 kilobytesin size (libphonenumber-js/metadata.mobile.jsonfile) - Choose this when:
- You need
maxmetadata capabilities and you only accept mobile numbers- It will still be able to handle non-mobile numbers just fine, with the only difference that
.isValid()or.isPossible()might potentially returnfalsefor them, or.getType()might potentially returnundefined.
- It will still be able to handle non-mobile numbers just fine, with the only difference that
- You need
- Is about
Choose one from the above and then simply import the functions from the relevant sub-package:
min—libphonenumber-js/min, or justlibphonenumber-js, since it's the default.max—libphonenumber-js/maxmobile—libphonenumber-js/mobile
As for "custom" metadata, it could be used in those rare cases when not all countries are needed and a developer would really prefer to reduce the bundle size to a minimum. In that case, one could generate their own "custom" metadata set and then import the functions from libphonenumber-js/core sub-package which doesn't come pre-packaged with any metadata and instead accepts metadata as the last argument of each exported function.
Definitions
National (Significant) Number
"National (significant) number" is all national phone number digits, excluding the "national prefix". Examples:
- International number:
+1 213 373 4253. Country:"US". National number:(213) 373-4253. National (significant) number:213 373 4253 - Inetrnational number:
+33 1 45 45 32 45. Country:"FR". National number:01 45 45 32 45. Notice the0at the start of the national number — it's because in France they add0"national prefix" when writing phone numbers in national format. National (significant) number:1 45 45 32 45(doesn't include the "national prefix").
Country Calling Code
"Country calling code" is all digits between the + and the national (significant) number in a number that is written in international format. Examples:
- International number:
+1 213 373 4253. Country:"US". National (significant) number:213 373 4253. Country calling code:1 - Inetrnational number:
+33 1 45 45 32 45. Country:"FR". National (significant) number:1 45 45 32 45. Country calling code:33
In some cases, multiple countries could share the same "country calling code". For example, USA, Canada and some Caribbean nations share the same country calling code 1.
Non-Geographic
The following "calling codes" don't belong to any given country or territory and are inherently international:
+800— Universal International Toll Free Number+808— Universal International Shared Cost Number+870— Inmarsat Global Limited+878— Universal Personal Telecommunications+881— Global Mobile Satellite System+882and+883— International Networks)+888— United Nations Office for the Coordination of Humanitarian Affairs+979— International Premium Rate Service
Such phone numbers are called "non-geographic", and their country is undefined.
Country Code
A "country code" is a two-letter ISO country code like "US", "CA", etc.
However, this library uses the term "country code" rather broadly and it includes both the official ISO country codes and a few of unofficial "country codes" that do not "officially" exist.
For that reason, a developer should use a "country code" returned from this library with caution in an application that only expects the official ISO "country codes" to exist. For example, such application will likely not have a label or a flag for such an unofficial "country code".
A developer could manually transform any unofficial "country code" returned from this library to a most-suitable official one. For example, it could be the ISO country code of the most suitable "parent" territory.
To get a list of all supported "country codes", both official and unofficial, use getCountries() function.
To check if a certain two-letter "country code" is supported by this library, use isSupportedCountry() function.
Country Code (additions)
Here's a list of the unofficial "country codes" — these codes are used for certain "regions" that're usually a subject of a territorial dispute.
AC— Ascension Island- (history) The region of Ascension Island is officially part of Saint Helena, Ascension and Tristan da Cunha
(
SH), which used to be called "Saint Helena and Dependencies" until 2009 when the dependencies were raised to equal status with Saint Helena. - Ascension Island has been assigned its own country calling code of
+247. - An unofficial code
ACis used for Ascension Island region in Google'slibphonenumber. ACis also an official "exceptional reservation" code for Ascension Island in the ISO-3166-1 standard.- The last official ISO-3166-2 "subdivision code" assigned to Ascension Island region is
SH-AC.
- (history) The region of Ascension Island is officially part of Saint Helena, Ascension and Tristan da Cunha
(
TA— Tristan da Cunha- (history) The region of Tristan da Cunha is officially part of Saint Helena, Ascension and Tristan da Cunha
(
SH), which used to be called "Saint Helena and Dependencies" until 2009 when the dependencies were raised to equal status with Saint Helena. - Tristan da Cunha shares a country calling code of
+290with Saint Helena where it has a unique prefix of8. - For the purpose of differentiating Tristan da Cunha phone numbers from Saint Helena phone numbers, an unofficial code
TAis used for it in Google'slibphonenumber. TAis also an official "exceptional reservation" code for Tristan da Cunha in the ISO-3166-1 standard.- The last official ISO-3166-2 "subdivision code" assigned to Tristan da Cunha region is
SH-TA.
- (history) The region of Tristan da Cunha is officially part of Saint Helena, Ascension and Tristan da Cunha
(
SH— Saint Helena- (history) The region of Saint Helena is officially part of Saint Helena, Ascension and Tristan da Cunha
(
SH), which used to be called "Saint Helena and Dependencies" until 2009 when the dependencies were raised to equal status with Saint Helena. - For the purpose of differentiating Saint Helena phone numbers from Tristan da Cunha phone numbers, the official ISO country code of
SHis only used for Saint Helena region in Google'slibphonenumber. - The last official ISO-3166-2 "subdivision code" assigned to Saint Helena region is
SH-HL.
- (history) The region of Saint Helena is officially part of Saint Helena, Ascension and Tristan da Cunha
(
XK— Kosovo- (history) The region of Kosovo separated from Yugoslavia (present Serbia,
RS) after a 1998-1999 civil war that was put to an end by NATO's bombing of Yugoslavia in 1999. The government of Kosovo officially (unilaterally) declared independence from Serbia in 2008. Due to the mixed opinions on the legitimacy of NATO's intervention, about half of the United Nations member states currently support Kosovo's independence while the rest of them don't, so Kosovo is currently not assigned any "official" country code. - Kosovo has been assigned its own country calling code of
+383. - An unofficial code
XKis used for Kosovo region in Google'slibphonenumber. XKis a "user-assigned" code in the ISO-3166-1 standard meaning that it can be freely assigned to any region by any application or organization for its own purposes.- The last official ISO-3166-2 "subdivision code" assigned to Kosovo region is
RS-KM.
- (history) The region of Kosovo separated from Yugoslavia (present Serbia,
There're also other territories having a disputed status of an independent state, whose country calling code or telephone numbering plan is different from the one used by their "official" parent territory. These territories are currently not implemented in this library but they could potentially be implemented in some future:
XA— Abkhazia- (history) The region of Abkhazia separated from Georgia) (
GE) during a civil war in 1992-1994. The government of Abkhazia officially (unilaterally) declared independence from Georgia in 1994 when the civil war was put to an end. The first state to officially recognize Abkhazia's independence was Russia in 2008. - Abkhazia currently shares a country calling code of
+7with Russia (RU) where it has unique prefixes of840and940, so the "country code" is currently parsed asRU. - For the purpose of differentiating Abkhazia phone numbers from Russia phone numbers, an unofficial code like
XAcould be used for it in Google'slibphonenumber. XAis a "user-assigned" code in the ISO-3166-1 standard meaning that it can be freely assigned to any region by any application or organization for its own purposes.- The last official ISO-3166-2 "subdivision code" assigned to Abkhazia region is
GE-AB.
- (history) The region of Abkhazia separated from Georgia) (
XO— South Ossetia- (history) The region of South Ossetia separated from Georgia) (
GE) during a civil war 1991–1992. The government of South Ossetia officially (unilaterally) declared independence from Georgia in 1992 when the civil war was put to an end. The first state to officially recognize South Ossetia's independence was Russia in 2008. - South Ossetia currently shares a country calling code of
+7with Russia (RU) where it has unique prefixes of850and929, so the "country code" is currently parsed asRU. - For the purpose of differentiating South Ossetia phone numbers from Russia phone numbers, an unofficial code like
XOcould be used for it in Google'slibphonenumber. XOis a "user-assigned" code in the ISO-3166-1 standard meaning that it can be freely assigned to any region by any application or organization for its own purposes.- South Ossetia region has not ever been assigned any official ISO-3166-2 "subdivision code".
- (history) The region of South Ossetia separated from Georgia) (
XC— Northern Cyprus- (history) The region of Northern Cyprus separated from Cyprus (
CY) during Turkey's military invasion in 1974. The government of Northern Cyprus officially (unilaterally) declared independence from Cyprus in 1983. The first state to officially recognize Northern Cyprus' independence was Turkey in 1983. - Northern Cyprus currently shares a country calling code of
+90with Turkey (TR) where it has unique prefixes of392,533and542, so the "country code" is currently parsed asTR. - For the purpose of differentiating Northern Cyprus phone numbers from Turkey phone numbers, some unofficial code like
XCcould be used for it in Google'slibphonenumber. - Northern Cyprus region has not ever been assigned any official ISO-3166-2 "subdivision code".
- (history) The region of Northern Cyprus separated from Cyprus (
API
parsePhoneNumber(string, defaultCountry?: string | options?: object): PhoneNumber
Parses a complete phone number from string.
Can be imported either as a "default" export or as a "named" export called parsePhoneNumberFromString.
import parsePhoneNumber from 'libphonenumber-js'
// import { parsePhoneNumberFromString as parsePhoneNumber } from 'libphonenumber-js'
const phoneNumber = parsePhoneNumber('(213) 373-42-53 ext. 1234', 'US')
if (phoneNumber) {
console.log(phoneNumber.formatNational())
}Returns an instance of PhoneNumber class, or undefined if no phone number could be parsed from the input string. That could be for a number of reasons. For example, the phone number in the input string could be incomplete, or it could contain a phone number that has an invalid country calling code, etc.
Available options:
defaultCountry: string— Default country code for parsing numbers written in non-international form (without a+sign). Will be ignored when parsing numbers written in international form (with a+sign). Instead of passing it asoptions.defaultCountry, one could also pass it as a standalonedefaultCountryargument (for convenience).defaultCallingCode: string— Default calling code for parsing numbers written in non-international form (without a+sign). Will be ignored when parsing numbers written in international form (with a+sign). It could be specified when parsing phone numbers belonging to "non-geographic numbering plans" which by nature don't have a country code, making thedefaultCountryoption unusable.extract: boolean— Defines the "strictness" of parsing a phone number. By default, theextractflag istruemeaning that it will attempt to extract the phone number from an input string like"My phone number is (213) 373-4253 and my hair is blue". This could be thought of as "less strict" parsing. To make it "more strict", one could passextract: falseflag, in which case the function will attempt to parse the input string as if the whole string was a phone number. Applied to the example above, it would returnundefinedbecause the entire string is not a phone number, but for an input string"(213) 373-4253"it would return a parsedPhoneNumber.
If a developer wants to know the exact reason why the phone number couldn't be parsed then they can use parsePhoneNumberWithError() function which throws an exact error:
import { parsePhoneNumberWithError, ParseError } from 'libphonenumber-js'
try {
const phoneNumber = parsePhoneNumberWithError('(213) 373-42-53 ext. 1234', {
defaultCountry: 'US'
})
} catch (error) {
if (error instanceof ParseError) {
// Not a phone number, non-existent country, etc.
console.log(error.message)
} else {
throw error
}
}NOT_A_NUMBER — When the supplied string is not a phone number. For example, when there are no digits: "abcde", "+".
INVALID_COUNTRY
When defaultCountry doesn't exist (or isn't supported by this library yet): parsePhoneNumber('(111) 222-3333', 'XX').
When parsing a non-international number without a defaultCountry: parsePhoneNumber('(111) 222-3333').
When an international number's country calling code doesn't exist: parsePhoneNumber('+9991112223333').
TOO_SHORT — When the number is too short. For example, just 1 or 2 digits: "1", "+12".
* TOO_LONG — When the national (significant) number is too long (17 digits max) or when the string being parsed is too long (250 characters max).
#
Analogy: parsePhoneNumberWithError() is analogous to new PhoneNumberUtil().parse() in Google's libphonenumber.
Strictness
By default, the parsing function will attempt to extract a phone number from the input string even in cases like "Support: (213) 373-4253 (robot)", which mimicks the behavior of the original Google's libphonenumber library, and is the default behavior for legacy reasons. However, if "strict" input validation is required, one can pass extract: false flag to demand that the whole input string be a viable phone number.
// By default it parses without `extract: false` flag.
// It will "extract" the phone number from the input string.
parsePhoneNumber('Call: (213) 373-4253', 'US') === PhoneNumber
// When parsing the same input string with `extract: false` flag,
// it will return `undefined`, because a phone number can't
// contain letters or a colon.
parsePhoneNumber('Call: (213) 373-4253', {
defaultCountry: 'US',
extract: false
}) === undefined
// When the whole input string represents a phone number,
// parsing it with `extract: false` flag will return a `PhoneNumber`.
parsePhoneNumber('(213) 373-4253', {
defaultCountry: 'US',
extract: false
}) === PhoneNumberPhoneNumber
PhoneNumber class represents a complete phone number.
PhoneNumber class instance is returned from parsePhoneNumber() function, or it could also be constructed manually from a number in E.164 format:
const phoneNumber = new PhoneNumber('+12133734253')
// (optional) Add a phone number extension.
phoneNumber.setExt('1234')
PhoneNumber class instance has the following properties:
number: string— The phone number inE.164format. Example:"+12133734253".countryCallingCode: string— The country calling code. Example:"1".nationalNumber: string— The national (significant) number. Example:"2133734253".country: string?— The country code. Example:"US". Will beundefinedwhen nocountrycould be derived from the phone number. For example, when several countries have the samecountryCallingCodeand thenationalNumberdoesn't look like it belongs to any particular one of them. Or when a number belongs to a non-geographic numbering plan.ext: string?— The phone number extension), if any. Example:"1234".carrierCode: string?— The "carrier code", if any. Example:"15". "Carrier codes" are only used in Colombia and Brazil and only when dialing within those countries from a mobile phone to a fixed line number.
PhoneNumber class instance provides the following methods:
setExt(ext: string)
Adds a phone number extension) to a phone number.
const phone = "+12133734253"
const phoneExt = "1234"
const phoneNumber = parsePhoneNumber(phone)
if (phoneNumber) {
if (phoneExt) {
phoneNumber.setExt(phoneExt)
}
// Returns "(213) 373-4253 ext. 1234"
return phoneNumber.formatNational()
}format(format: string, [options]): string
Formats the phone number into a string according to a specified format.
Available formats:
NATIONAL— Example:"(213) 373-4253"INTERNATIONAL— Example:"+1 213 373 4253"E.164— Example:"+12133734253"RFC3966(the phone number URI) — Example:"tel:+12133734253;ext=123"IDD— "Out-of-country" dialing format. Example:"011 7 800 555 35 35"for+7 800 555 35 35being called out ofoptions.fromCountry === "US". If nooptions.fromCountrywas passed or if there's no default IDD prefix foroptions.fromCountrythen returnsundefined.
Available options:
formatExtension(number, extension)— Formatsnumberandextensioninto a string. By default returns${number} ext. ${extension}for almost all countries with rare exceptions of some special cases like${number} x${extension}for the United Kingdom.nationalPrefix: Boolean— Some phone numbers can be formatted both with national prefix and without it. In such cases the library defaults to "with national prefix" (for legacy reasons). PassnationalPrefix: falseoption to force formatting without a national prefix.
Examples:
import parsePhoneNumber from 'libphonenumber-js'
const phoneNumber = parsePhoneNumber('+12133734253')
phoneNumber.format("NATIONAL") === '(213) 373-4253'
phoneNumber.format("INTERNATIONAL") === '+1 213 373 4253'
phoneNumber.format("RFC3966") === 'tel:+12133734253'
// The following are just convenience aliases for the `.format()` function.
phoneNumber.formatNational() === phoneNumber.format("NATIONAL")
phoneNumber.formatInternational() === phoneNumber.format("INTERNATIONAL")
phoneNumber.getURI() === phoneNumber.format("RFC3966")isPossible(): boolean
Checks if the phone number is "possible". Only checks the phone number length. Doesn't check the actual phone number digits.
isValid(): boolean
Checks if the phone number is "valid". First checks the phone number length and then checks the phone number digits against all available regular expressions.
By default, this library uses min ("minimal") metadata which is only 80 kB in size but also doesn't include the precise validation regular expressions resulting in less strict validation rules (some very basic validation like number length check is still included for each country). If you don't mind the extra 65 kB of metadata then use max metadata instead of the default (min) one. Google's library always uses "full" metadata so it will yield different isValidNumber() results compared to the "minimal" metadata used by default in this library.
/min vs /max vs /mobile metadata</summary>
####
js
import parseMin from 'libphonenumber-js/min'
import parseMax from 'libphonenumber-js/max'
import parseMobile from 'libphonenumber-js/mobile'
// In Singapore (+65), when a mobile number starts with `8`,
// it can only have the second digit in the range of `0..8`.
// In a number "+6589555555", the second digit is `9`
// which makes it an invalid mobile number.
// This is a "strict" validation rule and it is
// not included in the (default) `min` metadata.
// When using the (default) `min` metadata,
// basic number length check passes (from `8` to `11`)
// and the "loose" national number validation regexp check passes too:
// `(?:1\d{3}|[369]|7000|8(?:\d{2})?)\d{7}`.
parseMin('+6589555555').isValid() === true
// When using `max` or `mobile` metadata,
// the validation regexp for mobile numbers is more precise —
// `(?:8[1-8]|9[0-8])\\d{6}` — as well as the possible lengths (only `8`).
parseMax('+6589555555').isValid() === false
parseMobile('+6589555555').isValid() === false
#
See "Using phone number validation feature" for choosing between isPossible() and isValid().
getPossibleCountries(): string[]
Returns a list of countries that this phone number could possibly belong to.
Can be used when parsing a complete international phone number which contains a "country calling code" that is shared between several countries. If parsing such a phone number returns country: undefined then getPossibleCountries() function could be used to somehow speculate about what country could this phone number possibly belong to.
getType(): string?
Returns phone number type — fixed line, mobile, toll free, etc — or undefined if the number is invalid or if there are no phone number type regular expressions for this country in metadata.
By default, this library uses min ("minimal") metadata which is only 80 kB in size but also doesn't include the regular expressions for determining a phone number type — fixed line, mobile, toll free, etc — which could result in getType() returning undefined for most countries. If you don't mind the extra 65 kB of metadata then use max metadata instead of the default (min) one. Google's library always uses "full" metadata so it will yield different getNumberType() results compared to the "minimal" metadata used by default in this library.
MOBILE — Cellphones.
FIXED_LINE — Stationary phones.
FIXED_LINE_OR_MOBILE — Could be MOBILE or FIXED_LINE.
PREMIUM_RATE — Callers are charged by call or per minute. SMS text messages are also subject to charge.
TOLL_FREE — Free to call from anywhere.
SHARED_COST — "An intermediate level of telephone call billing where the charge for calling a particular international or long-distance phone number is partially, but not entirely, paid for by the recipient".
VOIP — "IP telephony". Calls are made over the Internet rather than via the conventional telephone-only lines.
PERSONAL_NUMBER — Phones connected by satellites.
PAGER — "Pagers" are wireless telecommunications devices that were widely used in the 80-es and could receive (and, optionally, send) text or voice messages.
UAN — "UAN is a number resource that allows a service or business with several terminating lines to be reached through a unique universal number. A UAN number shall be dialable from the entire Pakistan, based on the applicant’s proposed coverage without dialing the area code. UAN cannot be assigned to two separate business or mutually exclusive public services. Each service provider who allows UAN through its network shall offer a tariff, which is not more expensive than the normal tariff available for a similar non-UAN public service".
* VOICEMAIL — "A voicemail access number is a telephone number provided by a voicemail service to allow subscribers to dial into their voicemail accounts and manage any currently saved messages. Typically, the number is used when a subscriber is away from home and wishes to check any voice messages currently stored on the service. Originally envisioned as part of the features associated with voicemail accounts offered with land line accounts, many mobile service providers today also supply their customers with a voicemail access number to use when checking messages from any phone other than the mobile or cellular unit associated with the account".
#
/min vs /max vs /mobile metadata</summary>
####
js
import parseMin from 'libphonenumber-js/min'
import parseMax from 'libphonenumber-js/max'
import parseMobile from 'libphonenumber-js/mobile'
// Singapore (+65) mobile number "+6584655555".
// The (default) `min` bundle doesn't contain any regexps for
// getting phone number type from phone number digits for Singapore.
parseMin('+6584655555').getType() === undefined
// The `max` does contain all the regexps for getting
// phone number type from phone number digits for any country.
parseMax('+6584655555').getType() === 'MOBILE'
// The `max` does contain all the regexps for getting
// mobile phone number type from mobile phone number digits for any country.
parseMobile('+6584655555').getType() === 'MOBILE'
isNonGeographic(): boolean
Returns true if the number belongs to a "non-geographic numbering plan".
isEqual(phoneNumber: PhoneNumber): boolean
Compares two PhoneNumbers: returns true if they're equal, false otherwise.
isPossiblePhoneNumber(input: string, defaultCountry?: string | options?: object): boolean
Checks if input can be parsed as a "possible" phone number. A phone number is "possible" when it has valid length. The actual phone number digits aren't validated.
isPossiblePhoneNumber('8 (888) 888-88-88', 'RU') === true
isPossiblePhoneNumber('+12223333333') === trueFor the description of the defaultCountry?: string | options?: object argument, see parsePhoneNumber() function description.
This function is just a shortcut for a two-step process of "strictly" parsing a phone number and then calling .isPossible().
isValidPhoneNumber(input: string, defaultCountry?: string | options?: object): boolean
Checks if input can be parsed as a "valid" phone number. A phone number is "valid" when it has valid length, and the actual phone number digits match the regular expressions for its country.
isValidPhoneNumber('8 (888) 888-88-88', 'RU') === false
isValidPhoneNumber('8 (800) 555-35-35', 'RU') === true
isValidPhoneNumber('+12223333333') === false
isValidPhoneNumber('+12133734253') === trueFor the description of the defaultCountry?: string | options?: object argument, see parsePhoneNumber() function description.
This function is just a shortcut for a two-step process of "strictly" parsing a phone number and then calling .isValid().
See "Using phone number validation feature" for choosing between isPossible() and isValid().
isValidPhoneNumberForCountry(input: string, country: string): boolean
Same as isValidPhoneNumber() but with the "default country" argument being replaced with an "exact country", which is more strict.
This function is not currently exported from this library. The reason is that its result would be too vague when it returns false — it could mean any of:
- The input is not a valid phone number.
- The input is a valid phone number but it belongs to another country.
- The input is a phone number that belongs to the correct country but is not valid.
At least the second case should be handled separately from a "User Experience" point of view: if the user has input a valid phone number but for another country, they should be notified that "perhaps you meant another country" rather than just throwing "the phone number is incorrect" error in their face.
But for those who'd still like to have such function, here's a possible implementation for it:
export default function isValidPhoneNumberForCountry(phoneNumberString, country) {
const phoneNumber = parsePhoneNumber(phoneNumberString, {
defaultCountry: country,
// Demand that the entire input string must be a phone number.
// Otherwise, it would "extract" a phone number from an input string.
extract: false
})
if (!phoneNumber) {
return false
}
if (phoneNumber.country !== country) {
return false
}
return phoneNumber.isValid()
}The same approach could be used to implement an isPossiblePhoneNumberForCountry() function.
validatePhoneNumberLength(input: string, defaultCountry?: string | options?: object): string?
Checks if input phone number length is valid. If it is, then nothing is returned. Otherwise, a rejection reason is returned.
NOT_A_NUMBER — When the supplied string is not a phone number. For example, when there are no digits: "abcde", "+".
INVALID_COUNTRY
When defaultCountry doesn't exist (or isn't supported by this library yet): parsePhoneNumber('(111) 222-3333', 'XX').
When parsing a non-international number without a defaultCountry: parsePhoneNumber('(111) 222-3333').
When an international number's country calling code doesn't exist: parsePhoneNumber('+9991112223333').
TOO_SHORT — When the number is too short. For example, just 1 or 2 digits: "1", "+12".
TOO_LONG — When the national (significant) number is too long (17 digits max) or when the string being parsed is too long (250 characters max).
INVALID_LENGTH — When the national (significant) number is neither too short, nor too long, but somewhere in between and its length is still invalid.
#
validatePhoneNumberLength('abcde') === 'NOT_A_NUMBER'
validatePhoneNumberLength('444 1 44') === 'INVALID_COUNTRY'
validatePhoneNumberLength('444 1 44', 'TR') === 'TOO_SHORT'
validatePhoneNumberLength('444 1 444', 'TR') === undefined // Length is valid.
validatePhoneNumberLength('444 1 4444', 'TR') === 'INVALID_LENGTH'
validatePhoneNumberLength('444 1 44444', 'TR') === 'INVALID_LENGTH'
validatePhoneNumberLength('444 1 444444', 'TR') === undefined // Length is valid.
validatePhoneNumberLength('444 1 4444444444', 'TR') === 'TOO_LONG'For the description of the defaultCountry?: string | options?: object argument, see parsePhoneNumber() function description.
This function is just a more detailed version of isPossiblePhoneNumber() for those who asked for a more specific rejection reason.
The phone number is parsed "strictly" from the input string.
class AsYouType(defaultCountry?: string | options?: object)
Creates a formatter for a partially-entered phone number.
For the description of the defaultCountry?: string | options?: object argument, see parsePhoneNumber() function description.
The formatter instance has the following methods:
input(text: string)— Appends text to the input. Returns the formatted phone number.reset()— Resets the input.
new AsYouType().input('+12133734') === '+1 213 373 4'
new AsYouType('US').input('2133734') === '(213) 373-4'The formatter instance also provides the following getters:
getNumber(): PhoneNumber?— Returns thePhoneNumber. Will returnundefinedif no national (significant) number digits have been entered so far, or if nodefaultCountry/defaultCallingCodehas been specified and the user enters a phone number in national format (without a+).getNumberValue(): string?— Returns the phone number inE.164format. For example, for default country"US"and input"(222) 333-4444"it will return"+12223334444". Will returnundefinedif no digits have been input, or when the user inputs a phone number in national format (without a+) and no default country or default "country calling code" have been specified.getChars(): string— Returns the phone number characters:+sign (if present) and the digits. Returns an empty string if no phone number characters have been input.getTemplate(): string— Returns the template that is used to format the phone number characters —+sign (if present) and the digits — which are designated byx-es. Returns an empty string if no phone number characters have been input.
// National phone number input example.
const asYouType = new AsYouType('US')
asYouType.input('2') === '2'
asYouType.getNumber().number === '+12'
asYouType.getChars() === '2'
asYouType.getTemplate() === 'x'
asYouType.input('1') === '21'
asYouType.getNumber().number === '+121'
asYouType.getChars() === '21'
asYouType.getTemplate() === 'xx'
asYouType.input('3') === '(213)'
asYouType.getNumber().number === '+1213'
asYouType.getChars() === '213'
asYouType.getTemplate() === '(xxx)'
asYouType.input('3734253') === '(213) 373-4253'
asYouType.getNumber().number === '+12133734253'
asYouType.getChars() === '2133734253'
asYouType.getTemplate() === '(xxx) xxx-xxxx'
// International phone number input example.
const asYouType = new AsYouType()
asYouType.input('+1-213-373-4253') === '+1 213 373 4253'
asYouType.getNumber().country === 'US'
asYouType.getNumber().number === '+12133734253'
asYouType.getChars() === '+12133734253'
asYouType.getTemplate() === 'xx xxx xxx xxxx'isInternational(): boolean— Returnstrueif the phone number is being input in international format. In other words, returnstrueif and only if the parsed phone number starts with a"+".getCallingCode(): string?— Returns the "country calling code" part of the phone number. Returnsundefinedif the number is not being input in international format, or if no valid "country calling code" has been entered. Supports "non-geographic" phone numbering plans: even though those aren't technically "countries", they have their own "country calling codes" too.getCountry(): string?— Returns a two-letter country code of the phone number. Returnsundefinedfor "non-geographic" phone numbering plans. Returnsundefinedif no phone number has been input yet, or if it couldn't tell what country the phone number belongs to — that could happen when several countries have the same "country calling code" and the phone number doesn't look like it belongs to any particular one of them.isPossible(): boolean— Returnstrueif the phone number is "possible". Is just a shortcut forgetNumber()?.isPossible().isValid(): boolean— Returnstrueif the phone number is "valid". Is just a shortcut forgetNumber()?.isValid().
1.6.0)</summary>
####
For legacy API (before version 1.6.0) the formatter instance provides the following getters:
country: string? — The country code of the phone number. Will return undefined if the country couldn't be derived from the number.
getNationalNumber(): string — Returns the national (significant) number part of the phone number.
* getTemplate(): string? — Same as the current version of getTemplate() with the only difference that it returns undefined if no suitable format was found for the number being entered (or if no national (significant) number has been entered so far).
js
// National phone number input example.
const asYouType = new AsYouType('US')
asYouType.input('2') === '2'
asYouType.getNationalNumber() === '2'
asYouType.input('1') === '21'
asYouType.getNationalNumber() === '21'
asYouType.input('3') === '(213)'
asYouType.getNationalNumber() === '213'
asYouType.input('3734253') === '(213) 373-4253'
asYouType.getNationalNumber() === '2133734253'
// International phone number input example.
const asYouType = new AsYouType()
asYouType.input('+1-213-373-4253') === '+1 213 373 4253'
asYouType.country === 'US'
asYouType.getNationalNumber() === '2133734253'
#
"As You Type" formatter was created by Google as part of their Android OS and therefore only works for numerical keyboard input, i.e. it can only accept digits (and a + sign at the start of an international number). When used on desktops where a user can input all kinds of punctuation (spaces, dashes, parens, etc) it simply ignores everything except digits (and a + sign at the start of an international number).
Google's "As You Type" formatter does not support entering phone number extensions. If your project requires inputting phone number extensions then use a separate input field for that.
findPhoneNumbersInText(text: string, defaultCountry?: string | options?: object): object[]
Searches for complete phone numbers in text.
Available options:
defaultCountry: stringdefaultCallingCode: string
For the description of defaultCountry or defaultCallingCode, see parsePhoneNumber() function description.
import { findPhoneNumbersInText } from 'libphonenumber-js'
findPhoneNumbersInText(`
For tech support call +7 (800) 555-35-35 internationally
or reach a local US branch at (213) 373-4253 ext. 1234.
`, 'US')
// Outputs:
//
// [{
// number: PhoneNumber {
// country: 'RU',
// countryCallingCode: '7',
// number: '+78005553535',
// nationalNumber: '8005553535'
// },
// startsAt : 22,
// endsAt : 40
// }, {
// number: PhoneNumber {
// country: 'US',
// countryCallingCode: '1',
// number: '+12133734253',
// nationalNumber: '2133734253',
// ext: '1234'
// },
// startsAt : 86,
// endsAt : 110
// }](in previous versions, it was called findNumbers())
1.6.0) example</summary>
####
js
import { findNumbers } from 'libphonenumber-js'
findNumbers(`
For tech support call +7 (800) 555-35-35 internationally
or reach a local US branch at (213) 373-4253 ext. 1234.
`, 'US')
// Outputs:
//
// [{
// phone : '8005553535',
// country : 'RU',
// startsAt : 22,
// endsAt : 40
// },
// {
// phone : '2133734253',
// country : 'US',
// ext : '1234',
// startsAt : 86,
// endsAt : 110
// }]
#
By default it processes the whole text and then outputs the phone numbers found. If the text is very big (say, a hundred thousand characters) then it might freeze the user interface for a couple of seconds. To avoid such lags one could employ "iterator" approach using searchPhoneNumbersInText() to perform the search asynchronously (e.g. using requestIdleCallback or requestAnimationFrame).
(in previous versions, it was called searchNumbers())
searchPhoneNumbersInText()</summary>
####
ES6 iterator:
js
import { searchPhoneNumbersInText } from 'libphonenumber-js'
const text = `
For tech support call +7 (800) 555-35-35 internationally
or reach a local US branch at (213) 373-4253 ext. 1234.
`
async function() {
for (const number of searchPhoneNumbersInText(text, 'US')) {
console.log(number)
await new Promise(resolve => setTimeout(resolve, 0))
}
console.log('Finished')
}
Java-style iterator (for those still not using ES6):
js
import { PhoneNumberMatcher } from 'libphonenumber-js'
const matcher = new PhoneNumberMatcher(`
For tech support call +7 (800) 555-35-35 internationally
or reach a local US branch at (213) 373-4253 ext. 1234.
`, {
defaultCountry: 'US',
v2: true
})
// Search cycle iteration.
const iteration = () => {
if (matcher.hasNext()) {
console.log(matcher.next())
setTimeout(iteration, 0)
} else {
console.log('Finished')
}
}
// Run the search.
iteration()
#
Although Google's javascript port doesn't provide the findPhoneNumbersInText() function, the Java and C++ ports do. I guess that's because Google just doesn't need to crawl phone numbers on Node.js because they do it in Java or C++. Still, javascript nowadays is the most popular programming language given its simplicity and user-friendliness. The findPhoneNumbersInText() function provided by this library is a port of Google's PhoneNumberMatcher.java into javascript.
getExampleNumber(country: string, examples: object): PhoneNumber
Returns an example phone number for a country code. Returns an instance of PhoneNumber class. Will return undefined if country doesn't exist or isn't supported by this library.
import examples from 'libphonenumber-js/mobile/examples'
import { getExampleNumber } from 'libphonenumber-js'
const phoneNumber = getExampleNumber('RU', examples)
phoneNumber.formatNational() === '8 (912) 345-67-89'isSupportedCountry(country: string): boolean
Checks if a given country code is supported by this library.
isSupportedCountry('RU') === true
isSupportedCountry('XX') === falsegetCountries(): string[]
Returns a list of supported countries.
getCountries() === ["AC", "AD", ...]getCountryCallingCode(country: string): string
Returns country calling code for a country code. Will throw an error if country doesn't exist or isn't supported by this library.
getCountryCallingCode('RU') === '7'
getCountryCallingCode('IL') === '972'getExtPrefix(country: string): string
Returns phone number extension prefix for a given country code. If no custom ext prefix is defined for a country then the default " ext. " prefix is returned.
getExtPrefix('US') === ' ext. '
getExtPrefix('GB') === ' x'parseDigits(text: string): string
Parses digits from string. Can be used for building a phone number extension input component (e.g. react-phone-number-input).
parseDigits('x123') === '123'
parseDigits('٤٤٢٣') === '4423'