UNPKG

libphonenumber-js

Version:

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

956 lines (662 loc) 92.8 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/blob/master/java/libphonenumber/) library in javascript. [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 get the parsing and formatting right, 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. --> ## Difference 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). * Can search for phone numbers in text (Google's autogenerated javascript port can't). * Aims at parsing and formatting people's phone numbers while skipping all other "special" cases like: * Emergency phone numbers like `911`. * ["Short codes"](https://www.tatango.com/blog/sms-short-codes-what-every-business-needs-to-know/): short SMS-only numbers like `12345`. * Numbers starting with a [`*`](https://github.com/googlei18n/libphonenumber/blob/master/FALSEHOODS.md), like `*555`. * Alphabetic phone numbers like `1-800-GOT-MILK`: people don't input their phone numbers like that, it's only used in advertisement. * "Two-in-one" phone numbers with "combined" extensions like `(530) 583-6985 x302/x2303` that in fact represent two separate phone numbers, because the library can only return a single phone number when parsing a string. * Overall, doesn't support formatting non-"conventional" numbers like numbers with the "area code" omitted or "alternative" "short" numbers like [Australian `13`-smart numbers](https://github.com/catamphetamine/libphonenumber-js/issues/400). For example, when dialing phone numbers within the same "area", people sometimes skip the "area code", and dial, say, `456-789` instead of `(123) 456-789`. Google's `libphonenumber` supports formatting such numbers (with "area code" omitted) because it is used for dialing on the Android phone operating system. Because `libphonenumber-js` isn't a phone operating system and is not used for actual dialing — only for inputting internationally-dialable personal phone numbers — it doesn't format such "short" phone numbers because it doesn't need to support those. * Any other "miscellaneous" cases that're considered irrelevant for the task. * Doesn't provide "geolocation" by a phone number. * Doesn't use hyphens or brackets when formatting international phone numbers, only whitespace (seems more logical this way). * Doesn't set `.country` to `"001"` when parsing ["non-geographic"](#non-geographic) phone numbers (like mobile satellite communications services). Instead, `.country` is `undefined` in those cases, and a developer can call `.isNonGeographic()` method of the `PhoneNumber` instance to find out whether the parsed phone number is a "non-geographic" one. * Doesn't provide the equivalent of `libphonenumber`'s `formatNumberForMobileDialing()` function that formats a number for dialing using a mobile phone within the country: dialing local numbers from a mobile phone is a bit more complicated in some countries like Brazil or Colombia where they require adding ["carrier codes"](https://www.bandwidth.com/glossary/carrier-identification-code-cic/) when making a call. Since `libphonenumber-js` is not a dialing library (we're not Android phone operaing system), it doesn't prepend any "carrier codes" when formatting phone numbers, though it does parse such "carrier codes" correctly. <!-- (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) --> ## GitHub 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 (you can star the repo there too), and the primary repo is now the [GitLab one](https://gitlab.com/catamphetamine/libphonenumber-js). Issues can be reported in any repo. ## Install via [npm](https://npmjs.org/) ```sh $ npm install libphonenumber-js --save ``` via [yarn](https://yarnpkg.com) ```sh $ yarn add libphonenumber-js ``` If you're not using a bundler then use a [standalone version from a CDN](https://gitlab.com/catamphetamine/libphonenumber-js/#cdn). ## Use <!-- ### 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)_ --> ```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> --> ### Validate 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 the actual phone number digits. `validatePhoneNumberLength()` is just a more detailed version of `isPossiblePhoneNumber()` — if the phone number length is invalid, it returns the actual reason: `TOO_SHORT`, `TOO_LONG`, etc. ### Format phone number <!-- _(new API)_ --> ```js import parsePhoneNumber from 'libphonenumber-js' const phoneNumber = parsePhoneNumber('+12133734253') 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 ```js import { AsYouType } from 'libphonenumber-js' new AsYouType().input('+12133734') // Outputs: '+1 213 373 4' new AsYouType('US').input('2133734') // Outputs: '(213) 373-4' ``` ### Full-text search <!-- _(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, "metadata" being a list of phone number parsing and formatting rules for all countries. The complete list of those rules is huge, so this library provides a way to optimize bundle size by choosing between `max`, `min`, `mobile` and "custom" metadata: * `max` — The complete metadata set, is about `145 kilobytes` in size (`libphonenumber-js/metadata.max.json`). Choose this when you need the most strict version of `isValid()`, or if you need to detect phone number type ("fixed line", "mobile", etc). * `min` — (default) The smallest metadata set, is about `80 kilobytes` in size (`libphonenumber-js/metadata.min.json`). Choose this by default: when you don't need to detect phone number type ("fixed line", "mobile", etc), or when a basic version of `isValid()` is enough. The `min` metadata set doesn't contain the regular expressions for phone number digits validation (via [`.isValid()`](#isvalid)) and detecting phone number type (via [`.getType()`](#gettype)) for most countries. In this case, `.isValid()` still performs some basic phone number validation (for example, checks phone number length), but it doesn't validate phone number digits themselves the way `max` metadata validation does. * `mobile` — The complete metadata set for dealing with mobile numbers _only_, is about `95 kilobytes` in size (`libphonenumber-js/metadata.mobile.json`). Choose this when you need `max` metadata and when you _only_ accept mobile numbers. Other phone number types will still be parseable, but they won't be recognized as being "valid" (`.isValid()` will return `false`). To use a particular metadata set, simply import functions from a relevant sub-package: * `libphonenumber-js/max` * `libphonenumber-js/min` * `libphonenumber-js/mobile` Importing functions directly from `libphonenumber-js` effectively results in using the `min` metadata. Sometimes (rarely) not all countries are needed, and in those cases developers may want to [generate](#customizing-metadata) their own "custom" metadata set. For those cases, there's `libphonenumber-js/core` sub-package which doesn't come pre-packaged with any default metadata set and instead accepts metadata as the last argument of each exported function. ## 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 like: `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 have `country` set to `undefined`. ### National (significant) number "National (significant) number" are the national phone number digits (without "national prefix"). For example, `+1 213 373 4253` (or `(213) 373-4253` in national format) is a US phone number and its national (significant) number is `213 373 4253`. Another example is `+33 1 45 45 32 45` (or `01 45 45 32 45` in national format) which is a [French](https://en.wikipedia.org/wiki/Telephone_numbers_in_France) phone number where they add `0` "national prefix" when writing phone numbers in national format; in this case the national (significant) number is `1 45 45 32 45`. ### Country calling code "Country calling code" are the digits between the `+` and the national (significant) number when the number is written in international format. E.g. for US country calling code is `1` and for France it's `33`. Several countries can share the same "country calling code", e.g. [NANPA](https://en.wikipedia.org/wiki/North_American_Numbering_Plan) countries like USA and Canada sharing the same `1` country calling code. ## API ### parsePhoneNumber(string, defaultCountry?: string | options?: object): PhoneNumber Parses a phone number from `string`. Can be imported both as a "default" export and as a "named" export `parsePhoneNumberFromString`. ```js import parsePhoneNumber from 'libphonenumber-js' // Or: import { parsePhoneNumberFromString as parsePhoneNumber } from 'libphonenumber-js' const phoneNumber = parsePhoneNumber('(213) 373-42-53 ext. 1234', 'US') if (phoneNumber) { console.log(phoneNumber.formatNational()) } ``` Returns an instance of [`PhoneNumber`](#phonenumber) class, or `undefined` if no phone number could be parsed: for example, when the string contains no phone number, or the phone number starts with a non-existent [country calling code](#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 input string `"(213) 373-4253"` it would return a parsed `PhoneNumber`. If a developer wants to know the exact reason why the phone number couldn't be parsed then they can use `parsePhoneNumberWithError()` function which throws the exact error: ```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> #### Strictness By default, the parsing function will attempt to extract a phone number from an input string even in cases like `"Support: (213) 373-4253 (robot)"`, which mimicks the behavior of the original Google's `libphonenumber` library, and is the default behavior for legacy reasons. However, if "strict" input validation is required, one can pass `extract: false` flag to demand that the whole input string be a viable phone number. ```js parsePhoneNumber('Call: (213) 373-4253', 'US') === PhoneNumber // When parsing the same string with `extract: false` flag, // it will return `undefined`, because a phone number can't // contain letters or a colon. parsePhoneNumber('Call: (213) 373-4253', { defaultCountry: 'US', extract: false }) === undefined parsePhoneNumber('(213) 373-4253', { defaultCountry: 'US', extract: false }) === PhoneNumber ``` ### `PhoneNumber` `PhoneNumber` class represents a parsed 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 parsed phone `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 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)` Sets a [phone number extension](https://en.wikipedia.org/wiki/Extension_(telephone)) of a phone number. Could be useful when formatting phone numbers stored as two separate fields: the phone number itself and the extension part. ```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 `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 UK. * `nationalPrefix: Boolean` — Some phone numbers can be formatted both with national prefix and without it. In such cases the library defaults to "with national prefix" (for legacy reasons). Pass `nationalPrefix: false` option to force formatting without national prefix in such cases. Examples: ```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' // Aliases phoneNumber.formatNational() === phoneNumber.format("NATIONAL") phoneNumber.formatInternational() === phoneNumber.format("INTERNATIONAL") phoneNumber.getURI() === phoneNumber.format("RFC3966") ``` #### `isPossible(): boolean` Checks if the phone number is "possible". Only checks the phone number length, doesn't check the actual phone number digits against any regular expressions. #### `isValid(): boolean` Checks if the phone number is "valid". First checks the phone number length and then checks the phone number digits against all available regular expressions. By default the library uses "minimal" metadata which is only 75 kilobytes in size but also doesn't include the precise validation regular expressions resulting in less strict validation rules (some very basic validation like length check is still included for each country). If you don't mind the extra 65 kilobytes of metadata then use ["full" metadata](#min-vs-max-vs-mobile-vs-core) instead (140 kilobytes). Google's library always uses "full" metadata so it will yield different `isValidNumber()` results compared to the "minimal" metadata used by default in this library. <details> <summary>See an example illustrating different results when using <code>/min</code> vs <code>/max</code> vs <code>/mobile</code></summary> #### ```js import parseMin from 'libphonenumber-js/min' import parseMax from 'libphonenumber-js/max' import parseMobile from 'libphonenumber-js/mobile' // Mobile numbers in Singapore starting from `8` // can only have the second digit in the range of `0..8`. // Here the second digit is `9` which makes it an invalid mobile number. // This is a "strict" (advanced) validation rule and is // not included in the (default) "min" bundle. // The basic number length check passes (`8..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 // The "advanced" validation regexp for mobile numbers is // `(?:8[1-8]|9[0-8])\\d{6}` and possible lengths are `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 this phone number could possibly belong to. Can be used when parsing complete international phone numbers containing a "calling code" that is shared between several countries. If parsing such a phone number returns `country: undefined` then `getPossibleCountries()` function could be used to somehow speculate about what country could this phone number possibly belong to. #### `getType(): string?` Returns phone number type (fixed line, mobile, toll free, etc) or `undefined` (if the number is invalid or if there are no phone number type regular expressions for this country in metadata). By default the library uses "minimal" metadata which is only 75 kilobytes in size but also doesn't include the regular expressions for determining a specific phone number type (fixed line, mobile, toll free, etc) resulting in `getType()` returning `undefined` for most countries. If you don't mind the extra 65 kilobytes of metadata then use ["full" metadata](#min-vs-max-vs-mobile-vs-core) instead (140 kilobytes). Google's library always uses "full" metadata so it will yield different `getNumberType()` results compared to the "minimal" metadata used by default in this library. <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></summary> #### ```js import parseMin from 'libphonenumber-js/min' import parseMax from 'libphonenumber-js/max' import parseMobile from 'libphonenumber-js/mobile' // Singapore valid mobile number. // The (default) "min" bundle doesn't contain any regexps for // getting phone number type based on national number (for Singapore). parseMin('+6584655555').getType() === undefined // The "max" bundle contains regexps for // getting phone number type based on national number // for all possible phone number types. parseMax('+6584655555').getType() === 'MOBILE' // The "mobile" bundle contains regexps for // getting phone number type based on national number // for mobile phone numbers only. 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 an "exact country" instead. This function is not currently exported from this library. The reason is that its result would be too vague when `false` is returned — it could mean any of: * 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 "the country is incorrect" rather than that "the phone number is incorrect", otherwise it would be bad UX design. But for those who'd still like to have such function, here's a possible implementation for it: ```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've [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 set and the user enters a phone number not in international format. * `getNumberValue(): string?` — Returns the phone number in [`E.164`](https://en.wikipedia.org/wiki/E.164) format. For example, for country `"US"` and input `"(222) 333-4444"` it will return `"+12223334444"`. Will return `undefined` if no digits have been input, or when inputting a phone number in national format and no default country or default "country calling code" have been set. * `getChars(): string` — Returns the phone number characters entered by the user: digits and a `+` sign (if present). Returns an empty string if no phone number characters have been input. * `getTemplate(): string` — Returns the template used to format the phone number characters (digits and a `+` sign, if present), which are denoted by `x`-es. Returns an empty string if no phone number characters have been input. ```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. * `isPossible(): boolean` — Returns `true` if the phone number is "possible". Is just a shortcut for [`PhoneNumber.isPossible()`](#ispossible-boolean). * `isValid(): boolean` — Returns `true` if the phone number is "valid". Is just a shortcut for [`PhoneNumber.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 in the start of an international number). When used on desktops where a user can input all kinds of punctuation (spaces, dashes, parens, etc) it simply ignores everything except digits (and a `+` sign in the start of an international number). Google's "As You Type" formatter does not support entering phone number extensions. If your project requires phone number extensions input then use a separate input field for that. ### findPhoneNumbersInText(text: string, defaultCountry?: string | options?: object): object[] Searches for 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: //