UNPKG

libphonenumber-js

Version:

A simpler (and smaller) rewrite of Google Android's libphonenumber library in javascript

796 lines (565 loc) 112 kB
# libphonenumber-js [![npm version](https://img.shields.io/npm/v/libphonenumber-js.svg?style=flat-square)](https://www.npmjs.com/package/libphonenumber-js) [![npm downloads](https://img.shields.io/npm/dm/libphonenumber-js.svg?style=flat-square)](https://www.npmjs.com/package/libphonenumber-js) [![coverage](https://img.shields.io/coveralls/catamphetamine/libphonenumber-js/master.svg?style=flat-square)](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), the total weight becomes about 550 kB (350 kB code + 200 kB metadata). `libphonenumber-js` works around the bundle size issue by stripping down both code and metadata: the code was rewritten in javascript/typescript from scratch, and a developer can now choose which parts of metadata to include. <!-- 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. --> <details> <summary>Here's a full comparison to Google's <code>libphonenumber</code> for those who're interested.</summary> ###### * 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. </details> <!-- (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 ```sh npm install libphonenumber-js --save ``` 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 // `.getType()` only works when import from 'libphonenumber-js/max' 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 a complete or incomplete phone number. ```js import { AsYouType } from 'libphonenumber-js' // Country not specified — use international format new AsYouType().input('+12133734') === '+1 213 373 4' // Country specified — use national format new AsYouType('US').input('2133734') === '(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' // Length is invalid validatePhoneNumberLength('8 (800) 555-35-35', 'RU') === undefined // Length is valid ``` `isPossiblePhoneNumber()` validates phone number length. `isValidPhoneNumber()` validates both phone number length and phone number digits. It may seem counter-intuitive but when [choosing between the two](#using-phone-number-validation-feature), I'd personally prefer `isPossiblePhoneNumber()` because its strength is in its weakness. `isValidPhoneNumber()` is a double-edged sword in terms of how strict it is, and when not updated regularly, it could get stale over time and start rejecting freshly-assigned phone number ranges. As for `validatePhoneNumberLength()`, is just a more detailed version of `isPossiblePhoneNumber()` for those who need it — when the phone number length is invalid, instead of returning just `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') === [ { 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 package lets a developer choose from 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 package provides a way to optimize the bundle size by choosing between `max`, `min`, `mobile` or "custom" metadata, depending on the project's needs. * `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`. * "custom" — (advanced) Create [your own](#custom-metadata) metadata that is even smaller in size by dropping support for most countries * The size depends on the number of supported countries and the type of supported phone numbers * Choose this when: * You only need to support a handful of countries and you're absolutely obsessed with reducing the bundle size Choose one from the above and then simply `import` the functions from the relevant sub-package: * `min` — `libphonenumber-js/min`, or just `libphonenumber-js` (shorter alias) * `max` — `libphonenumber-js/max` * `mobile` — `libphonenumber-js/mobile` * "custom" — `libphonenumber-js/core` And if you're at the cutting edge of web development and you only need to support [ES6](https://caniuse.com/?search=es6)-compliant web browsers, which are basically any web browsers released since mid-2017, then just append `/es6` to the package name: * `min` — `libphonenumber-js/min/es6` * `max` — `libphonenumber-js/max/es6` * `mobile` — `libphonenumber-js/mobile/es6` * "custom" — `libphonenumber-js/core/es6` 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 This package introduces a few new terms in order describe its behavior more precisely. ### 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) it 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` In some cases, multiple countries could share the same "country calling code". For example, USA, Canada and some Caribbean nations [share](https://en.wikipedia.org/wiki/North_American_Numbering_Plan) the same country calling code `1`. ### Non-Geographic Some "country calling codes" don't belong to any given country or territory and are by-design international. Such phone numbers are called "non-geographic", and their `country` property is `undefined`. <details> <summary>Here's a full list of "non-geographic" calling codes.</summary> ###### * `+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) </details> ### Country Code A "country code" is a two-letter [ISO country code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) like `"US"`, `"CA"`, etc. <!-- 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)). --> However, this library uses the term "country code" rather broadly and it includes both the [official](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) ISO country codes and a few of [unofficial](#country-code-additions) "country codes" that do not "officially" exist. For that reason, a developer should use a "country code" returned from this library with caution in an application that only expects the official ISO "country codes" to exist. For example, such application will likely not have a label or a flag for such an unofficial "country code". A developer could manually transform any unofficial "country code" returned from this library to a most-suitable official one. Because there's no obvious answer in such case, it's up to developers themselves to decide which country name or flag to show. To get a list of all supported "country codes", both official and unofficial, use [`getCountries()`](#getcountries-string) function. To check if a certain two-letter "country code" is supported by this library, use [`isSupportedCountry()`](#issupportedcountrycountry-string-boolean) function. ### Country Code (additions) Here's a list of the unofficial "country codes". These codes are used for certain "regions" that're usually a subject of a [territorial dispute](https://en.wikipedia.org/wiki/Territorial_dispute). * `AC` — [Ascension Island](https://en.wikipedia.org/wiki/Ascension_Island) * `TA` — [Tristan da Cunha](https://en.wikipedia.org/wiki/Tristan_da_Cunha) * `SH` — [Saint Helena](https://en.wikipedia.org/wiki/Saint_Helena) * `XK` — [Kosovo](https://en.wikipedia.org/wiki/Kosovo) <details> <summary>Here're some more details on each one of them for those who're interested.</summary> ###### * `AC` — [Ascension Island](https://en.wikipedia.org/wiki/Ascension_Island) * (history) The region of Ascension Island is officially part of [Saint Helena, Ascension and Tristan da Cunha ](https://en.wikipedia.org/wiki/Saint_Helena,_Ascension_and_Tristan_da_Cunha) (`SH`), which used to be called "Saint Helena and Dependencies" until 2009 when the dependencies were raised to equal status with Saint Helena. * Ascension Island has been assigned its own country calling code of `+247`. * An unofficial code `AC` is used for Ascension Island region in Google's `libphonenumber`. * `AC` is also an official ["exceptional reservation"](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Reserved_code_elements) code for Ascension Island in the ISO-3166-1 standard. * The last official ISO-3166-2 ["subdivision code"](https://en.wikipedia.org/wiki/ISO_3166-2) assigned to Ascension Island region [is](https://en.wikipedia.org/wiki/ISO_3166-2:SH) `SH-AC`. * `TA` — [Tristan da Cunha](https://en.wikipedia.org/wiki/Tristan_da_Cunha) * (history) The region of Tristan da Cunha is officially part of [Saint Helena, Ascension and Tristan da Cunha ](https://en.wikipedia.org/wiki/Saint_Helena,_Ascension_and_Tristan_da_Cunha) (`SH`), which used to be called "Saint Helena and Dependencies" until 2009 when the dependencies were raised to equal status with Saint Helena. * Tristan da Cunha shares a country calling code of `+290` with [Saint Helena](https://en.wikipedia.org/wiki/Saint_Helena) where it has a unique prefix of `8`. * For the purpose of differentiating Tristan da Cunha phone numbers from [Saint Helena](https://en.wikipedia.org/wiki/Saint_Helena) phone numbers, an unofficial code `TA` is used for it in Google's `libphonenumber`. * `TA` is also an official ["exceptional reservation"](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Reserved_code_elements) code for Tristan da Cunha in the ISO-3166-1 standard. * The last official ISO-3166-2 ["subdivision code"](https://en.wikipedia.org/wiki/ISO_3166-2) assigned to Tristan da Cunha region [is](https://en.wikipedia.org/wiki/ISO_3166-2:SH) `SH-TA`. * `SH` — [Saint Helena](https://en.wikipedia.org/wiki/Saint_Helena) * (history) The region of Saint Helena is officially part of [Saint Helena, Ascension and Tristan da Cunha ](https://en.wikipedia.org/wiki/Saint_Helena,_Ascension_and_Tristan_da_Cunha) (`SH`), which used to be called "Saint Helena and Dependencies" until 2009 when the dependencies were raised to equal status with Saint Helena. * For the purpose of differentiating Saint Helena phone numbers from [Tristan da Cunha](https://en.wikipedia.org/wiki/Tristan_da_Cunha) phone numbers, the official ISO country code of `SH` is only used for Saint Helena region in Google's `libphonenumber`. * The last official ISO-3166-2 ["subdivision code"](https://en.wikipedia.org/wiki/ISO_3166-2) assigned to Saint Helena region [is](https://en.wikipedia.org/wiki/ISO_3166-2:SH) `SH-HL`. * `XK` — [Kosovo](https://en.wikipedia.org/wiki/Kosovo) * (history) The region of Kosovo separated from Yugoslavia (present [Serbia](https://en.wikipedia.org/wiki/Serbia), `RS`) after a 1998-1999 civil war that was put to an end by NATO's bombing of Yugoslavia in 1999. The government of Kosovo officially (unilaterally) declared independence from Serbia in 2008. Due to the mixed opinions on the legitimacy of NATO's intervention, about half of the United Nations member states currently support Kosovo's independence while the rest of them don't, so Kosovo is currently not assigned any "official" country code. * Kosovo has been assigned its own country calling code of `+383`. * An unofficial code `XK` is used for Kosovo region in Google's `libphonenumber`. * `XK` is a ["user-assigned"](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#User-assigned_code_elements) code in the ISO-3166-1 standard meaning that it can be freely assigned to any region by any application or organization for its own purposes. * The last official ISO-3166-2 ["subdivision code"](https://en.wikipedia.org/wiki/ISO_3166-2) assigned to Kosovo region [is](https://en.wikipedia.org/wiki/Autonomous_Province_of_Kosovo_and_Metohija) `RS-KM`. </details> ###### There's also a list of territories that have a disputed status of an independent state. For obvious reasons, they dropped the use of their original parent territory's telephone numbering plan and instead joined another state's telephone numbering plan. * [Abkhazia](https://en.wikipedia.org/wiki/Abkhazia) — used to be part of [Georgia](https://en.wikipedia.org/wiki/Georgia_(country)) (`GE`) but currently uses the telephone numbering plan of [Russia](https://en.wikipedia.org/wiki/Russia) (`RU`) * [South Ossetia](https://en.wikipedia.org/wiki/South_Ossetia) — used to be part of [Georgia](https://en.wikipedia.org/wiki/Georgia_(country)) (`GE`) but currently uses the telephone numbering plan of [Russia](https://en.wikipedia.org/wiki/Russia) (`RU`) * [Northern Cyprus](https://en.wikipedia.org/wiki/Northern_Cyprus) — used to be part of [Cyprus](https://en.wikipedia.org/wiki/Cyprus) (`CY`) but currently uses the telephone numbering plan of [Turkey](https://en.wikipedia.org/wiki/Turkey) (`TR`) <details> <summary>Here're some more details on each one of them for those who're interested.</summary> ###### These territories are currently not implemented in this library but they could potentially be implemented in some future: * [Abkhazia](https://en.wikipedia.org/wiki/Abkhazia) * (history) The region of Abkhazia separated from [Georgia](https://en.wikipedia.org/wiki/Georgia_(country)) (`GE`) during a civil war in 1992-1994. The government of Abkhazia officially (unilaterally) declared independence from Georgia in 1994 when the civil war was put to an end. The first state to officially recognize Abkhazia's independence was Russia in 2008. * Abkhazia currently shares a country calling code of `+7` with [Russia](https://en.wikipedia.org/wiki/Russia) (`RU`) where it has [unique prefixes](https://en.wikipedia.org/wiki/Telephone_numbers_in_Russia#Codes_assigned_to_Abkhazia) of `840` and `940`, so the "country code" is currently parsed as `RU`. * For the purpose of differentiating Abkhazia phone numbers from Russia phone numbers, an unofficial code like `XA` could be used for it in Google's `libphonenumber`. * `XA` is a ["user-assigned"](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#User-assigned_code_elements) code in the ISO-3166-1 standard meaning that it can be freely assigned to any region by any application or organization for its own purposes. * The last official ISO-3166-2 ["subdivision code"](https://en.wikipedia.org/wiki/ISO_3166-2) assigned to Abkhazia region [is](https://en.wikipedia.org/wiki/ISO_3166-2:GE) `GE-AB`. * [South Ossetia](https://en.wikipedia.org/wiki/South_Ossetia) * (history) The region of South Ossetia separated from [Georgia](https://en.wikipedia.org/wiki/Georgia_(country)) (`GE`) during a civil war 1991–1992. The government of South Ossetia officially (unilaterally) declared independence from Georgia in 1992 when the civil war was put to an end. The first state to officially recognize South Ossetia's independence was Russia in 2008. * South Ossetia currently shares a country calling code of `+7` with [Russia](https://en.wikipedia.org/wiki/Russia) (`RU`) where it has [unique prefixes](https://en.wikipedia.org/wiki/Telephone_numbers_in_Russia#Codes_assigned_to_South_Ossetia) of `850` and `929`, so the "country code" is currently parsed as `RU`. * For the purpose of differentiating South Ossetia phone numbers from Russia phone numbers, an unofficial code like `XO` could be used for it in Google's `libphonenumber`. * `XO` is a ["user-assigned"](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#User-assigned_code_elements) code in the ISO-3166-1 standard meaning that it can be freely assigned to any region by any application or organization for its own purposes. * South Ossetia region has [not](https://en.wikipedia.org/wiki/ISO_3166-2:GE) ever been assigned any official ISO-3166-2 ["subdivision code"](https://en.wikipedia.org/wiki/ISO_3166-2). * [Northern Cyprus](https://en.wikipedia.org/wiki/Northern_Cyprus) * (history) The region of Northern Cyprus separated from [Cyprus](https://en.wikipedia.org/wiki/Cyprus) (`CY`) during [Turkey](https://en.wikipedia.org/wiki/Turkey)'s military invasion in 1974. The government of Northern Cyprus officially (unilaterally) declared independence from Cyprus in 1983. The first state to officially recognize Northern Cyprus' independence was Turkey in 1983. * Northern Cyprus currently shares a country calling code of `+90` with Turkey (`TR`) where it has [unique prefixes](https://en.wikipedia.org/wiki/Telephone_numbers_in_Northern_Cyprus) of `392`, `533` and `542`, so the "country code" is currently parsed as `TR`. * For the purpose of differentiating Northern Cyprus phone numbers from Turkey phone numbers, some unofficial code like `XC` could be used for it in Google's `libphonenumber`. * Northern Cyprus region has [not](https://en.wikipedia.org/wiki/ISO_3166-2:CY) ever been assigned any official ISO-3166-2 ["subdivision code"](https://en.wikipedia.org/wiki/ISO_3166-2). </details> ## 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 code](#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 package uses [`min`](#min-vs-max-vs-mobile-vs-core) ("minimal") metadata which is only `80 kB` in size but also doesn't include the precise regular expressions for validating phone number digits, i.e. it only validates phone number length, effectively causing `isValid()` to behave same way as if it was `isPossible()`. So if you need to validate phone number digits themselves and 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. For reference, Google's original `libphonenumber` always uses `max` metadata and doesn't have a concept of `min` metadata. <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 co