D7net
Home
Console
Upload
information
Create File
Create Folder
About
Tools
:
/
home
/
forge
/
ebrokers.online
/
node_modules
/
libphonenumber-js
/
Filename :
README.md
back
Copy
# libphonenumber-js [](https://www.npmjs.com/package/libphonenumber-js) [](https://www.npmjs.com/package/libphonenumber-js) [](https://coveralls.io/r/catamphetamine/libphonenumber-js?branch=master) A simpler and smaller rewrite of Google Android's [`libphonenumber`](https://github.com/google/libphonenumber/) library in javascript/TypeScript. Parse and format personal phone numbers. [See Demo](https://catamphetamine.gitlab.io/libphonenumber-js/) If you’re trying to build a React component with it, take a look at [`react-phone-number-input`](https://www.npmjs.com/package/react-phone-number-input). ## LibPhoneNumber Google's [`libphonenumber`](https://github.com/googlei18n/libphonenumber) is an ultimate phone number formatting and parsing library developed by Google for [Android](https://en.wikipedia.org/wiki/Android_(operating_system)) phones. It is written in C++ and Java, and, while it has an [official autogenerated javascript port](https://github.com/googlei18n/libphonenumber/tree/master/javascript), that port is tightly coupled to Google's `closure` javascript framework, and, when compiled into a [bundle](https://github.com/ruimarinho/google-libphonenumber), 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. <!-- That's what `libphonenumber-js` is about: I started off from scratch, decyphering Google's code and figuring out how this whole machinery works, through trial and error, with several years of hacking around, receiving bug reports from other developers — eventually, it has reached a state when it can be assumed production-ready. --> <!-- One part of me was curious about how all this phone number parsing and formatting machinery worked, and another part of me was curious if there was a way to reduce those 530 kilobytes to something more reasonable while also getting rid of all the unnecessary bulk and rewriting it all in pure javascript. The resulting library does everything a modern web application needs while maintaining a much smaller size of about 130 kilobytes. --> ## Differences from Google's `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). * 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"](https://www.tatango.com/blog/sms-short-codes-what-every-business-needs-to-know/) — short SMS-only numbers like `12345`. * Numbers starting with an `*`. For example, `*555` is used in New Zeland to report non-urgent traffic incidents. Or, in Israel, certain advertising numbers start with a `*`. * Australian [`13`-smart](https://github.com/catamphetamine/libphonenumber-js/issues/400) numbers, which are a "catchy" "short" form of regular "landline" numbers and are mainly used in [advertisement](https://www.youtube.com/watch?v=Y0HchzE-7rM). * 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-789` instead 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 `.country` to `"001"` when parsing ["non-geographic"](#non-geographic) phone numbers, like mobile satellite communications services. Instead, `.country` is set to `undefined` in those cases, and instead 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 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"](https://www.bandwidth.com/glossary/carrier-identification-code-cic/) when making such calls. Since `libphonenumber-js` is 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](https://issuetracker.google.com/issues/335892662) when Canadian numbers `+1310xxxx` wheren't considered possible. <!-- (Australia, Bolivia, Brazil, China, Colombia, Croatia, Faroe Islands, South Korea, Liechtenstein, Luxembourg, Venezuela) --> <!-- for (var code of Object.keys(metadata.countries)) { var country = metadata.countries[code] if (country.formats && country.formats.find(_ => _.domestic_carrier_code_formatting_rule)) { console.log(code) } } --> <!-- * Doesn't use ["carrier codes"](https://github.com/googlei18n/libphonenumber/blob/master/FALSEHOODS.md) 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](https://npmjs.org/) ```sh $ npm install libphonenumber-js --save ``` via [yarn](https://yarnpkg.com) ```sh $ yarn add libphonenumber-js ``` Alternatively, one could include it on a web page [directly](#cdn) via a `<script/>` tag. ## Use If you'd like to create an issue, see [bug reporting](#bug-reporting) instructions. <!-- ### Importing When using [Babel](https://babeljs.io/) or [`esm`](npmjs.com/package/esm) or [rollup.js](https://rollupjs.org/) or any other `import` transpiler: ```js import parsePhoneNumber, { isPossiblePhoneNumber, isValidPhoneNumber, AsYouType, findPhoneNumbersInText } from 'libphonenumber-js' ``` When using Node.js 14 and not using any of the above: ```js import parsePhoneNumber from 'libphonenumber-js' // or import libphonenumber from 'libphonenumber-js' const { default: parsePhoneNumber, isPossiblePhoneNumber, isValidPhoneNumber, AsYouType, findPhoneNumbersInText } = libphonenumber ``` When using Node.js < 14 and not using any of the above: ```js const libphonenumber = require('libphonenumber-js') const { default: parsePhoneNumber, isPossiblePhoneNumber, isValidPhoneNumber, AsYouType, findPhoneNumbersInText } = libphonenumber ``` https://gitlab.com/catamphetamine/libphonenumber-js/-/issues/42 --> ### Parse phone number <!-- _(new API)_ --> Parses a complete phone number. ```js 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' } ``` <!-- <details> <summary>Legacy API</summary> ```js import { parseNumber } from 'libphonenumber-js' parseNumber('Phone: 8 (800) 555 35 35.', 'RU') // Outputs: { country: 'RU', phone: '8005553535' } ``` </details> --> ### Format phone number Formats a complete phone number. <!-- _(new API)_ --> ```js 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' } ``` <!-- <details> <summary>Legacy API</summary> ```js import { formatNumber } from 'libphonenumber-js' formatNumber('+12133734253', 'INTERNATIONAL') // Outputs: '+1 213 373 4253' formatNumber('+12133734253', 'NATIONAL') // Outputs: '(213) 373-4253' formatNumber({ country: 'US', phone: '2133734253' }, 'INTERNATIONAL') // Outputs: '+1 213 373 4253' formatNumber({ country: 'US', phone: '2133734253' }, 'NATIONAL') // Outputs: '(213) 373-4253' ``` </details> --> ### "As You Type" formatter Parses and formats an incomplete phone number. ```js 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. ```js 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. <!-- _(new API)_ --> ```js 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 kilobytes` in size (`libphonenumber-js/metadata.min.json` file) * Choose this when: * You don't need to detect phone number type — "fixed line", "mobile", etc — via [`.getType()`](#gettype-string) <!-- * Because the `min` metadata doesn't include (for most countries anyway) the regular expressions that're required for phone number type detection. --> * You're fine with just validating phone number length via [`.isPossible()`](#ispossible-boolean) and you don't need to strictly validate phone number digits via [`.isValid()`](#isvalid-boolean) <!-- * Because the `min` metadata doesn't include (for most countries anyway) the regular expressions that're required for phone number digits validation. --> * `max` — The complete metadata set * Is about `145 kilobytes` in size (`libphonenumber-js/metadata.max.json` file) * Choose this when: * The basic [`.isPossible()`](#ispossible-boolean) phone number length check is not enough for you and you need the strict phone number digits validation via [`.isValid()`](#isvalid-boolean) * You need to detect phone number type — "fixed line", "mobile", etc — via [`.getType()`](#gettype-string) * `mobile` — The complete metadata set for dealing with mobile numbers _only_ * Is about `95 kilobytes` in size (`libphonenumber-js/metadata.mobile.json` file) * Choose this when: * You need `max` metadata 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 return `false` for them, or `.getType()` might potentially return `undefined`. Choose one from the above and then simply `import` the functions from the relevant sub-package: * `min` — `libphonenumber-js/min`, or just `libphonenumber-js`, since it's the default. * `max` — `libphonenumber-js/max` * `mobile` — `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"](#custom-metadata) 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 ### Country code A "country code" is a [two-letter ISO country code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) (like `"US"`). <!-- or a special `001` country code used for ["non-geographic entities"](#non-geographic) (as per [Google's libphonenumber library](https://github.com/googlei18n/libphonenumber/blob/0068d861a68d3d4612f7bf8646ab844dd3cefce5/java/libphonenumber/test/com/google/i18n/phonenumbers/RegionCode.java#L23-L24)). --> This library supports all [officially assigned](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) ISO alpha-2 country codes, plus a few extra ones: `AC` ([Ascension Island](https://en.wikipedia.org/wiki/Ascension_Island)), `TA` ([Tristan da Cunha](https://en.wikipedia.org/wiki/Tristan_da_Cunha)), `XK` ([Kosovo](https://en.wikipedia.org/wiki/Kosovo)). <!-- var countries = [] for (const code of Object.keys(country_calling_codes)) { countries = countries.concat(country_calling_codes[code]) } console.log(countries.length) --> To check whether a country code is supported, use [`isSupportedCountry()`](#issupportedcountrycountry-string-boolean) function. ### Non-geographic There're several calling codes that don't belong to any country: * `+800` — [Universal International Toll Free Number](https://en.wikipedia.org/wiki/Toll-free_telephone_number) * `+808` — [Universal International Shared Cost Number](https://en.wikipedia.org/wiki/Shared-cost_service) * `+870` — [Inmarsat Global Limited](https://en.wikipedia.org/wiki/Inmarsat) * `+878` — [Universal Personal Telecommunications](https://en.wikipedia.org/wiki/Universal_Personal_Telecommunications) * `+881` — [Global Mobile Satellite System](https://en.wikipedia.org/wiki/Global_Mobile_Satellite_System) * `+882` and `+883` — [International Networks](https://en.wikipedia.org/wiki/International_Networks_(country_code)) * `+888` — [United Nations Office for the Coordination of Humanitarian Affairs](https://en.wikipedia.org/wiki/United_Nations_Office_for_the_Coordination_of_Humanitarian_Affairs#International_Dialing_Code) * `+979` — [International Premium Rate Service](https://en.wikipedia.org/wiki/International_Premium_Rate_Service) Such phone numbering plans are called "non-geographic", and their phone numbers' `country` is `undefined`. ### 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 the `0` at the start of the national number — it's because in France they [add](https://en.wikipedia.org/wiki/Telephone_numbers_in_France) `0` "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](#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` Several countries could share the same "country calling code". For example, [NANPA](https://en.wikipedia.org/wiki/North_American_Numbering_Plan) countries like USA and Canada share the same `1` country calling code. ## 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`. ```js 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`](#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](#country-calling-code), etc. Available `options`: * `defaultCountry: string` — Default [country](#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 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"](#non-geographic) which by nature don't have a country code, making the `defaultCountry` option unusable. * `extract: boolean` — Defines the ["strictness"](#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 an 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 an exact error: ```js 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 } } ``` <details> <summary>Possible errors</summary> * `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). </details> ###### Analogy: `parsePhoneNumberWithError()` is analogous to `new PhoneNumberUtil().parse()` in Google's `libphonenumber`. <!-- Analogy: `parsePhoneNumber()` is analogous to `new PhoneNumberUtil().parse()` in Google's `libphonenumber` with a difference that instead of throwing an error it simply returns `undefined`, which is more developer-friendly in my opinion. --> #### 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. ```js // 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 }) === PhoneNumber ``` ### `PhoneNumber` `PhoneNumber` class represents a complete phone number. `PhoneNumber` class instance is returned from [`parsePhoneNumber()`](#parsephonenumberstring-defaultcountry-string--options-object-phonenumber) function, or it could also be constructed manually from a number in [`E.164`](https://en.wikipedia.org/wiki/E.164) format: ```js const phoneNumber = new PhoneNumber('+12133734253') // (optional) Add a phone number extension. phoneNumber.setExt('1234') ``` <!-- `PhoneNumber` class constructor accepts two arguments: `country`/`countryCallingCode` and `nationalNumber`. Also `metadata`. ```js const phoneNumber = new PhoneNumber('RU', '8005553535', metadata) ``` --> `PhoneNumber` class instance has the following properties: * `number: string` — The phone number in [`E.164`](https://en.wikipedia.org/wiki/E.164) format. Example: `"+12133734253"`. * `countryCallingCode: string` — The [country calling code](#country-calling-code). Example: `"1"`. * `nationalNumber: string` — The [national (significant) number](#national-significant-number). Example: `"2133734253"`. * `country: string?` — The [country code](#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 particular one of them. Or when a number belongs to a [non-geographic numbering plan](#non-geographic). * `ext: string?` — The [phone number extension](https://en.wikipedia.org/wiki/Extension_(telephone)), if any. Example: `"1234"`. * `carrierCode: string?` — The ["carrier code"](https://www.voip-info.org/carrier-identification-codes/), 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. <!-- * `countryCallingCodeSource: string` — How the [country calling code](#country-calling-code) was obtained for this phone number. --> <!-- * `FROM_NUMBER_WITH_PLUS_SIGN` — The country_code is derived based on a phone number with a leading "+", e.g. the French number "+33 1 42 68 53 00". --> <!-- * `FROM_NUMBER_WITHOUT_PLUS_SIGN` — The country_code is derived based on a phone number without a leading "+", e.g. the French number "33 1 42 68 53 00" when defaultCountry is supplied as France. --> <!-- * `FROM_DEFAULT_COUNTRY` — The country_code is derived NOT based on the phone number itself, but from the defaultCountry parameter provided in the parsing function by the clients. This happens mostly for numbers written in the national format (without country code). For example, this would be set when parsing the French number "01 42 68 53 00", when defaultCountry is supplied as France. --> `PhoneNumber` class instance provides the following methods: #### `setExt(ext: string)` Adds a [phone number extension](https://en.wikipedia.org/wiki/Extension_(telephone)) to a phone number. ```js 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 `format`s: * `NATIONAL` — Example: `"(213) 373-4253"` * `INTERNATIONAL` — Example: `"+1 213 373 4253"` * [`E.164`](https://en.wikipedia.org/wiki/E.164) — Example: `"+12133734253"` * [`RFC3966`](https://www.ietf.org/rfc/rfc3966.txt) (the phone number URI) — Example: `"tel:+12133734253;ext=123"` * `IDD` — ["Out-of-country" dialing](https://wikitravel.org/en/International_dialling_prefix) 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 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). Pass `nationalPrefix: false` option to force formatting without a national prefix. Examples: ```js 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`](#min-vs-max-vs-mobile-vs-core) 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. <details> <summary>See an example illustrating different results when using <code>/min</code> vs <code>/max</code> vs <code>/mobile</code> 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 ``` </details> #### See ["Using phone number validation feature"](#using-phone-number-validation-feature) for choosing between `isPossible()` and `isValid()`. <!-- #### `isValidForRegion(country)` Is just an alias for `this.isValid() && this.country === country`. https://github.com/googlei18n/libphonenumber/blob/master/FAQ.md#when-should-i-use-isvalidnumberforregion --> <!-- See the comments for `validateLength()` method in `PhoneNumber.js` class for the rationale on why is this method not part of the public API. #### `validateLength(): string?` Checks if the phone number length is valid. If it is, then nothing is returned. Otherwise, a rejection reason is returned. ```js parsePhoneNumber('444 1 44', 'TR').validateLength() === 'TOO_SHORT' parsePhoneNumber('444 1 444', 'TR').validateLength() === undefined // Length is valid. parsePhoneNumber('444 1 4444', 'TR').validateLength() === 'INVALID_LENGTH' parsePhoneNumber('444 1 44444', 'TR').validateLength() === 'INVALID_LENGTH' parsePhoneNumber('444 1 444444', 'TR').validateLength() === undefined // Length is valid. parsePhoneNumber('444 1 4444444444', 'TR').validateLength() === 'TOO_LONG' ``` <details> <summary>Possible rejection reasons</summary> * `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. </details> ###### `validateLength()` is just a more detailed version of `isPossible()` — if the phone number length is invalid, it returns the actual reason: `TOO_SHORT`, `TOO_LONG`, etc. --> #### `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`](#min-vs-max-vs-mobile-vs-core) 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. <details> <summary>The list of possible return values</summary> #### * `MOBILE` — Cellphones. * `FIXED_LINE` — Stationary phones. * `FIXED_LINE_OR_MOBILE` — Could be `MOBILE` or `FIXED_LINE`. * [`PREMIUM_RATE`](https://en.wikipedia.org/wiki/Premium-rate_telephone_number) — Callers are charged by call or per minute. SMS text messages are also subject to charge. * [`TOLL_FREE`](https://en.wikipedia.org/wiki/Toll-free_telephone_number) — Free to call from anywhere. * [`SHARED_COST`](https://en.wikipedia.org/wiki/Shared-cost_service) — "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`](https://en.wikipedia.org/wiki/Voice_over_IP) — "IP telephony". Calls are made over the Internet rather than via the conventional telephone-only lines. * [`PERSONAL_NUMBER`](https://en.wikipedia.org/wiki/Personal_Communications_Service) — Phones connected by satellites. * [`PAGER`](https://en.wikipedia.org/wiki/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`](https://www.pta.gov.pk/media/num/faqs_110208.pdf) — "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`](https://www.easytechjunkie.com/what-is-a-voicemail-access-number.htm) — "A voicemail access number is a telephone number provided by a [voicemail](https://en.wikipedia.org/wiki/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". </details> #### <details> <summary>See an example illustrating different results when using <code>/min</code> vs <code>/max</code> vs <code>/mobile</code> 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' ``` </details> #### `isNonGeographic(): boolean` Returns `true` if the number belongs to a ["non-geographic numbering plan"](#non-geographic). #### `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. ```js isPossiblePhoneNumber('8 (888) 888-88-88', 'RU') === true isPossiblePhoneNumber('+12223333333') === true ``` For the description of the `defaultCountry?: string | options?: object` argument, see [`parsePhoneNumber()`](#parsephonenumberstring-defaultcountry-string--options-object-phonenumber) function description. This function is just a shortcut for a two-step process of ["strictly"](#strictness) 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. ```js 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()`](#parsephonenumberstring-defaultcountry-string--options-object-phonenumber) function description. This function is just a shortcut for a two-step process of ["strictly"](#strictness) parsing a phone number and then calling `.isValid()`. See ["Using phone number validation feature"](#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: ```js 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. <details> <summary>Possible rejection reasons</summary> * `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. </details> ###### ```js 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()`](#parsephonenumberstring-defaultcountry-string--options-object-phonenumber) function description. This function is just a more detailed version of `isPossiblePhoneNumber()` for those who [asked](https://github.com/catamphetamine/libphonenumber-js/issues/406) for a more specific rejection reason. <!-- This function is just a shortcut for a two-step process of ["strictly"](#strictness) parsing a phone number and then calling `.validateLength()`. --> The phone number is parsed ["strictly"](#strictness) 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()`](#parsephonenumberstring-defaultcountry-string--options-object-phonenumber) 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. ```js 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`](#phonenumber). Will return `undefined` if no [national (significant) number](#national-significant-number) digits have been entered so far, or if no `defaultCountry`/`defaultCallingCode` has been specified and the user enters a phone number in national format (without a `+`). * `getNumberValue(): string?` — Returns the phone number in [`E.164`](https://en.wikipedia.org/wiki/E.164) format. For example, for default country `"US"` and input `"(222) 333-4444"` it will return `"+12223334444"`. Will return `undefined` if 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 by `x`-es. Returns an empty string if no phone number characters have been input. ```js // 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"](#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"](#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](#country-code) of the phone number. Returns `undefined` for ["non-geographic"](#non-geographic) phone numbering plans. Returns `undefined` if 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` — Returns `true` if the phone number is "possible". Is just a shortcut for [`getNumber()?.isPossible()`](#ispossible-boolean). * `isValid(): boolean` — Returns `true` if the phone number is "valid". Is just a shortcut for [`getNumber()?.isValid()`](#isvalid-boolean). <details> <summary>Legacy API (before version <code>1.6.0</code>)</summary> #### For legacy API (before version `1.6.0`) the formatter instance provides the following getters: * `country: string?` — Phone number [country](#country-code). 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](#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' ``` </details> #### "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: string` * `defaultCallingCode: string` For the description of `defaultCountry` or `defaultCallingCode`, see [`parsePhoneNumber()`](#parsephonenumberstring-defaultcountry-string--options-object-phonenumber) function description. ```js 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()`) <details> <summary>Legacy API (before version <code>1.6.0</code>) 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 // }] ``` </details> #### 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()`) <details> <summary>Asynchronous search example using <code>searchPhoneNumbersInText()</code></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() ``` </details> #### 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](#country-code). Returns an instance of [`PhoneNumber`](#phonenumber) class. Will return `undefined` if `country` doesn't exist or isn't supported by this library. ```js 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 [country](#country-code) is supported by this library. ```js isSupportedCountry('RU') === true isSupportedCountry('XX') === false ``` ### getCountries(): string[] Returns a list of supported countries. <!-- (excluding `"001"` that stands for ["non-geographic entity"](#non-geographic)). --> ```js getCountries() === ["AC", "AD", ...] ``` ### getCountryCallingCode(country: string): string Returns [country calling code](#country-calling-code) for a [country](#country-code). Will throw an error if `country` doesn't exist or isn't supported by this library. ```js getCountryCallingCode('RU') === '7' getCountryCallingCode('IL') === '972' ``` ### getExtPrefix(country: string): string Returns phone number extension prefix for a given [country](#country-code). If no custom ext prefix is defined for a `country` then the default `" ext. "` prefix is returned. ```js 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](https://gitlab.com/catamphetamine/react-phone-number-input/)). ```js parseDigits('x123') === '123' parseDigits('٤٤٢٣') === '4423' ``` ### parseIncompletePhoneNumber(text: string): string Parses phone number characters (`+` and digits). Can be used for building a phone number input component (e.g. [react-phone-number-input](https://gitlab.com/catamphetamine/react-phone-number-input/)). ```js parseIncompletePhoneNumber('8 (800) 555') === '8800555' parseIncompletePhoneNumber('+7 800 555') === '+7800555' parseIncompletePhoneNumber('+٤٤٢٣٢٣٢٣٤') === '+442323234' ``` ### parsePhoneNumberCharacter(character, prevParsedCharacters?, eventListener?) 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`](https://gitlab.com/catamphetamine/react-phone-number-input) with [`input-format`](https://gitlab.com/catamphetamine/input-format). Frankly speaking, that's the only reason why this function is exported. Other developers, perhaps, should just ignore it and use `parseIncompletePhoneNumber()` instead because it's much simpler. ```js // 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 `eventListener` argument is a function of `eventName: string` argument. It will be called with an `"end"` argument 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 could return `"+1234"` rather than `"+12345678"`. ### formatIncompletePhoneNumber(value: string, defaultCountry?: string | options?: object): string 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`](https://en.wikipedia.org/wiki/E.164) format. For the description of the `defaultCountry?: string | options?: object` argument, see [`parsePhoneNumber()`](#parsephonenumberstring-defaultcountry-string--options-object-phonenumber) 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](https://gitlab.com/catamphetamine/react-phone-number-input/)). ```js // 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' ``` ## Legacy API <details> <summary>Legacy API (before version <code>1.6.0</code>): <code>parse()</code>, <code>parseNumber()</code>, <code>format()</code>, <code>formatNumber()</code>, <code>isValidNumber()</code>, <code>getNumberType()</code>.</summary> ### parseNumber(text, [defaultCountry], [options]) _(previously called `parse()`)_ _(legacy API)_ Attempts to parse a phone number from `text`. If [`defaultCountry`](#country-code) is passed then it's gonna be the default country for parsing non-international phone numbers. Returns `{ country, phone, ext }` object where * `country` is a [country code](#country-code). * `phone` is a [national (significant) number](#national-significant-number). * `ext` is a [phone number extension](https://en.wikipedia.org/wiki/Extension_(telephone)). If the phone number supplied isn't valid then an empty object `{}` is returned. <details> <summary>Examples</summary> ```js // Parses international numbers. parseNumber('+1 213 373 4253') === { country: 'US', phone: '2133734253' } parseNumber('Phone: +1-213-373-4253.') === { country: 'US', phone: '2133734253' } parseNumber('+12133734253') === { country: 'US', phone: '2133734253' } // Parses national numbers provided a default country. parseNumber('Phone: (213) 373-4253.', 'US') === { country: 'US', phone: '2133734253' } // Parses phone number extensions. parseNumber('(213) 373-4253 ext. 123', 'US') === { country: 'US', phone: '2133734253', ext: '123' } // Parses RFC 3966 phone number URIs. parseNumber('tel:+78005553535;ext=123') === { country: 'RU', phone: '8005553535', ext: '123' } ``` If the phone number supplied isn't valid then an empty object `{}` is returned. ```js parseNumber('+1 111 111 1111') === {} parseNumber('(111) 111-1111', 'US') === {} parseNumber('abcdefg') === {} ``` </details> #### Available `options`: * `defaultCountry : string` — Same as the `defaultCountry` argument. * `extended : boolean` — If set to `true` then `parseNumber()` will attempt to parse even a remotely hypothetical phone number even if it is considered "invalid". <details> <summary><code>{ extended: true }</code> documentation and examples</summary> The result of "extended" parsing is an object where * `country` is a [country code](#country-code). * `phone` is a [national (significant) number](#national-significant-number). * `ext` is a [phone number extension](https://en.wikipedia.org/wiki/Extension_(telephone)). * `countryCallingCode` is a [country calling code](#country-calling-code). * [`carrierCode`](https://www.voip-info.org/carrier-identification-codes/)s are only used in Colombia and Brazil and only when dialing within those countries from a mobile phone to a fixed line number. * `valid: boolean` — whether it's a "valid" (real) phone number. * `possible: boolean` — a phone number is considered "possible" when it fits the phone number length rules for a given country. E.g. for US national (significant) number regexp is `[2-9]\d{9}` and possible national (significant) number length is `10` so a phone number `(111) 111-1111` is not a "valid" number because it doesn't match the US national (significant) number regexp but it is a "possible" number because it's `10` digits long. * Some or all of these properties may be absent from the result object. ```js // If the number is valid. parseNumber('Phone: (213) 373-4253.', 'US', { extended: true }) === { country: 'US', phone: '2133734253', ext: undefined, countryCallingCode: 1, carrierCode: undefined, valid: true, possible: true } // If the number is not "valid" but "possible". parseNumber('(111) 111-1111', 'US', { extended: true }) === { country: 'US', phone: '1111111111', ext: undefined, countryCallingCode: 1, carrierCode: undefined, valid: false, possible: true } // If the number is not "valid" but "possible" // and country can't be derived from it. // (e.g. can't tell if it's a US number or a Canadian number) parseNumber('+1 111 111 1111', { extended: true }) === { country: undefined, phone: '1111111111', ext: undefined, countryCallingCode: 1, carrierCode: undefined, valid: false, possible: true } // If the number is not "possible" (invalid length). parseNumber('(213) 373', 'US', { extended: true }) === { country: 'US', phone: '213373', ext: undefined, countryCallingCode: 1, carrierCode: undefined, valid: false, possible: false } // In some cases if the number is extremely not "possible" // then an empty object `{}` is returned. // // Too short (or too long) for any country's phone number. parseNumber('1', 'US', { extended: true }) === {} // Non-existent country calling code. parseNumber('+210', { extended: true }) === {} // No phone number found. parseNumber('abcdefg', 'US', { extended: true }) === {} ``` The "extended" parsing mode is the default behaviour of the original Google's `libphonenumber`: it still returns parsed data even if the phone number being parsed is not considered valid (but is kinda "possible"). I guess this kind of behaviour is better for crawling websites for phone numbers because when mining "big data" it is better to extract all possible info rather than discard some pieces of it prematurely, e.g. when national (significant) number regexp for some country gets outdated which might very well happen because phone numbering plans are changing constantly around the world. Maybe after all it would make sense to make the "extended" parsing mode the default one in the next major version. I guess it would. </details> #### <details> <summary>Also parses IDD-prefixed phone numbers</summary> Sometimes users icorrectly input phone numbers in ["out-of-country" dialing](https://wikitravel.org/en/International_dialling_prefix) (IDD-prefixed) format instead of the proper international phone number format (the "+" notation). In such cases `parseNumber()` will attempt to parse such IDD-prefixed numbers if "default country" is provided: ```js // International format. parseNumber('+61 2 3456 7890') === { country: 'AU', phone: '234567890' } // IDD-prefixed format. parseNumber('011 61 2 3456 7890', 'US') === { country: 'AU', phone: '234567890' } ``` </details> ### formatNumber(number, format, [options]) _(previously called `format()`)_ _(legacy API)_ Formats a `number` into a string according to a `format`. Available `format`s and `options` are the same as for [`PhoneNumber.format(format)`](#formatformat-string-options). The `number` argument must be either a result of `parseNumber()` function call (to strip national prefix) or an E.164 phone number string (e.g. `+12133734253`). <details> <summary>Examples</summary> ```js // Formats E.164 phone numbers. formatNumber('+12133734253', 'NATIONAL') === '(213) 373-4253' formatNumber('+12133734253', 'INTERNATIONAL') === '+1 213 373 4253' // Formats E.164 phone numbers when // they're not "valid" but still "possible". formatNumber('+11111111111', 'NATIONAL') === '(111) 111-1111' formatNumber('+11111111111', 'INTERNATIONAL') === '+1 111 111 1111' // Formats E.164 phone numbers when // they're not "valid" and not "possible" (invalid length). formatNumber('+11111', 'NATIONAL') === '1111' formatNumber('+11111', 'INTERNATIONAL') === '+1 1111' // Formats a result of `parseNumber()` function call. const parsedNumber = parseNumber('2133734253', 'US') formatNumber(parsedNumber, 'NATIONAL') === '(213) 373-4253' formatNumber(parsedNumber, 'INTERNATIONAL') === '+1 213 373 4253' // Formats a result of `parseNumber()` function call in "extended" mode // when it's not a "valid" number but is still a "possible" one. const possibleNumber = parseNumber('+11111111111', { extended: true }) formatNumber(possibleNumber, 'NATIONAL') === '(111) 111-1111' formatNumber(possibleNumber, 'INTERNATIONAL') === '+1 111 111 1111' // Formats a result of `parseNumber()` function call in "extended" mode // when it's neither a "valid" number nor a "possible" one (invalid length). const possibleNumber = parseNumber('+11111', { extended: true }) formatNumber(possibleNumber, 'NATIONAL') === '1111' formatNumber(possibleNumber, 'INTERNATIONAL') === '+1 1111' // Formats phone number extensions. formatNumber({ country: 'US', phone: '2133734253', ext: '123' }, 'NATIONAL') === '(213) 373-4253 ext. 123' // When given an object not having `phone` property // (e.g. a empty object `{}`) it will throw. formatNumber({}) throws Error ``` </details> ### getNumberType(number, [defaultCountry]) _(legacy API)_ See the description for [`PhoneNumber.getType()`](#gettype-string). The `number` argument can be either a result of the `parseNumber()` function call — `{ country, phone }` — or a string (phone number digits only) possibly accompanied with the second `defaultCountry` argument. <details> <summary>Examples</summary> ```js getNumberType('+79160151539') === 'MOBILE' getNumberType('9160151539', 'RU') === 'MOBILE' getNumberType({ phone: '9160151539', country: 'RU' }) === 'MOBILE' ``` </details> ### isValidNumber(number, [defaultCountry]) _(legacy API)_ Checks if a phone number is valid, the validation is more strict than `parseNumber()`. The `number` argument can be either a result of the `parseNumber()` function call — `{ country, phone }` — or a string (phone number digits only) possibly accompanied with the second `defaultCountry` argument. <details> <summary>Examples</summary> ```js isValidNumber('+12133734253') === true isValidNumber('+1213373') === false isValidNumber('2133734253', 'US') === true isValidNumber('21337', 'US') === false isValidNumber({ phone: '2133734253', country: 'US' }) === true ``` </details> #### <details> <summary>The difference between using <code>parseNumber()</code> and <code>isValidNumber()</code></summary> The difference between using `parseNumber()` and `isValidNumber()` for phone number validation is that `isValidNumber()` also checks the precise regular expressions of possible phone numbers for a country. For example, for Germany `parseNumber('123456', 'DE')` would return `{ country: 'DE', phone: '123456' }` because this phone number matches the general phone number rules for Germany (basic length check, etc). But, if the metadata is compiled with `--extended` (or relevant `--types`) flag (see [Custom metadata](#custom-metadata) section of this document) then `isValidNumber()` is gonna use those precise regular expressions for extensive validation and `isValid('123456', 'DE')` will return `false` because the phone number `123456` doesn't actually exist in Germany. This is how it is implemented in the original Google's [`libphonenumber`](https://static.javadoc.io/com.googlecode.libphonenumber/libphonenumber/8.9.1/com/google/i18n/phonenumbers/PhoneNumberUtil.html#parse-java.lang.CharSequence-java.lang.String-): `parseNumber()` parses phone numbers and loosely validates them while `isValidNumber()` validates phone numbers precisely (provided the precise regular expressions are included in metadata). The precise regular expressions aren't included in the default metadata because that would cause the default metadata to grow twice in its size: the complete ("full") metadata size is about 145 kilobytes while the reduced ("default") metadata size is about 77 kilobytes. Hence in the default configuration `isValidNumber()` performs absolutely the same "lite" validation as `parseNumber()`. For enabling extensive phone number validation the simplest way is to import functions from `libphonenumber-js/custom` module and supply them with `libphonenumber-js/metadata.max.json`. For generating custom metadata see the instructions provided in the [Custom metadata](#custom-metadata) section of this document. </details> #### <details> <summary><code>isValidNumberForRegion()</code></summary> The optional `defaultCountry` argument is the _default_ country, i.e. it does not restrict to just that country, e.g. in those cases where several countries share the same phone numbering rules (NANPA, Britain, etc). For example, even though the number `07624 369230` belongs to the Isle of Man ("IM" country code) calling `isValidNumber('07624369230', 'GB')` still returns `true` because the country is not restricted to `GB`, it's just that `GB` is the default one for the phone numbering rules. For restricting the country, see `isValidNumberForRegion()`, though restricting a country [might not be a good idea](https://github.com/googlei18n/libphonenumber/blob/master/FAQ.md#when-should-i-use-isvalidnumberforregion). ```js // Even though '07624 369230' number belongs to the Isle of Man ("IM") // the `defaultCountry` argument "GB" still works here because // "GB" and "IM" both share the same phone numbering rules ("+44"). isValidNumber('07624369230', 'GB') === true isValidNumber('07624369230', 'IM') === true // Imposing country restrictions. isValidNumberForRegion('07624369230', 'GB') === false isValidNumberForRegion('07624369230', 'IM') === true ``` </details> </details> ## Using phone number validation feature I personally don't use strict phone number validation feature. The rationale is that telephone numbering plans can and sometimes do change, meaning that [`PhoneNumber.isValid()`](#isvalid-boolean) 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` that was used when building the website. Whenever there's a "business requirement" to validate phone number input, I prefer using [`PhoneNumber.isPossible()`](#ispossible-boolean) instead of [`PhoneNumber.isValid()`](#isvalid-boolean), 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()`](#isvalid-boolean) — maybe in your case it would make sense. ## React If you’re trying to build a React component with this library, take a look at [`react-phone-number-input`](https://www.npmjs.com/package/react-phone-number-input). ## GitHub Repository Status On March 9th, 2020, GitHub, Inc. silently [banned](https://medium.com/@catamphetamine/how-github-blocked-me-and-all-my-libraries-c32c61f061d3) my account — erasing all my repos, issues and comments, even in my employer's private repos — without any notice or explanation. Because of that, all source codes had to be promptly moved to GitLab. The [GitHub repo](https://github.com/catamphetamine/libphonenumber-js) is now only used as a backup (although you can still "star" it), and the primary repo is now the [GitLab one](https://gitlab.com/catamphetamine/libphonenumber-js). For users' convenience, issues can be reported in both places. <!-- ## Node ES Modules This package currently [doesn't provide](https://gitlab.com/catamphetamine/libphonenumber-js/-/tree/master/exports) Node 14+ ES Modules exports, but that shouldn't be an issue because Node.js seems to [support](https://gitlab.com/catamphetamine/libphonenumber-js/-/issues/42) importing from "legacy" packages just fine. --> ## Bug reporting This library is a simpler rewrite of Google's [`libphonenumber`](https://github.com/google/libphonenumber/blob/master/java/libphonenumber/) library. Basically, it mimicks Google's library behavior. Hence, as long as this library's [demo page](https://catamphetamine.gitlab.io/libphonenumber-js/) and Google's library [demo page](https://libphonenumber.appspot.com/) exhibit the same behavior, it's not considered a bug, regardless of whether that behavior contradicts any new changes in telephone numbering plans, etc. In that case, your only option would be to [report the issue to Google](https://github.com/google/libphonenumber/blob/master/CONTRIBUTING.md) directly. That being said, if the two demo pages exhibit different behavior and it's not caused by the intentional [differences](#differences-from-googles-libphonenumber), then it would be considered a valid case for reporting an issue. When reporting issues related to: * Parsing numbers * Validating numbers * Formatting numbers * "As You Type" formatter one must provide two links: * A link to the [demo page](https://catamphetamine.gitlab.io/libphonenumber-js/) illustrating the supposedly incorrect behavior. * A link to [Google's `libphonenumber` demo page](https://libphonenumber.appspot.com/) illustrating the expected behavior. Google's demo page output is divided into [four sections](https://libphonenumber.appspot.com/phonenumberparser?number=438331999&country=AU): * "Parsing Result" * "Validation Results" * "Formatting Results" * "AsYouTypeFormatter Results" Depending the type of bug you're reporting, mention the relevant section of the demo page output in your ticket. When writing a bug report: * First, describe the observed `libphonenumber-js` demo result (and provide a link to it). * Second, describe the observed Google's demo result (and provide a link to it). * The described observed result of Google's demo must be different from the described observed result of `libphonenumber-js` demo, otherwise it's not considered a bug. If you don't agree with Google's demo result then [report it to Google](https://github.com/google/libphonenumber/blob/master/CONTRIBUTING.md) directly instead. If they fix it in their library, I'll port the fix to this library. <!-- Phone number validation bugs should **only** be reported if they appear when using [custom metadata functions](#custom-metadata) fed with `metadata.max.json` because by default all functions in this library use the reduced metadata set which results in looser validation than the original Google `libphonenumber`'s. The [demo page](https://catamphetamine.gitlab.io/libphonenumber-js/) also uses the reduced metadata set and therefore its validation is also looser than the original Google `libphonenumber`'s. There is also a possibility of this library's demo metadata being outdated, or this library's metadata lagging behind Google's (I have to update it manually from time to time due to `ssh-agent` not working properly on Windows). --> <!-- When reporting `findPhoneNumbersInText()` bugs, one should know that `findPhoneNumbersInText()` code was ported from [Google's Java code](https://github.com/googlei18n/libphonenumber/blob/master/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberMatcher.java). I didn't write it myself, I just ported it. Therefore, it is unlikely that anyone other than Google would fix any bugs. --> <!-- https://codesandbox.io/s/damp-fast-26c7z?file=/src/index.ts --> ## CDN To include this library directly via a `<script/>` tag on a page, one can use any npm CDN service, e.g. [unpkg.com](https://unpkg.com) or [jsdelivr.com](https://jsdelivr.com) ```html <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`. <!-- ## Standalone For those who aren't using bundlers for some reason there's a way to build a standalone version of the library * `git clone https://gitlab.com/catamphetamine/libphonenumber-js.git` * `npm install` * `npm run build` * See the `bundle` folder for `libphonenumber-js.min.js` ```html <script src="/scripts/libphonenumber-js.min.js"></script> <script> alert(new libphonenumber.AsYouType('US').input('213-373-4253')) </script> ``` --> ## Metadata Metadata is generated from Google's [`PhoneNumberMetadata.xml`](https://github.com/googlei18n/libphonenumber/blob/master/resources/PhoneNumberMetadata.xml) by transforming XML into JSON and removing unnecessary fields. See [metadata fields description](https://gitlab.com/catamphetamine/libphonenumber-js/blob/master/METADATA.md). ### Programmatic access Metadata can be accessed programmatically by using the exported `Metadata` class. First, create a `Metadata` class instance: ```js import { Metadata } from 'libphonenumber-js' const metadata = new Metadata() ``` Then, select a ["numbering plan"](https://en.wikipedia.org/wiki/Telephone_numbering_plan) (a country): ```js metadata.selectNumberingPlan('US') ``` After that, the following methods of `metadata.numberingPlan` can be called: * `leadingDigits(): string?` — Returns ["leading digits"](https://gitlab.com/catamphetamine/libphonenumber-js/blob/master/METADATA.md#leading_digits) pattern. * `possibleLengths(): number[]` — Returns a list of [possible lengths](https://gitlab.com/catamphetamine/libphonenumber-js/blob/master/METADATA.md#possible_lengths) of a national (significant) number. * `IDDPrefix(): string` — Returns an [International Direct Dialing](https://gitlab.com/catamphetamine/libphonenumber-js/blob/master/METADATA.md#idd_prefix) prefix. * `defaultIDDPrefix(): string?` — Returns a [default International Direct Dialing](https://gitlab.com/catamphetamine/libphonenumber-js/blob/master/METADATA.md#default_idd_prefix) prefix when there're multiple ones available. Example: ```js 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: ```js 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](https://gitlab.com/catamphetamine/libphonenumber-js/-/blob/master/source/metadata.js) 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`](https://gitlab.com/catamphetamine/react-phone-number-input/-/blob/master/source/helpers/phoneInputHelpers.js) to get the "leading digits" for a country, or to get the maximum phone number length for a country. Stick to the methods documented above and don't call any other methods. If you think there's a need to call any other methods not mentioned above, create an issue with a discussion. <!-- Currently I have a script set up monitoring changes to `PhoneNumberMetadata.xml` in Google's repo and automatically releasing new versions of this library when metadata in Google's repo gets updated. So this library's metadata is supposed to be up-to-date. Still, in case the automatic metadata update script malfunctions some day, anyone can request metadata update via a Pull Request here on GitHub: --> <!-- In case I forget to run the "autoupdate" script for a long time anyone can request metadata update via a Pull Request here on GitHub: * Fork this repo * `npm install` * `npm run metadata:update:branch` * Submit a Pull Request to this repo from the `update-metadata` branch of your fork `npm run metadata:update:branch` command creates a new `update-metadata` branch, downloads the new [`PhoneNumberMetadata.xml`](https://github.com/googlei18n/libphonenumber/blob/master/resources/PhoneNumberMetadata.xml) into the project folder replacing the old one, generates JSON metadata out of the XML one, checks if the metadata has changed, runs the tests, commits the new metadata and pushes the commit to the remote `update-metadata` branch of your fork. Alternatively, a developer may wish to update metadata urgently, without waiting for a pull request approval. In this case just perform the steps described in the [Custom metadata](#customi-metadata) section of this document. --> ### Custom metadata This library comes prepackaged with [three types of metadata](#min-vs-max-vs-mobile-vs-core). 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, while still 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](https://gitlab.com/catamphetamine/libphonenumber-metadata-generator) instructions. <details> <summary>How to use the generated <code>metadata.custom.json</code> file with the "core" functions.</summary> #### Pass the `metadata` argument as the last one to the "core" functions. In ES6 that would be: ```js import _parsePhoneNumber, { findPhoneNumbersInText as _findPhoneNumbersInText, AsYouType as _AsYouType } from 'libphonenumber-js/core' import metadata from 'libphonenumber-js/max/metadata' function call(func, _arguments) { var args = Array.prototype.slice.call(_arguments) args.push(metadata) return func.apply(this, args) } export default function parsePhoneNumber() { return call(_parsePhoneNumber, arguments) } export function findPhoneNumbersInText() { return call(_findPhoneNumbersInText, arguments) } export function AsYouType(country) { return _AsYouType.call(this, country, metadata) } AsYouType.prototype = Object.create(_AsYouType.prototype, {}) AsYouType.prototype.constructor = AsYouType ``` And for [Common.js](https://auth0.com/blog/javascript-module-systems-showdown/) environment that would be: ```js var core = require('libphonenumber-js/core') var metadata = require('libphonenumber-js/max/metadata') function call(func, _arguments) { var args = Array.prototype.slice.call(_arguments) args.push(metadata) return func.apply(this, args) } function parsePhoneNumber() { return call(core.default, arguments) } exports = module.exports = parsePhoneNumber exports['default'] = parsePhoneNumber exports.findPhoneNumbersInText = function findPhoneNumbersInText() { return call(core.findPhoneNumbersInText, arguments) } exports.AsYouType = function AsYouType(country) { return core.AsYouType.call(this, country, metadata) } exports.AsYouType.prototype = Object.create(core.AsYouType.prototype, {}) exports.AsYouType.prototype.constructor = exports.AsYouType ``` </details> #### <details> <summary>Legacy: How to use the generated <code>metadata.custom.json</code> file with the legacy "custom" functions.</summary> #### Pass the `metadata` argument as the last one to the "custom" functions. In ES6 that would be: ```js import { parseNumber, formatNumber, isValidNumber, getNumberType, AsYouType } from 'libphonenumber-js/custom' import metadata from 'libphonenumber-js/max/metadata' parseNumber('+78005553535', metadata) formatNumber({ phone: '8005553535', country: 'RU' }, metadata) isValidNumber('+78005553535', metadata) getNumberType('+78005553535', metadata) new AsYouType('RU', metadata).input('+78005553535') ``` And for [Common.js](https://auth0.com/blog/javascript-module-systems-showdown/) environment that would be: ```js var custom = require('libphonenumber-js/custom') var metadata = require('libphonenumber-js/max/metadata') exports.parseNumber = function parseNumber() { var parameters = Array.prototype.slice.call(arguments) parameters.push(metadata) return custom.parseNumber.apply(this, parameters) } exports.formatNumber = function formatNumber() { var parameters = Array.prototype.slice.call(arguments) parameters.push(metadata) return custom.formatNumber.apply(this, parameters) } exports.isValidNumber = function isValidNumber() { var parameters = Array.prototype.slice.call(arguments) parameters.push(metadata) return custom.isValidNumber.apply(this, parameters) } exports.getNumberType = function isValidNumber() { var parameters = Array.prototype.slice.call(arguments) parameters.push(metadata) return custom.getNumberType.apply(this, parameters) } exports.AsYouType = function AsYouType(country) { custom.AsYouType.call(this, country, metadata) } exports.AsYouType.prototype = Object.create(custom.AsYouType.prototype, {}) exports.AsYouType.prototype.constructor = exports.AsYouType ``` </details> ###### Note that if you'll be using your own "custom" metadata then you're responsible for keeping it up-to-date because Google regularly updates their metadata. <!-- ## To do --> <!-- ## Automatic metadata update setup Create a daily (24 * 60 * 60) `launchd` job http://alvinalexander.com/mac-os-x/mac-osx-startup-crontab-launchd-jobs ```sh mkdir /Users/kuchumovn/work/libphonenumber-js-autoupdate git clone https://gitlab.com/catamphetamine/libphonenumber-js.git /Users/kuchumovn/work/libphonenumber-js-autoupdate cd /Users/kuchumovn/work/libphonenumber-js-autoupdate npm install chmod u+x /Users/kuchumovn/work/libphonenumber-js-autoupdate/autoupdate.sh nano ~/Library/LaunchAgents/com.gitlab.catamphetamine.libphonenumber-js.metadata-update.plist <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.gitlab.catamphetamine.libphonenumber-js.metadata-update</string> <key>ProgramArguments</key> <array> <string>/Users/kuchumovn/work/libphonenumber-js-autoupdate/autoupdate.sh</string> </array> <key>Nice</key> <integer>1</integer> <key>StartInterval</key> <integer>86400</integer> <key>RunAtLoad</key> <true/> <key>StandardErrorPath</key> <string>/tmp/libphonenumber.errors.txt</string> <key>StandardOutPath</key> <string>/tmp/libphonenumber.output.txt</string> </dict> </plist> launchctl load ~/Library/LaunchAgents/com.gitlab.catamphetamine.libphonenumber-js.metadata-update.plist launchctl list | grep 'libphonenumber-js' ``` --> ## Maintenance This library reuses Google's metadata. Google periodically publishes a new version of the metadata, with the changes described in their [release notes](https://github.com/googlei18n/libphonenumber/blob/master/release_notes.txt). Those're usually minor fixes whenever some country decides to adjust their telephone numbering plan. After Google updates their metadata, this library pulls the updated metadata from Google's repository and publishes a new version of itself on `npm`. The metadata pulling process is automated through an "autoupdate" script: see `autoupdate.cmd` (Windows) or `autoupdate.sh` (Linux/macOS). The script detects changes to `PhoneNumberMetadata.xml` file in Google `libphonenumber`'s repo and, if there are any changes, it pulls the latest metadata, transforms it, commits the changes to the repository, builds a new version of the package and releases it to `npm`. I did manage to set up the autoupdate script to run dialy on my Windows machine in an automatic fashion through "Task Scheduler", but then `npm` started requiring "two-factor authentication" in order to publish a package, which requires human intervention, so currently the autoupdate process is kinda semi-automatic. <details> <summary>How to set up <code>autoupdate.cmd</code> to run automatically on Windows</summary> ###### To set up a task to run the autoupdate script periodically in Windows: * Open "Start" menu * Enter "Task Scheduler" * Task Scheduler window opens * On the right side, choose "Create Basic Task" * Enter "Name": "libphonenumber-js" * Enter some "Description" * Choose "Daily" * In "Start" specify a specific time. For example, when you're not using the computer but it's still on. * "Action" — "Start a program" * "Program/Script" — Choose the "autoupdate.cmd" file in `libphonenumber-js` directory After the task has been created, go to its "Properties", select "Settings" tab and check the check box where it says "Run task as soon as possible after a scheduled start is missed". Also, by default, it will open a physical "cmd" window when running the script. To prevent that, go to the task's "Properties", select "General" tab, and in "Security options" section, change the selected "radio button" from "Run only when user is logged on" to "Run whether user is logged on or not" and also check a checkbox next to it that says "Do not store password. The task will only have access to local computer resources". How to [fix](https://stackoverflow.com/questions/370030/why-git-cant-remember-my-passphrase-under-windows) `git` command asking for a password every time: "Git: "Enter passphrase for key ..."": * Open Windows start menu. Enter "Services". Choose the "Services" app. * In the "Services" app, find "OpenSSH Authentication Agent" service. Right-click it and choose "Properties". * In the properties modal, in the "Startup type" selector choose "Automatic". Also find and click the "Start" button below the selector. Click "OK" to close the properties modal. * Open Windows start menu. Enter "cmd". Choose the "Command Prompt" app. * Enter "ssh-add" and press Enter. * It will prompt for a passphrase: "Enter passphrase for ...". If instead it says "Error connecting to agent" then you didn't click the "Start" button at the previous steps. * Enter the passphrase and press Enter. * It will say: "Identity added". * Enter command: git config --global core.sshCommand "C:/Windows/System32/OpenSSH/ssh.exe" * Press Enter. * Now "git bash" is supposed to know the passphrase without having to type it in every time. </details> ###### <!-- So currently, I just run the "autoupdate" script manually from time to time. With this workflow, one can see how the metadata could potentially get a bit stale, in which case just ping me to re-run the autoupdate script, assuming I'm still alive and well. --> Also Google sometimes (extremely rarely) updates their code: * [`phonenumberutil.js`](https://github.com/googlei18n/libphonenumber/blob/master/javascript/i18n/phonenumbers/phonenumberutil.js) — is mirrored as functions: `parseNumber()`, `formatNumber()`, `isValidNumber()`, `getNumberType()` * [`AsYouTypeFormatter.java`](https://github.com/google/libphonenumber/blob/master/java/libphonenumber/src/com/google/i18n/phonenumbers/AsYouTypeFormatter.java) — is mirrored as `AsYouType` class * [`PhoneNumberMatcher.java`](https://github.com/googlei18n/libphonenumber/blob/master/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberMatcher.java) — is mirrored as `findPhoneNumbersInText()` function The latest sync-up with Google's code was on Sep 19th, 2025. ## Contributing After cloning this repo, install the dependencies: ```sh npm install ``` This library is written in ES6 and uses [Babel](http://babeljs.io/) for ES5 transpilation during the "build" step: ```sh npm run build ``` After making any code changes, run the tests: ```sh npm test ``` After the tests pass, check the code coverage ("statements" percentage) — it should remain at 100%: ```sh npm run test-coverage ``` A detailed code coverage report can be viewed by opening `./coverage/lcov-report/index.html` file. Sidenote: Because code coverage is tested using `istanbul` with `babel`, it may very rarely introduce "quirky" situtations when `babel` polyfill code gets mistakenly included in the analysis report, resulting in a "mysterious" decrease of the code coverage. The workaround is to re-implement those polyfills in a simpler manner or to use `/* istanbul ignore file */` directive. To test the updated code on a real project before publishing a new release, one could use "pack-and-install" trick to simulate publishing a new release. ```sh npm pack ``` It will `build`, `test` and then create a `.tgz` archive that can be installed from a project folder just like a normal `npm` package. ```sh npm install [module name with version].tar.gz ``` ## Advertisement If you like this library then you might also like: * [`react-phone-number-input`](https://npmjs.com/package/react-phone-number-input) — A `React` component for phone number input. * [`javascript-time-ago`](https://npmjs.com/package/javascript-time-ago) — An international human-readable past or future date formatter. Example: `"2 days ago"`. * [`react-time-ago`](https://npmjs.com/package/react-time-ago) — A `React` component for international human-readable past or future date formatter. Example: `"2 days ago"`. * [`read-excel-file`](https://www.npmjs.com/package/read-excel-file) — A simple and easy-to-use `*.xlsx` file reader (client-side or server-side). * [`write-excel-file`](https://www.npmjs.com/package/write-excel-file) — A simple and easy-to-use `*.xlsx` file writer (client-side or server-side). * [`flexible-json-schema`](https://www.npmjs.com/package/flexible-json-schema) — A simple and easy-to-use `*.json` schema data validator / parser. * [`navigation-stack`](https://www.npmjs.com/package/navigation-stack) — Navigation in a Single-Page Application. * [`virtual-scroller`](https://www.npmjs.com/package/virtual-scroller) — A universal implementation of a "virtual scroller" infinite list scrolling component: only renders the rows that fit the screen bounds. ## License Google's `libphonenumber` is [licensed](https://github.com/google/libphonenumber/blob/master/LICENSE) under Apache 2. [Apache 2](https://en.wikipedia.org/wiki/Apache_License#Licensing_conditions) 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](LICENSE), which is [compatible](https://www.quora.com/Is-the-MIT-license-compatible-with-the-Apache-License-Version-2-APLv2) 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.