libphonenumber-js: the rewrite of Google's phone number library that chose size over completeness
A simpler (and smaller) rewrite of Google Android's libphonenumber library in javascript
At a glance
- What is it?
- An MIT-licensed JavaScript rewrite of Android's libphonenumber that cuts the bundle from 550 kB to 145 kB by shrinking both the code and the country metadata, and documents every case it gives up.
- Who is it for?
- Choose libphonenumber-js when you are validating a contact form, normalising a number for storage, or rendering a number back to a person, because that is the whole job and 145 kB does it well. Choose Google's library instead when you need emergency numbers, short codes, carrier codes for mobile dialing, or geolocation from a number, because those are the features this project deliberately leaves out.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 110 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem is 200 kB of metadata you will never read
Google's libphonenumber is a C++ and Java library that Android phones use to parse and format numbers, and it has an official autogenerated JavaScript port. The port is the interesting part for web developers, because it works, and because when you bundle it the total weight lands at about 550 kB: roughly 350 kB of code and 200 kB of metadata. Almost none of that metadata describes the country you are serving. It describes every country, every numbering plan change since the library began, and the special cases nobody types into a web form. libphonenumber-js attacks the number from both ends. The README's comparison puts the result at 145 kB, split into 65 kB of code and 80 kB of metadata, and the way it gets there is stated plainly: the code was rewritten from scratch in JavaScript and TypeScript, and a developer can now choose which parts of the metadata to include. That second half is the actual design idea. A rewrite gets you the code down. Letting the consumer pick the metadata tier is what gets the rest.
Five package entry points, and the trade each one makes
The tree shows the same choice made five times. There is `min/`, `max/`, `mobile/` and `core/` as directories, alongside `metadata.min.json`, `metadata.max.json` and `metadata.full.json` as type declarations that name real files, and a single `examples.mobile.json` that documents the mobile tier's coverage. The `package.json` at version 1.13.7 makes each tier a real export path with both module systems wired up, so the choice happens in an import statement rather than in a build flag. The entry point is declared as `main` pointing at `index.cjs` and `module` pointing at `index.js`, with `type` set to `module`, which is the full CommonJS and ESM pairing most bundlers expect. Each tier also has an `es6` subpath with its own `types` entry, so TypeScript consumers get declarations without pulling the CommonJS build. The four tiers are not four versions of the same thing with different defaults. They are four different answers to how much of the world's numbering data you want in your bundle, and the names are terse enough that you will have to look them up once.
Installing it and including it from a CDN
Installation is the ordinary npm incantation, and it is the only command in the README:
npm install libphonenumber-js --saveThe README then notes an alternative for people who are not using a bundler at all: include the library on a web page directly through a `<script/>` tag. That sentence matters because it means the library works as a plain browser global without a module system, which is the situation a lot of small sites are actually in. It also explains why the package carries an `index.cjs` next to `index.js` at all, and why the old 0.2.1 release notes exist in the release history at all, describing how people who do not use npm or a bundler access the library through a global. For a React component, the README points you somewhere else entirely: `react-phone-number-input`, a separate package, so the form widget and the parser are separate decisions. The CI configuration in the tree is a mix of `.gitlab-ci.yml`, `.travis.yml` and `.nycrc`, which dates the project's setup to a period when GitLab CI was still being adopted alongside Travis, and `rollup.config.mjs` at the root shows the bundling is done with Rollup and its config file has been converted to ESM.
Every documented omission, taken seriously
The comparison section in the README is a list of things this library does not do, and it is more useful than most libraries' feature lists. Emergency numbers such as `911` are out, because a web form does not validate emergency calls. Short codes like `12345`, which are SMS-only numbers, are out. Numbers beginning with `*` are out, and the README gives two real examples: `*555` for reporting non-urgent traffic incidents in New Zealand, and Israeli advertising numbers. Australian 13-smart numbers are out. Alphabetic numbers like `1-800-GOT-MILK` are out, on the grounds that people do not type their phone numbers that way and it belonged to the push-button era. Two-in-one numbers with combined extensions such as `(530) 583-6985 x302/x2303` are out, because such a string actually represents two numbers and there is no correct single answer. Local numbers with the area code omitted, like `456-789` in place of `(123) 456-789`, are out, which the README justifies by arguing there are no local areas any more. That is a position, and a defensible one, but it is a position.
Behavioural differences that will surface as bugs in your app
Beyond the omissions, several methods behave differently from Google's library and these are the ones that generate support issues. Formatting does not use hyphens or brackets in international format; whitespace is used instead, on the reasoning that brackets mean nothing when there are no local areas and whitespace simply reads better. There is no geolocation feature, so you cannot ask a parsed number which city it belongs to. Non-geographic numbers, such as mobile satellite communication services, do not get `.country` set to the string `"001"`; `.country` is `undefined` and you call `.isNonGeographic()` on the `PhoneNumber` instance instead. There is no equivalent of `formatNumberForMobileDialing()`, which matters in Brazil and Colombia where carrier codes have to be prepended when calling a fixed line from a mobile phone inside the same country. The README's position is that this is not a dialing library, since it is not an Android phone operating system, though it does parse carrier codes correctly. One entry runs the other way: it fixes a bug where Canadian numbers beginning `+1310` were not considered possible. The list even names the specific countries affected by the carrier code rules, in a commented-out line: Australia, Bolivia, Brazil, China, Colombia, Croatia, Faroe Islands, South Korea, Liechtenstein, Luxembourg and Venezuela.
Metadata is a snapshot, and the repo admits it
The part of the tree that tells you how this project is really maintained is `PhoneNumberMetadata.xml`, sitting at the root next to `METADATA.md`. The XML file is the raw numbering data, and `METADATA.md` is the document explaining what was changed when converting it. That pairing means the library's accuracy is bounded by a data file that has to be regenerated when a country changes its numbering plan, and there is no way around that for any library in this space. The two `autoupdate` scripts at the root, `autoupdate.sh` and `autoupdate.cmd`, exist to do exactly that refresh, one for Unix shells and one for Windows. A `build-scripts/` directory holds the generation tooling, `test/` holds the suite, and `website/` holds the documentation site, which the README links as the demo at catamphetamine.gitlab.io. The release history is where this gets interesting, and it is worth reading carefully before you draw conclusions from it: the only two releases listed are 0.2.1 and 0.2.2, both published in December 2016, while `package.json` is at version 1.13.7. The npm versions moved for years without tagged releases, so the release list understates the project rather than describing it. The last recorded commit is 2026-06-18, which is recent enough that the project is being worked on now.
Editorial conclusion
Choose libphonenumber-js when you are validating a contact form, normalising a number for storage, or rendering a number back to a person, because that is the whole job and 145 kB does it well. Choose Google's library instead when you need emergency numbers, short codes, carrier codes for mobile dialing, or geolocation from a number, because those are the features this project deliberately leaves out. What you give up either way is certainty about numbering plans changing, since the metadata is a snapshot and `autoupdate.sh` and `autoupdate.cmd` exist precisely because someone has to run them.
Frequently asked questions
What is libphonenumber used for?
It parses and formats phone numbers, which mostly means validating that a number is possible for a country and rendering it back in a consistent format. libphonenumber-js does this for personal phone numbers and deliberately skips emergency numbers, short codes and geolocation.
Is libphonenumber-js available on NPM?
Yes, it is installed with npm. The README also mentions including it on a page directly through a script tag for people not using a bundler, and the package exposes CommonJS, ESM and per-metadata-tier entry points.
What are the differences between Google's libphonenumber and libphonenumber-js?
The main one is size: about 145 kB against Google's 550 kB, achieved by rewriting the code and letting you choose which metadata to include. It also comes with TypeScript definitions, can search for numbers inside text, and skips emergency numbers, short codes, alphabetic numbers and geolocation.
Who maintains libphonenumber?
Google develops the original libphonenumber for Android phones, and it is written in C++ and Java with an autogenerated JavaScript port. libphonenumber-js is a separate, community-maintained rewrite under the catamphetamine name on GitHub, released under MIT.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/catamphetamine-libphonenumber-js)