A simpler and smaller rewrite of Google Android's libphonenumber
library in javascript.
If you’re trying to build a React component with it, take a look at react-phone-number-input
.
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 get the parsing and formatting right, and that's what libphonenumber-js
is.
libphonenumber
Smaller footprint: 145 kB
(65 kB code + 80 kB sufficient metadata) vs the original Google's 550 kB
(350 kB code + 200 kB full metadata).
Can search for phone numbers in text (Google's autogenerated javascript port can't).
Aims at parsing and formatting people's phone numbers while skipping all other "special" cases like:
Emergency phone numbers like 911
.
"Short codes": short SMS-only numbers like 12345
.
Numbers starting with a *
, like *555
.
Alphabetic phone numbers like 1-800-GOT-MILK
: people don't input their phone numbers like that, it's only used in advertisement.
"Two-in-one" phone numbers with "combined" extensions like (530) 583-6985 x302/x2303
that in fact represent two separate phone numbers, because the library can only return a single phone number when parsing a string.
Overall, doesn't support formatting non-"conventional" numbers like numbers with the "area code" omitted or "alternative" "short" numbers like Australian 13
-smart numbers. For example, when dialing phone numbers within the same "area", people sometimes skip the "area code", and dial, say, 456-789
instead of (123) 456-789
. Google's libphonenumber
supports formatting such numbers (with "area code" omitted) because it is used for dialing on the Android phone operating system. Because libphonenumber-js
isn't a phone operating system and is not used for actual dialing — only for inputting internationally-dialable personal phone numbers — it doesn't format such "short" phone numbers because it doesn't need to support those.
Any other "miscellaneous" cases that're considered irrelevant for the task.
Doesn't provide "geolocation" by a phone number.
Doesn't use hyphens or brackets when formatting international phone numbers, only whitespace (seems more logical this way).
Doesn't set .country
to "001"
when parsing "non-geographic" phone numbers (like mobile satellite communications services). Instead, .country
is undefined
in those cases, and a developer can call .isNonGeographic()
method of the PhoneNumber
instance to find out whether the parsed phone number is a "non-geographic" one.
Doesn't provide the equivalent of libphonenumber
's formatNumberForMobileDialing()
function that formats a number for dialing using a mobile phone within the country: dialing local numbers from a mobile phone is a bit more complicated in some countries like Brazil or Colombia where they require adding "carrier codes" when making a call. Since libphonenumber-js
is not a dialing library (we're not Android phone operaing system), it doesn't prepend any "carrier codes" when formatting phone numbers, though it does parse such "carrier codes" correctly.
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'
}
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 the actual phone number digits.
validatePhoneNumberLength()
is just a more detailed version of isPossiblePhoneNumber()
— if the phone number length is invalid, it returns the actual reason: TOO_SHORT
, TOO_LONG
, etc.
import parsePhoneNumber from 'libphonenumber-js'
const phoneNumber = parsePhoneNumber('+12133734253')
phoneNumber.formatInternational() === '+1 213 373 4253'
phoneNumber.formatNational() === '(213) 373-4253'
phoneNumber.getURI() === 'tel:+12133734253'
import { AsYouType } from 'libphonenumber-js'
new AsYouType().input('+12133734')
// Outputs: '+1 213 373 4'
new AsYouType('US').input('2133734')
// Outputs: '(213) 373-4'
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
// }]
This library provides different "metadata" sets, "metadata" being a list of phone number parsing and formatting rules for all countries. The complete list of those rules is huge, so this library provides a way to optimize bundle size by choosing between max
, min
, mobile
and "custom" metadata:
max
— The complete metadata set, is about 145 kilobytes
in size (libphonenumber-js/metadata.max.json
). Choose this when you need the most strict version of isValid()
, or if you need to detect phone number type ("fixed line", "mobile", etc).
min
— (default) The smallest metadata set, is about 80 kilobytes
in size (libphonenumber-js/metadata.min.json
). Choose this by default: when you don't need to detect phone number type ("fixed line", "mobile", etc), or when a basic version of isValid()
is enough. The min
metadata set doesn't contain the regular expressions for phone number digits validation (via .isValid()
) and detecting phone number type (via .getType()
) for most countries. In this case, .isValid()
still performs some basic phone number validation (for example, checks phone number length), but it doesn't validate phone number digits themselves the way max
metadata validation does.
mobile
— The complete metadata set for dealing with mobile numbers only, is about 95 kilobytes
in size (libphonenumber-js/metadata.mobile.json
). Choose this when you need max
metadata and when you only accept mobile numbers. Other phone number types will still be parseable, but they won't be recognized as being "valid" (.isValid()
will return false
).
To use a particular metadata set, simply import functions from a relevant sub-package:
libphonenumber-js/max
libphonenumber-js/min
libphonenumber-js/mobile
Importing functions directly from libphonenumber-js
effectively results in using the min
metadata.
Sometimes (rarely) not all countries are needed, and in those cases developers may want to generate their own "custom" metadata set. For those cases, there's libphonenumber-js/core
sub-package which doesn't come pre-packaged with any default metadata set and instead accepts metadata as the last argument of each exported function.
A "country code" is a two-letter ISO country code (like US
).
This library supports all officially assigned ISO alpha-2 country codes, plus a few extra ones like: AC
(Ascension Island), TA
(Tristan da Cunha), XK
(Kosovo).
To check whether a country code is supported, use isSupportedCountry()
function.
There're several calling codes that don't belong to any country:
+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+882
and +883
— International Networks+888
— United Nations Office for the Coordination of Humanitarian Affairs+979
— International Premium Rate ServiceSuch phone numbering plans are called "non-geographic", and their phone numbers have country
set to undefined
.
"National (significant) number" are the national phone number digits (without "national prefix"). For example, +1 213 373 4253
(or (213) 373-4253
in national format) is a US phone number and its national (significant) number is 213 373 4253
. Another example is +33 1 45 45 32 45
(or 01 45 45 32 45
in national format) which is a French phone number where they add 0
"national prefix" when writing phone numbers in national format; in this case the national (significant) number is 1 45 45 32 45
.
"Country calling code" are the digits between the +
and the national (significant) number when the number is written in international format. E.g. for US country calling code is 1
and for France it's 33
. Several countries can share the same "country calling code", e.g. NANPA countries like USA and Canada sharing the same 1
country calling code.
Parses a phone number from string
.
Can be imported both as a "default" export and as a "named" export parsePhoneNumberFromString
.
import parsePhoneNumber from 'libphonenumber-js'
// Or: 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: for example, when the string contains no phone number, or the phone number starts with a non-existent country calling code, etc.
Available options
:
defaultCountry: string
— Default country 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 as options.defaultCountry
, one could also pass it as a standalone defaultCountry
argument (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 the defaultCountry
option unusable.
extract: boolean
— Defines the "strictness" of parsing a phone number. By default, the extract
flag is true
meaning 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 pass extract: false
flag, 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 return undefined
because the entire string is not a phone number, but for input string "(213) 373-4253"
it would return a parsed PhoneNumber
.
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 the 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
}
}
By default, the parsing function will attempt to extract a phone number from an 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.
parsePhoneNumber('Call: (213) 373-4253', 'US') === PhoneNumber
// When parsing the same 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
parsePhoneNumber('(213) 373-4253', {
defaultCountry: 'US',
extract: false
}) === PhoneNumber
PhoneNumber
PhoneNumber
class instance has the following properties:
number: string
— The phone number in E.164
format. 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 be undefined
when no country
could be derived from the phone number. For example, when several countries have the same countryCallingCode
and the nationalNumber
doesn't look like it belongs to any 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)
Sets a phone number extension of a phone number. Could be useful when formatting phone numbers stored as two separate fields: the phone number itself and the extension part.
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 format
.
Available format
s:
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 35
being called out of options.fromCountry === "US"
. If no options.fromCountry
was passed or if there's no default IDD prefix for options.fromCountry
then returns undefined
.Available options
:
formatExtension(number, extension)
— Formats number
and extension
into a string. By default returns ${number} ext. ${extension}
for almost all countries with rare exceptions of some special cases like ${number} x${extension}
for UK.
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). Pass nationalPrefix: false
option to force formatting without national prefix in such cases.
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'
// Aliases
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 against any regular expressions.
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 the library uses "minimal" metadata which is only 75 kilobytes in size but also doesn't include the precise validation regular expressions resulting in less strict validation rules (some very basic validation like length check is still included for each country). If you don't mind the extra 65 kilobytes of metadata then use "full" metadata instead (140 kilobytes). 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
See "Using phone number validation feature" for choosing between isPossible()
and isValid()
.
getPossibleCountries(): string[]
Returns a list of countries this phone number could possibly belong to.
Can be used when parsing complete international phone numbers containing a "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 the library uses "minimal" metadata which is only 75 kilobytes in size but also doesn't include the regular expressions for determining a specific phone number type (fixed line, mobile, toll free, etc) resulting in getType()
returning undefined
for most countries. If you don't mind the extra 65 kilobytes of metadata then use "full" metadata instead (140 kilobytes). 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.
/min
vs /max
vs /mobile
isNonGeographic(): boolean
Returns true
if the number belongs to a "non-geographic numbering plan".
isEqual(phoneNumber: PhoneNumber): boolean
Compares two PhoneNumber
s: 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') === true
For 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') === true
For 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 an "exact country" instead.
This function is not currently exported from this library. The reason is that its result would be too vague when false
is returned — it could mean any of:
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 "the country is incorrect" rather than that "the phone number is incorrect", otherwise it would be bad UX design.
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.
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've 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 the PhoneNumber
. Will return undefined
if no national (significant) number digits have been entered so far, or if no defaultCountry
/defaultCallingCode
has been set and the user enters a phone number not in international format.
getNumberValue(): string?
— Returns the phone number in E.164
format. For example, for country "US"
and input "(222) 333-4444"
it will return "+12223334444"
. Will return undefined
if no digits have been input, or when inputting a phone number in national format and no default country or default "country calling code" have been set.
getChars(): string
— Returns the phone number characters entered by the user: digits and a +
sign (if present). Returns an empty string if no phone number characters have been input.
getTemplate(): string
— Returns the template used to format the phone number characters (digits and a +
sign, if present), which are denoted by x
-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
— Returns true
if the phone number is being input in international format. In other words, returns true
if and only if the parsed phone number starts with a "+"
.
getCallingCode(): string?
— Returns the "country calling code" part of the phone number. Returns undefined
if 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. Returns undefined
for "non-geographic" phone numbering plans. Returns undefined
if no phone number has been input yet.
isPossible(): boolean
— Returns true
if the phone number is "possible". Is just a shortcut for PhoneNumber.isPossible()
.
isValid(): boolean
— Returns true
if the phone number is "valid". Is just a shortcut for PhoneNumber.isValid()
.
1.6.0
)"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 in 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 in the start of an international number).
Google's "As You Type" formatter does not support entering phone number extensions. If your project requires phone number extensions input then use a separate input field for that.
Searches for phone numbers in text
.
Available options
:
defaultCountry: string
defaultCallingCode: 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
) exampleBy 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 can employ "iterator" approach using searchPhoneNumbersInText()
to perform the search asynchronously (e.g. using requestIdleCallback
or requestAnimationFrame
).
(in previous versions, it was called searchNumbers()
)
searchPhoneNumbersInText()
Although Google's javascript port doesn't have the findPhoneNumbersInText()
functionality the Java and C++ ports do. I guess Google just doesn't need to crawl phone numbers on Node.js because they can afford to hire a Java/C++ developer to do that. Still, javascript nowadays is the most popular programming language given its simplicity and user-friendliness. The findPhoneNumbersInText()
function provided is a port of Google's PhoneNumberMatcher.java
into javascript.
Returns an example phone number for a country. 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'
Checks if a country is supported by this library.
isSupportedCountry('RU') === true
isSupportedCountry('XX') === false
Returns a list of supported countries.
getCountries() === ["AC", "AD", ...]
Returns country calling code for a country. Will throw an error if country
doesn't exist or isn't supported by this library.
getCountryCallingCode('RU') === '7'
getCountryCallingCode('IL') === '972'
Returns phone number extension prefix for a given country. If no custom ext prefix is defined for a country
then the default " ext. "
prefix is returned.
getExtPrefix('US') === ' ext. '
getExtPrefix('GB') === ' x'
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'
Parses phone number characters (+
and digits). Can be used for building a phone number input component (e.g. react-phone-number-input).
parseIncompletePhoneNumber('8 (800) 555') === '8800555'
parseIncompletePhoneNumber('+7 800 555') === '+7800555'
parseIncompletePhoneNumber('+٤٤٢٣٢٣٢٣٤') === '+442323234'
Parses next character of an input string while parsing phone number digits (including a +
) from that string. Basically, it discards everything except +
and digits, and +
is only allowed at the start of a phone number.
This function is a low-level one that is currently only used in react-phone-number-input
with input-format
. Frankly speaking, that's the only reason why this function is exported. Other developers should just ignore it and use parseIncompletePhoneNumber()
instead because it's much simpler.
// Suppose a user inputs a "+1 (213) 373-42-53" string
// and it starts parsing that string character-by-character.
parsePhoneNumberCharacter('+', undefined) === '+'
parsePhoneNumberCharacter('1', '+') === '1'
parsePhoneNumberCharacter(' ', '+1') === undefined
parsePhoneNumberCharacter('(', '+1') === undefined
parsePhoneNumberCharacter('2', '+1') === '2'
parsePhoneNumberCharacter('1', '+12') === '1'
parsePhoneNumberCharacter('3', '+121') === '3'
parsePhoneNumberCharacter(')', '+1213') === undefined
parsePhoneNumberCharacter(' ', '+1213') === undefined
parsePhoneNumberCharacter('3', '+1213') === '3'
parsePhoneNumberCharacter('7', '+12133') === '7'
parsePhoneNumberCharacter('3', '+121337') === '3'
parsePhoneNumberCharacter('-', '+121337') === undefined
parsePhoneNumberCharacter('4', '+1213373') === '4'
parsePhoneNumberCharacter('2', '+12133734') === '2'
parsePhoneNumberCharacter('-', '+12133734') === undefined
parsePhoneNumberCharacter('5', '+121337342') === '5'
parsePhoneNumberCharacter('3', '+1213373425') === '3'
So basically, it's the same as parseIncompletePhoneNumber()
with the only difference that it operates at a character-by-character level rather than at a string-as-a-whole level.
The optional emitEvent
argument is a function of (eventName: string)
arguments. It will be called in a situation when the application should stop parsing the input string. Currently, the only situation when that could happen is when it encounters an "out-of-place" +
character. For example, when parsing a "+1 (234) + 56-78"
string it would emit an "end"
event at the second +
character so that the application would return "+1234"
rather than "+12345678"
.
Formats a possibly incomplete phone number.
While the usual parsePhoneNumber(string).format()
function could only be used to format a complete phone number, this function could be used to format a possibly incomplete phone number.
The value
argument should be a (possibly incomplete) phone number in E.164
format.
For the description of the defaultCountry?: string | options?: object
argument, see parsePhoneNumber()
function description.
This function is just an alias for new AsYouType(defaultCountry, metadata).input(value)
. It can be used for building a phone number input component (e.g. react-phone-number-input).
// National numbers, with second argument.
formatIncompletePhoneNumber('8800555', 'RU') === '8 (800) 555'
formatIncompletePhoneNumber('8800555', { defaultCountry: 'RU' }) === '8 (800) 555'
formatIncompletePhoneNumber('8800555', { defaultCallingCode: '7' }) === '8 (800) 555'
// International numbers, without second argument.
formatIncompletePhoneNumber('+7800555') === '+7 800 555'
1.6.0
): parse()
, parseNumber()
, format()
, formatNumber()
, isValidNumber()
, getNumberType()
.{ extended: true }
documentation and examplesparseNumber()
and isValidNumber()
isValidNumberForRegion()
I personally don't use strict phone number validation in my projects. The rationale is that telephone numbering plans can and sometimes do change, meaning that PhoneNumber.isValid()
function may one day become outdated on a website that isn't actively maintained anymore. Imagine a "promo-site" or a "personal website" being deployed once and then running for years without any maintenance, where a client may be unable to submit a simple "Contact Us" form just because this newly allocated pool of mobile phone numbers wasn't present in that old version of libphonenumber-js
bundled in it.
Whenever there's a "business requirement" to validate a phone number that's being input by a user, I prefer using PhoneNumber.isPossible()
instead of PhoneNumber.isValid()
, so that it just validates the phone number length, and doesn't validate the actual phone number digits. But it doesn't mean that you shouldn't use PhoneNumber.isValid()
— maybe in your case it would make sense.
If you’re trying to build a React component with this library, take a look at react-phone-number-input
.
This library is a simpler rewrite of Google's libphonenumber
library. Basically, it mimicks Google's library behavior. Hence, as long as this library's demo page and Google's library demo page exhibit the same behavior, it's not considered a bug.
When reporting issues with:
one must provide two links:
libphonenumber
demo page illustrating the expected behavior.Google's demo page outputs four sections:
Choose the relevant section of those four corresponding to the type of the bug you're reporting.
In a bug report:
libphonenumber-js
demo result (and provide a link to it).libphonenumber-js
demo, otherwise it's not considered a bug. If you don't agree with Google's demo result then create an issue in Google's repo instead. If they fix it in their library, I'll port the fix to this library.This library comes with TypeScript "typings". If you happen to find any bugs in those, create an issue.
One can use any npm CDN service, e.g. unpkg.com or jsdelivr.com
<script src="https://unpkg.com/libphonenumber-js@[version]/bundle/libphonenumber-[type].js"></script>
<script>
alert(new libphonenumber.AsYouType('US').input('213-373-4253'))
</script>
where [version]
is an npm package version range (for example, 1.x
or ^1.7.6
) and [type]
is the bundle type: min
, max
or mobile
.
Metadata is generated from Google's PhoneNumberMetadata.xml
by transforming XML into JSON and removing unnecessary fields. See metadata fields description.
Metadata can be accessed programmatically by using the exported Metadata
class.
First, create a Metadata
class instance:
import { Metadata } from 'libphonenumber-js'
const metadata = new Metadata()
Then, select a "numbering plan" (a country):
metadata.selectNumberingPlan('US')
After that, the following methods of metadata.numberingPlan
can be called:
leadingDigits(): string?
— Returns "leading digits" pattern.
possibleLengths(): number[]
— Returns a list of possible lengths of a national (significant) number.
IDDPrefix(): string
— Returns an International Direct Dialing prefix.
defaultIDDPrefix(): string?
— Returns a default International Direct Dialing prefix when there're multiple ones available.
Example:
import { Metadata } from 'libphonenumber-js'
const metadata = new Metadata()
metadata.selectNumberingPlan('US')
metadata.numberingPlan.leadingDigits() === undefined
metadata.numberingPlan.possibleLengths() === [10]
metadata.numberingPlan.IDDPrefix() === '011'
metadata.numberingPlan.defaultIDDPrefix() === undefined
Using with custom metadata:
import { Metadata } from 'libphonenumber-js/core'
import min from 'libphonenumber-js/min/metadata'
// import max from 'libphonenumber-js/max/metadata'
// import mobile from 'libphonenumber-js/mobile/metadata'
const metadata = new Metadata(min)
As one can see, the Metadata
class is not documented much. Partially, that's because its usage is not necessarily encouraged, but it's still used, for example, in react-phone-number-input
to get "leading digits" for a country, or to get maximum phone number length for a country. Stick to the methods documented above, don't call any other methods. If you think there's a need to call any other methods, create a discussion issue.
This library comes prepackaged with three types of metadata.
Sometimes, if only a specific set of countries is needed in a project, and a developer really wants to reduce the resulting bundle size, say, by 50 kilobytes (even when including all regular expressions for validating phone number digits and detecting phone number type), then they can generate such custom metadata and pass it as the last argument to this library's "core" functions.
See generate custom metadata instructions.
metadata.custom.json
file with the "core" functions.metadata.custom.json
file with the legacy "custom" functions.Metadata should be re-generated each time the project is being deployed because Google constantly updates their metadata.
Google periodically releases new metadata with the changes described in the release notes. Sometimes those are minor non-breaking updates, sometimes those are major-version breaking updates.
Metadata update process is automated through an "autoupdate" script: see autoupdate.cmd
(Windows) or autoupdate.sh
(Linux/macOS). The script detects changes to PhoneNumberMetadata.xml
in Google libphonenumber
's repo and if there are changes then it pulls the latest metadata, processes it, commits the changes to GitHub, builds a new version of the library and releases it to NPM. So this library's metadata is supposed to be up-to-date. I could set up this script to run automatically but on my Windows machine ssh-agent
doesn't work properly so I run the "autoupdate" script manually from time to time.
Also Google sometimes (very rarely) updates their code:
phonenumberutil.js
— parseNumber()
, formatNumber()
, isValidNumber()
, getNumberType()
AsYouTypeFormatter.java
— AsYouType
PhoneNumberMatcher.java
— findPhoneNumbersInText()
The latest sync-up was on Aug 14th, 2024.
After cloning this repo, ensure dependencies are installed by running:
npm install
This module is written in ES6 and uses Babel for ES5 transpilation. Widely consumable JavaScript can be produced by running:
npm run build
Once npm run build
has run, you may import
or require()
directly from
node.
After developing, the full test suite can be evaluated by running:
npm test
Test coverage must remain at 100%:
npm run test-coverage
When you're ready to test your new functionality on a real project, you can run
npm pack
It will build
, test
and then create a .tgz
archive which you can then install in your project folder
npm install [module name with version].tar.gz
This component comes with a 100% code coverage.
To run tests:
npm test
To generate a code coverage report:
npm run test-coverage
The code coverage report can be viewed by opening ./coverage/lcov-report/index.html
.
If you like this library then you might also like:
react-phone-number-input
— A React
component for phone number input.javascript-time-ago
— An international human-readable past or future date formatter. Example: "2 days ago"
.react-time-ago
— A React
component for international human-readable formatting of past or future dates. Example: "2 days ago"
.read-excel-file
— A simple and easy-to-use *.xlsx
file reader (client-side or server-side).write-excel-file
— A simple and easy-to-use *.xlsx
file writer (client-side or server-side).flexible-json-schema
— A simple and easy-to-use *.json
schema data validator / parser.virtual-scroller
— A universal implementation of a "virtual scroller" infinite list scrolling component: only renders the rows that fit the screen bounds.Google's libphonenumber
is licensed under Apache 2.
Apache 2 does not require a derivative work of the software, or modifications to the original, to be distributed using the same license. Hence, this library is licensed under MIT, which is compatible with Apache 2.
The Apache license is terminated if the user sues anyone over patent infringement related to the software covered by the license. This condition is added in order to prevent patent litigations.