# 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), weighs about 550 kB (350 kB code + 200 kB metadata). With many websites today asking for user's phone number, the internet could benefit from a simpler and smaller library that would just deal with parsing or formatting personal phone numbers, and that's what `libphonenumber-js` is. ## Differences from Google's `libphonenumber` * Smaller footprint: `145 kB` (65 kB code + 80 kB sufficient metadata) vs the original Google'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. ## Install via [npm](https://npmjs.org/) ```sh $ npm install libphonenumber-js --save ``` via [yarn](https://yarnpkg.com) ```sh $ yarn add libphonenumber-js ``` Alternatively, one could include it on a web page [directly](#cdn) via a ` ``` where `[version]` is an npm package version range (for example, `1.x` or `^1.7.6`) and `[type]` is the bundle type: `min`, `max` or `mobile`. ## Metadata Metadata is generated from Google's [`PhoneNumberMetadata.xml`](https://github.com/googlei18n/libphonenumber/blob/master/resources/PhoneNumberMetadata.xml) by transforming XML into JSON and removing unnecessary fields. See [metadata fields description](https://gitlab.com/catamphetamine/libphonenumber-js/blob/master/METADATA.md). ### Programmatic access Metadata can be accessed programmatically by using the exported `Metadata` class. First, create a `Metadata` class instance: ```js import { Metadata } from 'libphonenumber-js' const metadata = new Metadata() ``` Then, select a ["numbering plan"](https://en.wikipedia.org/wiki/Telephone_numbering_plan) (a country): ```js metadata.selectNumberingPlan('US') ``` After that, the following methods of `metadata.numberingPlan` can be called: * `leadingDigits(): string?` — Returns ["leading digits"](https://gitlab.com/catamphetamine/libphonenumber-js/blob/master/METADATA.md#leading_digits) pattern. * `possibleLengths(): number[]` — Returns a list of [possible lengths](https://gitlab.com/catamphetamine/libphonenumber-js/blob/master/METADATA.md#possible_lengths) of a national (significant) number. * `IDDPrefix(): string` — Returns an [International Direct Dialing](https://gitlab.com/catamphetamine/libphonenumber-js/blob/master/METADATA.md#idd_prefix) prefix. * `defaultIDDPrefix(): string?` — Returns a [default International Direct Dialing](https://gitlab.com/catamphetamine/libphonenumber-js/blob/master/METADATA.md#default_idd_prefix) prefix when there're multiple ones available. Example: ```js import { Metadata } from 'libphonenumber-js' const metadata = new Metadata() metadata.selectNumberingPlan('US') metadata.numberingPlan.leadingDigits() === undefined metadata.numberingPlan.possibleLengths() === [10] metadata.numberingPlan.IDDPrefix() === '011' metadata.numberingPlan.defaultIDDPrefix() === undefined ``` Using with custom metadata: ```js import { Metadata } from 'libphonenumber-js/core' import min from 'libphonenumber-js/min/metadata' // import max from 'libphonenumber-js/max/metadata' // import mobile from 'libphonenumber-js/mobile/metadata' const metadata = new Metadata(min) ``` As one can see, the [`Metadata` class](https://gitlab.com/catamphetamine/libphonenumber-js/-/blob/master/source/metadata.js) is not documented much. Partially, that's because its usage is not necessarily encouraged, but it's still used, for example, in [`react-phone-number-input`](https://gitlab.com/catamphetamine/react-phone-number-input/-/blob/master/source/helpers/phoneInputHelpers.js) to get the "leading digits" for a country, or to get the maximum phone number length for a country. Stick to the methods documented above and don't call any other methods. If you think there's a need to call any other methods not mentioned above, create an issue with a discussion. ### Custom metadata This library comes prepackaged with [three types of metadata](#min-vs-max-vs-mobile-vs-core). Sometimes, if only a specific set of countries is needed in a project, and a developer really wants to reduce the resulting bundle size, say, by 50 kilobytes, while still including all regular expressions for validating phone number digits and detecting phone number type, then they can generate such custom metadata and pass it as the last argument to this library's "core" functions. See [generate custom metadata](https://gitlab.com/catamphetamine/libphonenumber-metadata-generator) instructions.
How to use the generated metadata.custom.json file with the "core" functions. #### Pass the `metadata` argument as the last one to the "core" functions. In ES6 that would be: ```js import _parsePhoneNumber, { findPhoneNumbersInText as _findPhoneNumbersInText, AsYouType as _AsYouType } from 'libphonenumber-js/core' import metadata from 'libphonenumber-js/max/metadata' function call(func, _arguments) { var args = Array.prototype.slice.call(_arguments) args.push(metadata) return func.apply(this, args) } export default function parsePhoneNumber() { return call(_parsePhoneNumber, arguments) } export function findPhoneNumbersInText() { return call(_findPhoneNumbersInText, arguments) } export function AsYouType(country) { return _AsYouType.call(this, country, metadata) } AsYouType.prototype = Object.create(_AsYouType.prototype, {}) AsYouType.prototype.constructor = AsYouType ``` And for [Common.js](https://auth0.com/blog/javascript-module-systems-showdown/) environment that would be: ```js var core = require('libphonenumber-js/core') var metadata = require('libphonenumber-js/max/metadata') function call(func, _arguments) { var args = Array.prototype.slice.call(_arguments) args.push(metadata) return func.apply(this, args) } function parsePhoneNumber() { return call(core.default, arguments) } exports = module.exports = parsePhoneNumber exports['default'] = parsePhoneNumber exports.findPhoneNumbersInText = function findPhoneNumbersInText() { return call(core.findPhoneNumbersInText, arguments) } exports.AsYouType = function AsYouType(country) { return core.AsYouType.call(this, country, metadata) } exports.AsYouType.prototype = Object.create(core.AsYouType.prototype, {}) exports.AsYouType.prototype.constructor = exports.AsYouType ```
####
Legacy: How to use the generated metadata.custom.json file with the legacy "custom" functions. #### Pass the `metadata` argument as the last one to the "custom" functions. In ES6 that would be: ```js import { parseNumber, formatNumber, isValidNumber, getNumberType, AsYouType } from 'libphonenumber-js/custom' import metadata from 'libphonenumber-js/max/metadata' parseNumber('+78005553535', metadata) formatNumber({ phone: '8005553535', country: 'RU' }, metadata) isValidNumber('+78005553535', metadata) getNumberType('+78005553535', metadata) new AsYouType('RU', metadata).input('+78005553535') ``` And for [Common.js](https://auth0.com/blog/javascript-module-systems-showdown/) environment that would be: ```js var custom = require('libphonenumber-js/custom') var metadata = require('libphonenumber-js/max/metadata') exports.parseNumber = function parseNumber() { var parameters = Array.prototype.slice.call(arguments) parameters.push(metadata) return custom.parseNumber.apply(this, parameters) } exports.formatNumber = function formatNumber() { var parameters = Array.prototype.slice.call(arguments) parameters.push(metadata) return custom.formatNumber.apply(this, parameters) } exports.isValidNumber = function isValidNumber() { var parameters = Array.prototype.slice.call(arguments) parameters.push(metadata) return custom.isValidNumber.apply(this, parameters) } exports.getNumberType = function isValidNumber() { var parameters = Array.prototype.slice.call(arguments) parameters.push(metadata) return custom.getNumberType.apply(this, parameters) } exports.AsYouType = function AsYouType(country) { custom.AsYouType.call(this, country, metadata) } exports.AsYouType.prototype = Object.create(custom.AsYouType.prototype, {}) exports.AsYouType.prototype.constructor = exports.AsYouType ```
###### Note that if you'll be using your own "custom" metadata then you're responsible for keeping it up-to-date because Google regularly updates their metadata. ## Maintenance This library reuses Google's metadata. Google periodically publishes a new version of the metadata, with the changes described in their [release notes](https://github.com/googlei18n/libphonenumber/blob/master/release_notes.txt). Those're usually minor fixes whenever some country decides to adjust their telephone numbering plan. After Google updates their metadata, this library pulls the updated metadata from Google's repository and publishes a new version of itself on `npm`. The metadata pulling process is automated through an "autoupdate" script: see `autoupdate.cmd` (Windows) or `autoupdate.sh` (Linux/macOS). The script detects changes to `PhoneNumberMetadata.xml` file in Google `libphonenumber`'s repo and, if there are any changes, it pulls the latest metadata, transforms it, commits the changes to the repository, builds a new version of the package and releases it to `npm`. I did manage to set up the autoupdate script to run dialy on my Windows machine in an automatic fashion through "Task Scheduler", but then `npm` started requiring "two-factor authentication" in order to publish a package, which requires human intervention, so currently the autoupdate process is kinda semi-automatic.
How to set up autoupdate.cmd to run automatically on Windows ###### To set up a task to run the autoupdate script periodically in Windows: * Open "Start" menu * Enter "Task Scheduler" * Task Scheduler window opens * On the right side, choose "Create Basic Task" * Enter "Name": "libphonenumber-js" * Enter some "Description" * Choose "Daily" * In "Start" specify a specific time. For example, when you're not using the computer but it's still on. * "Action" — "Start a program" * "Program/Script" — Choose the "autoupdate.cmd" file in `libphonenumber-js` directory After the task has been created, go to its "Properties", select "Settings" tab and check the check box where it says "Run task as soon as possible after a scheduled start is missed". Also, by default, it will open a physical "cmd" window when running the script. To prevent that, go to the task's "Properties", select "General" tab, and in "Security options" section, change the selected "radio button" from "Run only when user is logged on" to "Run whether user is logged on or not" and also check a checkbox next to it that says "Do not store password. The task will only have access to local computer resources". How to [fix](https://stackoverflow.com/questions/370030/why-git-cant-remember-my-passphrase-under-windows) `git` command asking for a password every time: "Git: "Enter passphrase for key ..."": * Open Windows start menu. Enter "Services". Choose the "Services" app. * In the "Services" app, find "OpenSSH Authentication Agent" service. Right-click it and choose "Properties". * In the properties modal, in the "Startup type" selector choose "Automatic". Also find and click the "Start" button below the selector. Click "OK" to close the properties modal. * Open Windows start menu. Enter "cmd". Choose the "Command Prompt" app. * Enter "ssh-add" and press Enter. * It will prompt for a passphrase: "Enter passphrase for ...". If instead it says "Error connecting to agent" then you didn't click the "Start" button at the previous steps. * Enter the passphrase and press Enter. * It will say: "Identity added". * Enter command: git config --global core.sshCommand "C:/Windows/System32/OpenSSH/ssh.exe" * Press Enter. * Now "git bash" is supposed to know the passphrase without having to type it in every time.
###### Also Google sometimes (extremely rarely) updates their code: * [`phonenumberutil.js`](https://github.com/googlei18n/libphonenumber/blob/master/javascript/i18n/phonenumbers/phonenumberutil.js) — is mirrored as functions: `parseNumber()`, `formatNumber()`, `isValidNumber()`, `getNumberType()` * [`AsYouTypeFormatter.java`](https://github.com/google/libphonenumber/blob/master/java/libphonenumber/src/com/google/i18n/phonenumbers/AsYouTypeFormatter.java) — is mirrored as `AsYouType` class * [`PhoneNumberMatcher.java`](https://github.com/googlei18n/libphonenumber/blob/master/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberMatcher.java) — is mirrored as `findPhoneNumbersInText()` function The latest sync-up with Google's code was on Sep 19th, 2025. ## Contributing After cloning this repo, install the dependencies: ```sh npm install ``` This library is written in ES6 and uses [Babel](http://babeljs.io/) for ES5 transpilation during the "build" step: ```sh npm run build ``` After making any code changes, run the tests: ```sh npm test ``` After the tests pass, check the code coverage ("statements" percentage) — it should remain at 100%: ```sh npm run test-coverage ``` A detailed code coverage report can be viewed by opening `./coverage/lcov-report/index.html` file. Sidenote: Because code coverage is tested using `istanbul` with `babel`, it may very rarely introduce "quirky" situtations when `babel` polyfill code gets mistakenly included in the analysis report, resulting in a "mysterious" decrease of the code coverage. The workaround is to re-implement those polyfills in a simpler manner or to use `/* istanbul ignore file */` directive. To test the updated code on a real project before publishing a new release, one could use "pack-and-install" trick to simulate publishing a new release. ```sh npm pack ``` It will `build`, `test` and then create a `.tgz` archive that can be installed from a project folder just like a normal `npm` package. ```sh npm install [module name with version].tar.gz ``` ## Advertisement If you like this library then you might also like: * [`react-phone-number-input`](https://npmjs.com/package/react-phone-number-input) — A `React` component for phone number input. * [`javascript-time-ago`](https://npmjs.com/package/javascript-time-ago) — An international human-readable past or future date formatter. Example: `"2 days ago"`. * [`react-time-ago`](https://npmjs.com/package/react-time-ago) — A `React` component for international human-readable past or future date formatter. Example: `"2 days ago"`. * [`read-excel-file`](https://www.npmjs.com/package/read-excel-file) — A simple and easy-to-use `*.xlsx` file reader (client-side or server-side). * [`write-excel-file`](https://www.npmjs.com/package/write-excel-file) — A simple and easy-to-use `*.xlsx` file writer (client-side or server-side). * [`flexible-json-schema`](https://www.npmjs.com/package/flexible-json-schema) — A simple and easy-to-use `*.json` schema data validator / parser. * [`navigation-stack`](https://www.npmjs.com/package/navigation-stack) — Navigation in a Single-Page Application. * [`virtual-scroller`](https://www.npmjs.com/package/virtual-scroller) — A universal implementation of a "virtual scroller" infinite list scrolling component: only renders the rows that fit the screen bounds. ## License Google's `libphonenumber` is [licensed](https://github.com/google/libphonenumber/blob/master/LICENSE) under Apache 2. [Apache 2](https://en.wikipedia.org/wiki/Apache_License#Licensing_conditions) does not require a derivative work of the software, or modifications to the original, to be distributed using the same license. Hence, this library is licensed under [MIT](LICENSE), which is [compatible](https://www.quora.com/Is-the-MIT-license-compatible-with-the-Apache-License-Version-2-APLv2) with Apache 2. The Apache license is terminated if the user sues anyone over patent infringement related to the software covered by the license. This condition is added in order to prevent patent litigations.