UNPKG

68.7 kBMarkdownView Raw
1# libphonenumber-js
2
3[![npm version](https://img.shields.io/npm/v/libphonenumber-js.svg?style=flat-square)](https://www.npmjs.com/package/libphonenumber-js)
4[![npm downloads](https://img.shields.io/npm/dm/libphonenumber-js.svg?style=flat-square)](https://www.npmjs.com/package/libphonenumber-js)
5[![coverage](https://img.shields.io/coveralls/catamphetamine/libphonenumber-js/master.svg?style=flat-square)](https://coveralls.io/r/catamphetamine/libphonenumber-js?branch=master)
6
7A simpler and smaller rewrite of Google Android's [`libphonenumber`](https://github.com/google/libphonenumber/blob/master/java/libphonenumber/) library in javascript.
8
9[See Demo](https://catamphetamine.gitlab.io/libphonenumber-js/)
10
11If 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).
12
13## LibPhoneNumber
14
15Google'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).
16
17With 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.
18
19<!-- 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. -->
20
21<!--
22One 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.
23-->
24
25## Difference from Google's `libphonenumber`
26
27 * 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).
28
29 * Can search for phone numbers in text (Google's autogenerated javascript port can't).
30
31 * Doesn't parse or format special "local"-only phone numbers: numbers specific to a "local" area (for example, a city) with the "area code" omitted (like `456-789` with the "area code" `(123)` omitted vs. the full `(123) 456-789` number), emergency phone numbers like `911`, ["short codes"](https://support.twilio.com/hc/en-us/articles/223182068-What-is-a-short-code-) (short SMS-only numbers), numbers starting with a [`*`](https://github.com/googlei18n/libphonenumber/blob/master/FALSEHOODS.md) (like `*555`), etc. The aim of this library is parsing and formatting people's phone numbers.
32
33 * Doesn't provide an equivalent of `formatNumberForMobileDialing()` function that returns a number formatted in such a way that it can be dialed from a mobile phone within a specific country. For example, it adds ["carrier codes"](https://www.bandwidth.com/glossary/carrier-identification-code-cic/) when dialing within certain countries (Brazil, Colombia). Since this is not a dialing library, it doesn't provide such a function and doesn't use "carrier codes" when formatting phone numbers.
34
35 <!-- (Australia, Bolivia, Brazil, China, Colombia, Croatia, Faroe Islands, South Korea, Liechtenstein, Luxembourg, Venezuela) -->
36
37 <!--
38 for (var code of Object.keys(metadata.countries)) {
39 var country = metadata.countries[code]
40 if (country.formats && country.formats.find(_ => _.domestic_carrier_code_formatting_rule)) {
41 console.log(code)
42 }
43 }
44 -->
45
46 * Doesn't parse alphabetic phone numbers like `1-800-GOT-MILK`: people don't input their phone numbers in this format, it's only used in advertisement.
47
48 * Doesn't parse "combined" extensions into two separate numbers (example: `(530) 583-6985 x302/x2303`): people don't input their phone numbers in this format.
49
50 * Doesn't use hyphens and brackets when formatting international phone numbers, only whitespace: seems more logical this way.
51
52 * Doesn't use the `"001"` country code for ["non-geographic"](#non-geographic) phone numbers. Instead, `PhoneNumber` class has an `.isNonGeographic()` method.
53
54 <!--
55 * 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.
56 (`.formatNumberForMobileDialing()` method is not implemented therefore there's no need to format carrier codes)
57 -->
58
59## GitHub
60
61On 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) 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.
62
63## Install
64
65via [npm](https://npmjs.org/)
66
67```sh
68$ npm install libphonenumber-js --save
69```
70
71via [yarn](https://yarnpkg.com)
72
73```sh
74$ yarn add libphonenumber-js
75```
76
77If you're not using a bundler then use a [standalone version from a CDN](https://gitlab.com/catamphetamine/libphonenumber-js/#cdn).
78
79## Use
80
81### Parse phone number
82
83<!--
84_(new API)_
85-->
86
87```js
88import parsePhoneNumber from 'libphonenumber-js'
89
90const phoneNumber = parsePhoneNumber('Phone: 8 (800) 555 35 35.', 'RU')
91if (phoneNumber) {
92 phoneNumber.country === 'RU'
93 phoneNumber.number === '+78005553535'
94 phoneNumber.isValid() === true
95 // Note: `.getType()` requires `/max` metadata: see below for an explanation.
96 phoneNumber.getType() === 'TOLL_FREE'
97}
98```
99
100<!--
101<details>
102<summary>Legacy API</summary>
103
104```js
105import { parseNumber } from 'libphonenumber-js'
106
107parseNumber('Phone: 8 (800) 555 35 35.', 'RU')
108// Outputs: { country: 'RU', phone: '8005553535' }
109```
110</details>
111-->
112
113### Format phone number
114
115<!--
116_(new API)_
117-->
118
119```js
120import parsePhoneNumber from 'libphonenumber-js'
121
122const phoneNumber = parsePhoneNumber('+12133734253')
123
124phoneNumber.formatInternational() === '+1 213 373 4253'
125phoneNumber.formatNational() === '(213) 373-4253'
126phoneNumber.getURI() === 'tel:+12133734253'
127```
128
129<!--
130<details>
131<summary>Legacy API</summary>
132
133```js
134import { formatNumber } from 'libphonenumber-js'
135
136formatNumber('+12133734253', 'INTERNATIONAL')
137// Outputs: '+1 213 373 4253'
138
139formatNumber('+12133734253', 'NATIONAL')
140// Outputs: '(213) 373-4253'
141
142formatNumber({ country: 'US', phone: '2133734253' }, 'INTERNATIONAL')
143// Outputs: '+1 213 373 4253'
144
145formatNumber({ country: 'US', phone: '2133734253' }, 'NATIONAL')
146// Outputs: '(213) 373-4253'
147```
148</details>
149-->
150
151### "As You Type" formatter
152
153```js
154import { AsYouType } from 'libphonenumber-js'
155
156new AsYouType().input('+12133734')
157// Outputs: '+1 213 373 4'
158
159new AsYouType('US').input('2133734')
160// Outputs: '(213) 373-4'
161```
162
163### Full-text search
164
165<!--
166_(new API)_
167-->
168
169```js
170import { findPhoneNumbersInText } from 'libphonenumber-js'
171
172findPhoneNumbersInText(`
173 For tech support call +7 (800) 555-35-35 internationally
174 or reach a local US branch at (213) 373-4253 ext. 1234.
175`, 'US')
176
177// Outputs:
178//
179// [{
180// number: PhoneNumber {
181// country: 'RU',
182// countryCallingCode: '7',
183// number: '+78005553535',
184// nationalNumber: '8005553535'
185// },
186// startsAt : 22,
187// endsAt : 40
188// }, {
189// number: PhoneNumber {
190// country: 'US',
191// countryCallingCode: '1',
192// number: '+12133734253',
193// nationalNumber: '2133734253',
194// ext: '1234'
195// },
196// startsAt : 86,
197// endsAt : 110
198// }]
199```
200
201## "min" vs "max" vs "mobile" vs "core"
202
203This 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:
204
205* `max` — The complete metadata set, is about `145 kilobytes` in size (`libphonenumber-js/metadata.full.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).
206
207* `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.
208
209* `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`).
210
211To use a particular metadata set, simply import functions from a relevant sub-package:
212
213* `libphonenumber-js/max`
214* `libphonenumber-js/min`
215* `libphonenumber-js/mobile`
216
217Importing functions directly from `libphonenumber-js` effectively results in using the `min` metadata.
218
219Sometimes (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.
220
221## Definitions
222
223### Country code
224
225"Country code" means either 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)). -->
226
227### Non-geographic
228
229There're several calling codes that don't belong to any country:
230
231* `+800` — [Universal International Toll Free Number](https://en.wikipedia.org/wiki/Toll-free_telephone_number)
232* `+808` — [Universal International Shared Cost Number](https://en.wikipedia.org/wiki/Shared-cost_service)
233* `+870` — [Inmarsat Global Limited](https://en.wikipedia.org/wiki/Inmarsat)
234* `+878` — [Universal Personal Telecommunications](https://en.wikipedia.org/wiki/Universal_Personal_Telecommunications)
235* `+881` — [Global Mobile Satellite System](https://en.wikipedia.org/wiki/Global_Mobile_Satellite_System)
236* `+882` and `+883` — [International Networks](https://en.wikipedia.org/wiki/International_Networks_(country_code))
237* `+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)
238* `+979` — [International Premium Rate Service](https://en.wikipedia.org/wiki/International_Premium_Rate_Service)
239
240Such phone numbering plans are called "non-geographic", and their phone numbers have `country` set to `undefined`.
241
242### National (significant) number
243
244"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`.
245
246### Country calling code
247
248"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.
249
250## API
251
252### parsePhoneNumberFromString(string, [options or defaultCountry]): PhoneNumber
253
254Parses a phone number from `string`.
255
256Can be imported both as a "default" export and as a "named" export.
257
258```js
259import parsePhoneNumberFromString from 'libphonenumber-js'
260// Or: import { parsePhoneNumberFromString } from 'libphonenumber-js'
261
262const phoneNumber = parsePhoneNumberFromString('Call: (213) 373-42-53 ext. 1234.', 'US')
263if (phoneNumber) {
264 console.log(phoneNumber.formatNational())
265}
266```
267
268Returns 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.
269
270Available `options`:
271
272* `defaultCountry` — Default country for parsing national numbers. Instead of passing `options.defaultCountry` one could pass `defaultCountry` argument directly.
273
274* `defaultCallingCode` — Default calling code for parsing national numbers. Some numbering plans are for ["non-geographic numbering plans"](#non-geographic) and they don't have a country code, so `defaultCountry` can't be specified for them.
275
276If 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:
277
278```js
279import { parsePhoneNumberWithError, ParseError } from 'libphonenumber-js'
280
281try {
282 const phoneNumber = parsePhoneNumberWithError('Call: (213) 373-42-53 ext. 1234.', 'US')
283} catch (error) {
284 if (error instanceof ParseError) {
285 // Not a phone number, non-existent country, etc.
286 console.log(error.message)
287 } else {
288 throw error
289 }
290}
291```
292
293<details>
294<summary>Possible errors</summary>
295
296* `INVALID_COUNTRY` — When `defaultCountry` doesn't exist (`parsePhoneNumber('(111) 222-3333', 'XX')`) or isn't supported by this library, or when parsing non-international number without a `defaultCountry` (`parsePhoneNumber('(111) 222-3333')`), or when international number country calling code doesn't exist (`parsePhoneNumber('+9991112223333')`).
297
298* `NOT_A_NUMBER` — When no phone number was found. For example, when there are no digits (`"abcde"`) or when there's not enough digits (`parsePhoneNumber('2', 'US')`, `parsePhoneNumber('+1')`).
299
300* `TOO_LONG` — When national (significant) number is too long (17 digits max) or when the string being parsed is too long (250 characters max).
301
302* `TOO_SHORT` — When national (significant) number is too short (for ex. 1 digit).
303</details>
304
305### `PhoneNumber`
306
307<!--
308`PhoneNumber` class constructor accepts two arguments: `country`/`countryCallingCode` and `nationalNumber`. Also `metadata`.
309
310```js
311const phoneNumber = new PhoneNumber('RU', '8005553535', metadata)
312```
313-->
314
315`PhoneNumber` class instance has the following properties:
316
317* `number: string` — The phone number in [`E.164`](https://en.wikipedia.org/wiki/E.164) format. Example: `"+12133734253"`.
318* `countryCallingCode: string` — The [country calling code](#country-calling-code). Example: `"1"`.
319* `nationalNumber: string` — The [national (significant) number](#national-significant-number). Example: `"2133734253"`.
320* `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).
321* `ext: string?` — The [phone number extension](https://en.wikipedia.org/wiki/Extension_(telephone)), if any. Example: `"1234"`.
322* `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.
323
324`PhoneNumber` class instance provides the following methods:
325
326#### `format(format: string, [options]): string`
327
328Formats the phone number into a string according to a `format`.
329
330Available `format`s:
331
332 * `NATIONAL` — Example: `"(213) 373-4253"`
333 * `INTERNATIONAL` — Example: `"+1 213 373 4253"`
334 * [`E.164`](https://en.wikipedia.org/wiki/E.164) — Example: `"+12133734253"`
335 * [`RFC3966`](https://www.ietf.org/rfc/rfc3966.txt) (the phone number URI) — Example: `"tel:+12133734253;ext=123"`
336 * `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`.
337
338Available `options`:
339
340 * `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.
341
342 * `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.
343
344Examples:
345
346```js
347import parsePhoneNumber from 'libphonenumber-js'
348
349const phoneNumber = parsePhoneNumber('+12133734253')
350
351phoneNumber.format("NATIONAL") === '(213) 373-4253'
352phoneNumber.format("INTERNATIONAL") === '+1 213 373 4253'
353phoneNumber.format("RFC3966") === 'tel:+12133734253'
354
355// Aliases
356phoneNumber.formatNational() === phoneNumber.format("NATIONAL")
357phoneNumber.formatInternational() === phoneNumber.format("INTERNATIONAL")
358phoneNumber.getURI() === phoneNumber.format("RFC3966")
359```
360
361#### `isPossible(): boolean`
362
363Checks if the phone number is "possible". Only checks the phone number length, doesn't check the number digits against any regular expressions.
364
365#### `isValid(): boolean`
366
367Checks if the phone number is "valid". First checks the phone number length and then checks the phone number digits against all available regular expressions.
368
369By 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.
370
371<details>
372<summary>See an example illustrating different results when using <code>/min</code> vs <code>/max</code> vs <code>/mobile</code></summary>
373
374####
375```js
376import parseMin from 'libphonenumber-js/min'
377import parseMax from 'libphonenumber-js/max'
378import parseMobile from 'libphonenumber-js/mobile'
379
380// Mobile numbers in Singapore starting from `8`
381// can only have the second digit in the range of `0..8`.
382// Here the second digit is `9` which makes it an invalid mobile number.
383// This is a "strict" (advanced) validation rule and is
384// not included in the (default) "min" bundle.
385
386// The basic number length check passes (`8..11`) and the
387// "loose" national number validation regexp check passes too:
388// `(?:1\d{3}|[369]|7000|8(?:\d{2})?)\d{7}`.
389parseMin('+6589555555').isValid() === true
390
391// The "advanced" validation regexp for mobile numbers is
392// `(?:8[1-8]|9[0-8])\\d{6}` and possible lengths are `8`.
393parseMax('+6589555555').isValid() === false
394parseMobile('+6589555555').isValid() === false
395```
396</details>
397
398####
399
400See also ["Using phone number validation feature"](#using-phone-number-validation-feature) considerations.
401
402<!--
403#### `isValidForRegion(country)`
404
405Is just an alias for `this.isValid() && this.country === country`.
406https://github.com/googlei18n/libphonenumber/blob/master/FAQ.md#when-should-i-use-isvalidnumberforregion
407-->
408
409#### `getType(): string?`
410
411Returns 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).
412
413By 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.
414
415<details>
416<summary>The list of possible return values</summary>
417
418####
419
420* `MOBILE`
421* `FIXED_LINE`
422* `FIXED_LINE_OR_MOBILE`
423* `PREMIUM_RATE`
424* `TOLL_FREE`
425* `SHARED_COST`
426* `VOIP`
427* `PERSONAL_NUMBER`
428* `PAGER`
429* `UAN`
430* `VOICEMAIL`
431</details>
432
433####
434
435<details>
436<summary>See an example illustrating different results when using <code>/min</code> vs <code>/max</code> vs <code>/mobile</code></summary>
437
438####
439```js
440import parseMin from 'libphonenumber-js/min'
441import parseMax from 'libphonenumber-js/max'
442import parseMobile from 'libphonenumber-js/mobile'
443
444// Singapore valid mobile number.
445
446// The (default) "min" bundle doesn't contain any regexps for
447// getting phone number type based on national number (for Singapore).
448parseMin('+6584655555').getType() === undefined
449
450// The "max" bundle contains regexps for
451// getting phone number type based on national number
452// for all possible phone number types.
453parseMax('+6584655555').getType() === 'MOBILE'
454
455// The "mobile" bundle contains regexps for
456// getting phone number type based on national number
457// for mobile phone numbers only.
458parseMobile('+6584655555').getType() === 'MOBILE'
459```
460</details>
461
462#### `isNonGeographic(): boolean`
463
464Returns `true` if the number belongs to a ["non-geographic numbering plan"](#non-geographic).
465
466#### `isEqual(phoneNumber: PhoneNumber): boolean`
467
468Compares two `PhoneNumber`s: returns `true` if they're equal, `false` otherwise.
469
470### `class` AsYouType([options or defaultCountry])
471
472Creates a formatter for a partially entered phone number.
473
474Available `options`:
475
476* `defaultCountry` — Default country for parsing national numbers. Instead of passing `options.defaultCountry` one could pass `defaultCountry` argument directly.
477
478* `defaultCallingCode` — Default calling code for parsing national numbers. Some numbering plans are for ["non-geographic numbering plans"](#non-geographic) and they don't have a country code, so `defaultCountry` can't be specified for them.
479
480The formatter instance has the following methods:
481
482 * `input(text: string)` — Appends text to the input. Returns the formatted phone number.
483
484 * `reset()` — Resets the input.
485
486```js
487new AsYouType().input('+12133734') === '+1 213 373 4'
488new AsYouType('US').input('2133734') === '(213) 373-4'
489```
490
491The formatter instance also provides the following getters:
492
493 * `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.
494
495 * `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.
496
497 * `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.
498
499```js
500// National phone number input example.
501
502const asYouType = new AsYouType('US')
503
504asYouType.input('2') === '2'
505asYouType.getNumber().number === '+12'
506asYouType.getChars() === '2'
507asYouType.getTemplate() === 'x'
508
509asYouType.input('1') === '21'
510asYouType.getNumber().number === '+121'
511asYouType.getChars() === '21'
512asYouType.getTemplate() === 'xx'
513
514asYouType.input('3') === '(213)'
515asYouType.getNumber().number === '+1213'
516asYouType.getChars() === '213'
517asYouType.getTemplate() === '(xxx)'
518
519asYouType.input('3734253') === '(213) 373-4253'
520asYouType.getNumber().number === '+12133734253'
521asYouType.getChars() === '2133734253'
522asYouType.getTemplate() === '(xxx) xxx-xxxx'
523
524// International phone number input example.
525
526const asYouType = new AsYouType()
527asYouType.input('+1-213-373-4253') === '+1 213 373 4253'
528asYouType.getNumber().country === 'US'
529asYouType.getNumber().number === '+12133734253'
530asYouType.getChars() === '+12133734253'
531asYouType.getTemplate() === 'xx xxx xxx xxxx'
532```
533
534 * `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 `"+"`.
535
536 * `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. Returns "country calling code" for ["non-geographic"](#non-geographic) phone numbering plans too.
537
538 * `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.
539
540 * `isPossible(): boolean` — Returns `true` if the phone number is "possible". Is just a shortcut for [`PhoneNumber.isPossible()`](#ispossible-boolean).
541
542 * `isValid(): boolean` — Returns `true` if the phone number is "valid". Is just a shortcut for [`PhoneNumber.isValid()`](#isvalid-boolean).
543
544<details>
545<summary>Legacy API (before version <code>1.6.0</code>)</summary>
546
547####
548
549For legacy API (before version `1.6.0`) the formatter instance provides the following getters:
550
551 * `country: string?` — Phone number [country](#country-code). Will return `undefined` if the country couldn't be derived from the number.
552
553 * `getNationalNumber(): string` — Returns the national (significant) number part of the phone number.
554
555 * `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).
556
557```js
558// National phone number input example.
559
560const asYouType = new AsYouType('US')
561
562asYouType.input('2') === '2'
563asYouType.getNationalNumber() === '2'
564
565asYouType.input('1') === '21'
566asYouType.getNationalNumber() === '21'
567
568asYouType.input('3') === '(213)'
569asYouType.getNationalNumber() === '213'
570
571asYouType.input('3734253') === '(213) 373-4253'
572asYouType.getNationalNumber() === '2133734253'
573
574// International phone number input example.
575
576const asYouType = new AsYouType()
577asYouType.input('+1-213-373-4253') === '+1 213 373 4253'
578asYouType.country === 'US'
579asYouType.getNationalNumber() === '2133734253'
580```
581</details>
582
583####
584
585"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).
586
587Google'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.
588
589### findPhoneNumbersInText(text: string, [defaultCountry: string?], [options]): object[]
590
591Searches for phone numbers in `text`.
592
593Available `options`:
594
595* `defaultCountry` — Default country for parsing national numbers. Instead of passing `options.defaultCountry` one could pass `defaultCountry` argument directly.
596
597* `defaultCallingCode` — Default calling code for parsing national numbers. Some numbering plans are for ["non-geographic numbering plans"](#non-geographic) and they don't have a country code, so `defaultCountry` can't be specified for them.
598
599```js
600import { findPhoneNumbersInText } from 'libphonenumber-js'
601
602findPhoneNumbersInText(`
603 For tech support call +7 (800) 555-35-35 internationally
604 or reach a local US branch at (213) 373-4253 ext. 1234.
605`, 'US')
606
607// Outputs:
608//
609// [{
610// number: PhoneNumber {
611// country: 'RU',
612// countryCallingCode: '7',
613// number: '+78005553535',
614// nationalNumber: '8005553535'
615// },
616// startsAt : 22,
617// endsAt : 40
618// }, {
619// number: PhoneNumber {
620// country: 'US',
621// countryCallingCode: '1',
622// number: '+12133734253',
623// nationalNumber: '2133734253',
624// ext: '1234'
625// },
626// startsAt : 86,
627// endsAt : 110
628// }]
629```
630
631(in previous versions, it was called `findNumbers()`)
632
633<details>
634<summary>Legacy API (before version <code>1.6.0</code>) example</summary>
635
636####
637
638```js
639import { findNumbers } from 'libphonenumber-js'
640
641findNumbers(`
642 For tech support call +7 (800) 555-35-35 internationally
643 or reach a local US branch at (213) 373-4253 ext. 1234.
644`, 'US')
645
646// Outputs:
647//
648// [{
649// phone : '8005553535',
650// country : 'RU',
651// startsAt : 22,
652// endsAt : 40
653// },
654// {
655// phone : '2133734253',
656// country : 'US',
657// ext : '1234',
658// startsAt : 86,
659// endsAt : 110
660// }]
661```
662</details>
663
664####
665
666By default it processes the whole text and then outputs the phone numbers found. If the text is very big (say, a hundred thousand characters) then it might freeze the user interface for a couple of seconds. To avoid such lags one can employ "iterator" approach using `searchPhoneNumbersInText()` to perform the search asynchronously (e.g. using `requestIdleCallback` or `requestAnimationFrame`).
667
668(in previous versions, it was called `searchNumbers()`)
669
670<details>
671<summary>Asynchronous search example using <code>searchPhoneNumbersInText()</code></summary>
672
673####
674
675ES6 iterator:
676
677```js
678import { searchPhoneNumbersInText } from 'libphonenumber-js'
679
680const text = `
681 For tech support call +7 (800) 555-35-35 internationally
682 or reach a local US branch at (213) 373-4253 ext. 1234.
683`
684
685async function() {
686 for (const number of searchPhoneNumbersInText(text, 'US')) {
687 console.log(number)
688 await new Promise(resolve => setTimeout(resolve, 0))
689 }
690 console.log('Finished')
691}
692```
693
694Java-style iterator (for those still not using ES6):
695
696```js
697import { PhoneNumberMatcher } from 'libphonenumber-js'
698
699const matcher = new PhoneNumberMatcher(`
700 For tech support call +7 (800) 555-35-35 internationally
701 or reach a local US branch at (213) 373-4253 ext. 1234.
702`, {
703 defaultCountry: 'US',
704 v2: true
705})
706
707// Search cycle iteration.
708const iteration = () => {
709 if (matcher.hasNext()) {
710 console.log(matcher.next())
711 setTimeout(iteration, 0)
712 } else {
713 console.log('Finished')
714 }
715}
716
717// Run the search.
718iteration()
719```
720</details>
721
722####
723
724Although Google's javascript port doesn't have the `findPhoneNumbersInText()` functionality the Java and C++ ports do. I guess Google just doesn't need to crawl phone numbers on Node.js because they can afford to hire a Java/C++ developer to do that. Still, javascript nowadays is the most popular programming language given its simplicity and user-friendliness. The `findPhoneNumbersInText()` function provided is a port of Google's `PhoneNumberMatcher.java` into javascript.
725
726### getExampleNumber(country: string, examples: object): PhoneNumber
727
728Returns an example phone number for a [country](#country-code). Returns an instance of [`PhoneNumber`](#phonenumber) class. Will return `undefined` if `country` doesn't exist or isn't supported by this library.
729
730```js
731import examples from 'libphonenumber-js/examples.mobile.json'
732import { getExampleNumber } from 'libphonenumber-js'
733
734const phoneNumber = getExampleNumber('RU', examples)
735
736phoneNumber.formatNational() === '8 (912) 345-67-89'
737```
738
739### isSupportedCountry(country: string): boolean
740
741Checks if a country is supported by this library.
742
743```js
744isSupportedCountry('RU') === true
745isSupportedCountry('XX') === false
746```
747
748### getCountries(): string[]
749
750Returns a list of supported countries.
751
752<!-- (excluding `"001"` that stands for ["non-geographic entity"](#non-geographic)). -->
753
754```js
755getCountries() === ["AC", "AD", ...]
756```
757
758### getCountryCallingCode(country: string): string
759
760Returns [country calling code](#country-calling-code) for a [country](#country-code). Will throw an error if `country` doesn't exist or isn't supported by this library.
761
762```js
763getCountryCallingCode('RU') === '7'
764getCountryCallingCode('IL') === '972'
765```
766
767### getExtPrefix(country: string): string
768
769Returns phone number extension prefix for a given `country`. If no custom ext prefix is defined for a `country` then the default `" ext. "` prefix is returned.
770
771```js
772getExtPrefix('US') === ' ext. '
773getExtPrefix('GB') === ' x'
774```
775
776<!--
777### parsePhoneNumberCharacter(nextCharacter, prevParsedCharacters)
778
779Parses next character while parsing phone number digits (including a `+`) from text: discards everything except `+` and digits, and `+` is only allowed at the start of a phone number.
780
781For example, is used in [`input-format`](https://gitlab.com/catamphetamine/input-format).
782
783```js
784// Suppose a user inputs "+1 (213) 373-42-53".
785
786parsePhoneNumberCharacter('+', undefined) === '+'
787parsePhoneNumberCharacter('1', '+') === '1'
788parsePhoneNumberCharacter(' ', '+1') === undefined
789parsePhoneNumberCharacter('(', '+1') === undefined
790parsePhoneNumberCharacter('2', '+1') === '2'
791parsePhoneNumberCharacter('1', '+12') === '1'
792parsePhoneNumberCharacter('3', '+121') === '3'
793parsePhoneNumberCharacter(')', '+1213') === undefined
794parsePhoneNumberCharacter(' ', '+1213') === undefined
795parsePhoneNumberCharacter('3', '+1213') === '3'
796parsePhoneNumberCharacter('7', '+12133') === '7'
797parsePhoneNumberCharacter('3', '+121337') === '3'
798parsePhoneNumberCharacter('-', '+121337') === undefined
799parsePhoneNumberCharacter('4', '+1213373') === '4'
800parsePhoneNumberCharacter('2', '+12133734') === '2'
801parsePhoneNumberCharacter('-', '+12133734') === undefined
802parsePhoneNumberCharacter('5', '+121337342') === '5'
803parsePhoneNumberCharacter('3', '+1213373425') === '3'
804```
805-->
806
807### parseDigits(text: string): string
808
809Parses digits from string. Can be used for building a phone number extension input component (e.g. [react-phone-number-input](https://gitlab.com/catamphetamine/react-phone-number-input/)).
810
811```js
812parseDigits('x123') === '123'
813parseDigits('٤٤٢٣') === '4423'
814```
815
816### parseIncompletePhoneNumber(text: string): string
817
818Parses phone number characters (`+` and digits). Can be used for building a phone number input component (e.g. [react-phone-number-input](https://gitlab.com/catamphetamine/react-phone-number-input/)).
819
820```js
821parseIncompletePhoneNumber('8 (800) 555') === '8800555'
822parseIncompletePhoneNumber('+7 800 555') === '+7800555'
823parseIncompletePhoneNumber('+٤٤٢٣٢٣٢٣٤') === '+442323234'
824```
825
826### formatIncompletePhoneNumber(value: string, country: string?): string
827
828Formats incomplete phone number as a national one for a given `country`. If `country` is not specified then outputs the phone number in international format. This is just an alias for `new AsYouType(country, metadata).input(value)`. Can be used for building a phone number input component (e.g. [react-phone-number-input](https://gitlab.com/catamphetamine/react-phone-number-input/)).
829
830```js
831formatIncompletePhoneNumber('8800555', 'RU') === '8 (800) 555'
832formatIncompletePhoneNumber('+7800555') === '+7 800 555'
833```
834
835## Legacy API
836
837<details>
838<summary>Legacy API (before version <code>1.6.0</code>): <code>parse()</code>, <code>parseNumber()</code>, <code>format()</code>, <code>formatNumber()</code>, <code>isValidNumber()</code>, <code>getNumberType()</code>.</summary>
839
840### parseNumber(text, [defaultCountry], [options])
841
842_(previously called `parse()`)_
843
844_(legacy API)_
845
846Attempts to parse a phone number from `text`.
847
848If [`defaultCountry`](#country-code) is passed then it's gonna be the default country for parsing non-international phone numbers.
849
850Returns `{ country, phone, ext }` object where
851 * `country` is a [country code](#country-code).
852 * `phone` is a [national (significant) number](#national-significant-number).
853 * `ext` is a [phone number extension](https://en.wikipedia.org/wiki/Extension_(telephone)).
854
855If the phone number supplied isn't valid then an empty object `{}` is returned.
856
857<details>
858<summary>Examples</summary>
859
860```js
861// Parses international numbers.
862parseNumber('+1 213 373 4253') === { country: 'US', phone: '2133734253' }
863parseNumber('Phone: +1-213-373-4253.') === { country: 'US', phone: '2133734253' }
864parseNumber('+12133734253') === { country: 'US', phone: '2133734253' }
865
866// Parses national numbers provided a default country.
867parseNumber('Phone: (213) 373-4253.', 'US') === { country: 'US', phone: '2133734253' }
868
869// Parses phone number extensions.
870parseNumber('(213) 373-4253 ext. 123', 'US') === { country: 'US', phone: '2133734253', ext: '123' }
871
872// Parses RFC 3966 phone number URIs.
873parseNumber('tel:+78005553535;ext=123') === { country: 'RU', phone: '8005553535', ext: '123' }
874```
875
876If the phone number supplied isn't valid then an empty object `{}` is returned.
877
878```js
879parseNumber('+1 111 111 1111') === {}
880parseNumber('(111) 111-1111', 'US') === {}
881parseNumber('abcdefg') === {}
882```
883</details>
884
885####
886
887Available `options`:
888
889 * `defaultCountry : string` — Same as the `defaultCountry` argument.
890
891 * `extended : boolean` — If set to `true` then `parseNumber()` will attempt to parse even a remotely hypothetical phone number even if it is considered "invalid".
892
893<details>
894<summary><code>{ extended: true }</code> documentation and examples</summary>
895
896The result of "extended" parsing is an object where
897
898 * `country` is a [country code](#country-code).
899 * `phone` is a [national (significant) number](#national-significant-number).
900 * `ext` is a [phone number extension](https://en.wikipedia.org/wiki/Extension_(telephone)).
901 * `countryCallingCode` is a [country calling code](#country-calling-code).
902 * [`carrierCode`](https://www.voip-info.org/carrier-identification-codes/)s are only used in Colombia and Brazil and only when dialing within those countries from a mobile phone to a fixed line number.
903 * `valid: boolean` — whether it's a "valid" (real) phone number.
904 * `possible: boolean` — a phone number is considered "possible" when it fits the phone number length rules for a given country. E.g. for US national (significant) number regexp is `[2-9]\d{9}` and possible national (significant) number length is `10` so a phone number `(111) 111-1111` is not a "valid" number because it doesn't match the US national (significant) number regexp but it is a "possible" number because it's `10` digits long.
905 * Some or all of these properties may be absent from the result object.
906
907```js
908// If the number is valid.
909parseNumber('Phone: (213) 373-4253.', 'US', { extended: true }) ===
910{
911 country: 'US',
912 phone: '2133734253',
913 ext: undefined,
914 countryCallingCode: 1,
915 carrierCode: undefined,
916 valid: true,
917 possible: true
918}
919
920// If the number is not "valid" but "possible".
921parseNumber('(111) 111-1111', 'US', { extended: true }) ===
922{
923 country: 'US',
924 phone: '1111111111',
925 ext: undefined,
926 countryCallingCode: 1,
927 carrierCode: undefined,
928 valid: false,
929 possible: true
930}
931
932// If the number is not "valid" but "possible"
933// and country can't be derived from it.
934// (e.g. can't tell if it's a US number or a Canadian number)
935parseNumber('+1 111 111 1111', { extended: true }) ===
936{
937 country: undefined,
938 phone: '1111111111',
939 ext: undefined,
940 countryCallingCode: 1,
941 carrierCode: undefined,
942 valid: false,
943 possible: true
944}
945
946// If the number is not "possible" (invalid length).
947parseNumber('(213) 373', 'US', { extended: true }) ===
948{
949 country: 'US',
950 phone: '213373',
951 ext: undefined,
952 countryCallingCode: 1,
953 carrierCode: undefined,
954 valid: false,
955 possible: false
956}
957
958// In some cases if the number is extremely not "possible"
959// then an empty object `{}` is returned.
960//
961// Too short (or too long) for any country's phone number.
962parseNumber('1', 'US', { extended: true }) === {}
963// Non-existent country calling code.
964parseNumber('+210', { extended: true }) === {}
965// No phone number found.
966parseNumber('abcdefg', 'US', { extended: true }) === {}
967```
968
969The "extended" parsing mode is the default behaviour of the original Google's `libphonenumber`: it still returns parsed data even if the phone number being parsed is not considered valid (but is kinda "possible"). I guess this kind of behaviour is better for crawling websites for phone numbers because when mining "big data" it is better to extract all possible info rather than discard some pieces of it prematurely, e.g. when national (significant) number regexp for some country gets outdated which might very well happen because phone numbering plans are changing constantly around the world. Maybe after all it would make sense to make the "extended" parsing mode the default one in the next major version. I guess it would.
970</details>
971
972####
973
974<details>
975<summary>Also parses IDD-prefixed phone numbers</summary>
976
977Sometimes users icorrectly input phone numbers in ["out-of-country" dialing](https://wikitravel.org/en/International_dialling_prefix) (IDD-prefixed) format instead of the proper international phone number format (the "+" notation). In such cases `parseNumber()` will attempt to parse such IDD-prefixed numbers if "default country" is provided:
978
979```js
980// International format.
981parseNumber('+61 2 3456 7890') === { country: 'AU', phone: '234567890' }
982// IDD-prefixed format.
983parseNumber('011 61 2 3456 7890', 'US') === { country: 'AU', phone: '234567890' }
984```
985</details>
986
987### formatNumber(number, format, [options])
988
989_(previously called `format()`)_
990
991_(legacy API)_
992
993Formats a `number` into a string according to a `format`.
994
995Available `format`s and `options` are the same as for [`PhoneNumber.format(format)`](#formatformat-string-options).
996
997The `number` argument must be either a result of `parseNumber()` function call (to strip national prefix) or an E.164 phone number string (e.g. `+12133734253`).
998
999<details>
1000<summary>Examples</summary>
1001
1002```js
1003// Formats E.164 phone numbers.
1004formatNumber('+12133734253', 'NATIONAL') === '(213) 373-4253'
1005formatNumber('+12133734253', 'INTERNATIONAL') === '+1 213 373 4253'
1006
1007// Formats E.164 phone numbers when
1008// they're not "valid" but still "possible".
1009formatNumber('+11111111111', 'NATIONAL') === '(111) 111-1111'
1010formatNumber('+11111111111', 'INTERNATIONAL') === '+1 111 111 1111'
1011
1012// Formats E.164 phone numbers when
1013// they're not "valid" and not "possible" (invalid length).
1014formatNumber('+11111', 'NATIONAL') === '1111'
1015formatNumber('+11111', 'INTERNATIONAL') === '+1 1111'
1016
1017// Formats a result of `parseNumber()` function call.
1018const parsedNumber = parseNumber('2133734253', 'US')
1019formatNumber(parsedNumber, 'NATIONAL') === '(213) 373-4253'
1020formatNumber(parsedNumber, 'INTERNATIONAL') === '+1 213 373 4253'
1021
1022// Formats a result of `parseNumber()` function call in "extended" mode
1023// when it's not a "valid" number but is still a "possible" one.
1024const possibleNumber = parseNumber('+11111111111', { extended: true })
1025formatNumber(possibleNumber, 'NATIONAL') === '(111) 111-1111'
1026formatNumber(possibleNumber, 'INTERNATIONAL') === '+1 111 111 1111'
1027
1028// Formats a result of `parseNumber()` function call in "extended" mode
1029// when it's neither a "valid" number nor a "possible" one (invalid length).
1030const possibleNumber = parseNumber('+11111', { extended: true })
1031formatNumber(possibleNumber, 'NATIONAL') === '1111'
1032formatNumber(possibleNumber, 'INTERNATIONAL') === '+1 1111'
1033
1034// Formats phone number extensions.
1035formatNumber({ country: 'US', phone: '2133734253', ext: '123' }, 'NATIONAL') === '(213) 373-4253 ext. 123'
1036
1037// When given an object not having `phone` property
1038// (e.g. a empty object `{}`) it will throw.
1039formatNumber({}) throws Error
1040```
1041</details>
1042
1043### getNumberType(number, [defaultCountry])
1044
1045_(legacy API)_
1046
1047See the description for [`PhoneNumber.getType()`](#gettype).
1048
1049The `number` argument can be either a result of the `parseNumber()` function call — `{ country, phone }` — or a string (phone number digits only) possibly accompanied with the second `defaultCountry` argument.
1050
1051<details>
1052<summary>Examples</summary>
1053
1054```js
1055getNumberType('+79160151539') === 'MOBILE'
1056getNumberType('9160151539', 'RU') === 'MOBILE'
1057getNumberType({ phone: '9160151539', country: 'RU' }) === 'MOBILE'
1058```
1059</details>
1060
1061### isValidNumber(number, [defaultCountry])
1062
1063_(legacy API)_
1064
1065Checks if a phone number is valid, the validation is more strict than `parseNumber()`.
1066
1067The `number` argument can be either a result of the `parseNumber()` function call — `{ country, phone }` — or a string (phone number digits only) possibly accompanied with the second `defaultCountry` argument.
1068
1069<details>
1070<summary>Examples</summary>
1071
1072```js
1073isValidNumber('+12133734253') === true
1074isValidNumber('+1213373') === false
1075
1076isValidNumber('2133734253', 'US') === true
1077isValidNumber('21337', 'US') === false
1078
1079isValidNumber({ phone: '2133734253', country: 'US' }) === true
1080```
1081</details>
1082
1083####
1084
1085<details>
1086<summary>The difference between using <code>parseNumber()</code> and <code>isValidNumber()</code></summary>
1087
1088The difference between using `parseNumber()` and `isValidNumber()` for phone number validation is that `isValidNumber()` also checks the precise regular expressions of possible phone numbers for a country. For example, for Germany `parseNumber('123456', 'DE')` would return `{ country: 'DE', phone: '123456' }` because this phone number matches the general phone number rules for Germany (basic length check, etc). But, if the metadata is compiled with `--extended` (or relevant `--types`) flag (see [Customizing metadata](#customizing-metadata) section of this document) then `isValidNumber()` is gonna use those precise regular expressions for extensive validation and `isValid('123456', 'DE')` will return `false` because the phone number `123456` doesn't actually exist in Germany.
1089
1090This is how it is implemented in the original Google's [`libphonenumber`](https://static.javadoc.io/com.googlecode.libphonenumber/libphonenumber/8.9.1/com/google/i18n/phonenumbers/PhoneNumberUtil.html#parse-java.lang.CharSequence-java.lang.String-): `parseNumber()` parses phone numbers and loosely validates them while `isValidNumber()` validates phone numbers precisely (provided the precise regular expressions are included in metadata).
1091
1092The precise regular expressions aren't included in the default metadata because that would cause the default metadata to grow twice in its size: the complete ("full") metadata size is about 145 kilobytes while the reduced ("default") metadata size is about 77 kilobytes. Hence in the default configuration `isValidNumber()` performs absolutely the same "lite" validation as `parseNumber()`. For enabling extensive phone number validation the simplest way is to import functions from `libphonenumber-js/custom` module and supply them with `libphonenumber-js/metadata.full.json`. For generating custom metadata see the instructions provided in the [Customizing metadata](#customizing-metadata) section of this document.
1093</details>
1094
1095####
1096
1097<details>
1098<summary><code>isValidNumberForRegion()</code></summary>
1099
1100The optional `defaultCountry` argument is the _default_ country, i.e. it does not restrict to just that country, e.g. in those cases where several countries share the same phone numbering rules (NANPA, Britain, etc). For example, even though the number `07624 369230` belongs to the Isle of Man ("IM" country code) calling `isValidNumber('07624369230', 'GB')` still returns `true` because the country is not restricted to `GB`, it's just that `GB` is the default one for the phone numbering rules. For restricting the country see `isValidNumberForRegion()` though restricting a country [might not be a good idea](https://github.com/googlei18n/libphonenumber/blob/master/FAQ.md#when-should-i-use-isvalidnumberforregion).
1101
1102```js
1103// Even though '07624 369230' number belongs to the Isle of Man ("IM")
1104// the `defaultCountry` argument "GB" still works here because
1105// "GB" and "IM" both share the same phone numbering rules ("+44").
1106isValidNumber('07624369230', 'GB') === true
1107isValidNumber('07624369230', 'IM') === true
1108
1109// Imposing country restrictions.
1110isValidNumberForRegion('07624369230', 'GB') === false
1111isValidNumberForRegion('07624369230', 'IM') === true
1112```
1113</details>
1114</details>
1115
1116## Using phone number validation feature
1117
1118I personally don't use strict phone number validation in my projects because telephone numbering plans sometimes change and so validation rules can change too which means that [`PhoneNumber.isValid()`](#isvalid) function may become outdated if a website isn't re-deployed regularly. For example:
1119
1120* New phone number rules can be added to Google's `libphonenumber` library after they have already been implemented in real life (which can introduce a delay).
1121
1122<!--
1123* Then those new rules from Google's `libphonenumber` are updated automatically in this library (the scheduled update script introduces a small delay of 1 day, unless it malfunctions).
1124-->
1125
1126* After that those new rules from Google's `libphonenumber` are merged in this library (another delay).
1127
1128* And then there's still the web application itself using this library and until a developer installs `libphonenumber-js@latest` manually and rebuilds and redeploys the web application, it's gonna use the old (potentially outdated) phone number validation rules which could result in losing rare customers with newly valid (but previously non-valid) phone numbers if a website form is too strict about validating user's input.
1129
1130Phone number validation rules are [being updated regularly](https://github.com/googlei18n/libphonenumber/commits/master/resources/PhoneNumberMetadata.xml) in Google's repo. Imagine a web application (for example, a "promo-site" or a "personal website") with a "Contact Us" form being deployed once and then running for years without any maintenance.
1131
1132If it was required to validate a phone number being input by a user, then I'd personally use something like [`PhoneNumber.isPossible()`](#ispossible) that just validates phone number length.
1133
1134## React
1135
1136If you’re trying to build a React component with this library, take a look at [`react-phone-number-input`](https://www.npmjs.com/package/react-phone-number-input).
1137
1138## Bug reporting
1139
1140When reporting an issue one must also provide a link to [Google's `libphonenumber` demo page](https://libphonenumber.appspot.com/) illustrating the expected behaviour. This includes validation, parsing, formatting and "as you type" formatting. For example, for an Australian number `438 331 999` Google's demo [outputs four sections](https://libphonenumber.appspot.com/phonenumberparser?number=438331999&country=AU) — "Parsing Result", "Validation Results", "Formatting Results" and "AsYouTypeFormatter Results". In a bug report, first describe the observed `libphonenumber-js` demo result and then Google's demo result (with a link to it) which must differ from the observed `libphonenumber-js` demo result. If the observed `libphonenumber-js` demo result is the same as Google's demo result and you don't agree with Google's demo result then create an issue in [Google's repo](https://github.com/googlei18n/libphonenumber).
1141
1142<!--
1143Phone number validation bugs should **only** be reported if they appear when using [custom metadata functions](#customizing-metadata) fed with `metadata.full.json` because by default all functions in this library use the reduced metadata set which results in looser validation than the original Google `libphonenumber`'s. The [demo page](https://catamphetamine.gitlab.io/libphonenumber-js/) also uses the reduced metadata set and therefore its validation is also looser than the original Google `libphonenumber`'s.
1144
1145There is also a possibility of this library's demo metadata being outdated, or this library's metadata lagging behind Google's (I have to update it manually from time to time due to `ssh-agent` not working properly on Windows).
1146-->
1147
1148When reporting `findPhoneNumbersInText()` bugs one should know that `findPhoneNumbersInText()` code was ported from [Google's Java code](https://github.com/googlei18n/libphonenumber/blob/master/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberMatcher.java). I didn't write it myself, I just ported it. Therefore, it is unlikely that anyone other than Google will be fixing such bugs.
1149
1150## TypeScript
1151
1152[TypeScript support](https://gitlab.com/catamphetamine/libphonenumber-js/blob/master/index.d.ts) for this library is entirely community-driven. I myself don't use TypeScript. Send your pull requests.
1153
1154## CDN
1155
1156One can use any npm CDN service, e.g. [unpkg.com](https://unpkg.com) or [jsdelivr.com](https://jsdelivr.com)
1157
1158```html
1159<script src="https://unpkg.com/libphonenumber-js@[version]/bundle/libphonenumber-[type].js"></script>
1160
1161<script>
1162 alert(new libphonenumber.AsYouType('US').input('213-373-4253'))
1163</script>
1164```
1165
1166where `[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`.
1167
1168<!--
1169## Standalone
1170
1171For those who aren't using bundlers for some reason there's a way to build a standalone version of the library
1172
1173 * `git clone https://gitlab.com/catamphetamine/libphonenumber-js.git`
1174 * `npm install`
1175 * `npm run build`
1176 * See the `bundle` folder for `libphonenumber-js.min.js`
1177
1178```html
1179<script src="/scripts/libphonenumber-js.min.js"></script>
1180<script>
1181 alert(new libphonenumber.AsYouType('US').input('213-373-4253'))
1182</script>
1183```
1184-->
1185
1186## Metadata
1187
1188Metadata 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).
1189
1190### Programmatic access
1191
1192Metadata can be accessed programmatically by using the exported `Metadata` class.
1193
1194```js
1195import { Metadata } from 'libphonenumber-js/core'
1196import minMetadata from 'libphonenumber-js/metadata.min'
1197
1198const metadata = new Metadata(minMetadata)
1199// Select a country.
1200metadata.country('US')
1201
1202console.log(metadata.numberingPlan.leadingDigits())
1203console.log(metadata.numberingPlan.possibleLengths())
1204console.log(metadata.numberingPlan.IDDPrefix())
1205console.log(metadata.numberingPlan.defaultIDDPrefix())
1206```
1207
1208As 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 encouraged, but it's still used, for example, in [`react-phone-number-input`](https://gitlab.com/catamphetamine/react-phone-number-input/-/blob/master/source/phoneInputHelpers.js) to get "leading digits" for a country, or to get maximum phone number length for a country.
1209
1210<!--
1211Currently I have a script set up monitoring changes to `PhoneNumberMetadata.xml` in Google's repo and automatically releasing new versions of this library when metadata in Google's repo gets updated. So this library's metadata is supposed to be up-to-date. Still, in case the automatic metadata update script malfunctions some day, anyone can request metadata update via a Pull Request here on GitHub:
1212-->
1213
1214<!--
1215In case I forget to run the "autoupdate" script for a long time anyone can request metadata update via a Pull Request here on GitHub:
1216
1217 * Fork this repo
1218 * `npm install`
1219 * `npm run metadata:update:branch`
1220 * Submit a Pull Request to this repo from the `update-metadata` branch of your fork
1221
1222`npm run metadata:update:branch` command creates a new `update-metadata` branch, downloads the new [`PhoneNumberMetadata.xml`](https://github.com/googlei18n/libphonenumber/blob/master/resources/PhoneNumberMetadata.xml) into the project folder replacing the old one, generates JSON metadata out of the XML one, checks if the metadata has changed, runs the tests, commits the new metadata and pushes the commit to the remote `update-metadata` branch of your fork.
1223
1224Alternatively, a developer may wish to update metadata urgently, without waiting for a pull request approval. In this case just perform the steps described in the [Customizing metadata](#customizing-metadata) section of this document.
1225-->
1226
1227### Customizing metadata
1228
1229This library comes prepackaged with [three types of metadata](#min-vs-max-vs-mobile-vs-core).
1230
1231Sometimes, 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 (even when 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.
1232
1233See [generate custom metadata instructions](https://gitlab.com/catamphetamine/libphonenumber-metadata-generator).
1234
1235<details>
1236<summary>Then, use the generated <code>metadata.custom.json</code> file with the "core" functions.</summary>
1237
1238####
1239
1240Pass the `metadata` argument as the last one to the "core" functions.
1241
1242In ES6 that would be:
1243
1244```js
1245import {
1246 parsePhoneNumberFromString as _parsePhoneNumberFromString,
1247 findPhoneNumbersInText as _findPhoneNumbersInText,
1248 AsYouType as _AsYouType
1249} from 'libphonenumber-js/core'
1250
1251import metadata from 'libphonenumber-js/metadata.full.json'
1252
1253function call(func, _arguments) {
1254 var args = Array.prototype.slice.call(_arguments)
1255 args.push(metadata)
1256 return func.apply(this, args)
1257}
1258
1259export default function parsePhoneNumberFromString() {
1260 return call(_parsePhoneNumberFromString, arguments)
1261}
1262
1263export function findPhoneNumbersInText() {
1264 return call(_findPhoneNumbersInText, arguments)
1265}
1266
1267export function AsYouType(country) {
1268 return _AsYouType.call(this, country, metadata)
1269}
1270AsYouType.prototype = Object.create(_AsYouType.prototype, {})
1271AsYouType.prototype.constructor = AsYouType
1272```
1273
1274And for [Common.js](https://auth0.com/blog/javascript-module-systems-showdown/) environment that would be:
1275
1276```js
1277var core = require('libphonenumber-js/core')
1278var metadata = require('libphonenumber-js/metadata.full.json')
1279
1280function call(func, _arguments) {
1281 var args = Array.prototype.slice.call(_arguments)
1282 args.push(metadata)
1283 return func.apply(this, args)
1284}
1285
1286function parsePhoneNumberFromString() {
1287 return call(core.parsePhoneNumberFromString, arguments)
1288}
1289
1290exports = module.exports = parsePhoneNumberFromString
1291exports['default'] = parsePhoneNumberFromString
1292
1293exports.findPhoneNumbersInText = function findPhoneNumbersInText() {
1294 return call(core.findPhoneNumbersInText, arguments)
1295}
1296
1297exports.AsYouType = function AsYouType(country) {
1298 return core.AsYouType.call(this, country, metadata)
1299}
1300exports.AsYouType.prototype = Object.create(core.AsYouType.prototype, {})
1301exports.AsYouType.prototype.constructor = exports.AsYouType
1302```
1303</details>
1304
1305####
1306
1307<details>
1308<summary>Legacy: How to use the generated <code>metadata.custom.json</code> file with the legacy "custom" functions.</summary>
1309
1310####
1311
1312Pass the `metadata` argument as the last one to the "custom" functions.
1313
1314In ES6 that would be:
1315
1316```js
1317import {
1318 parseNumber,
1319 formatNumber,
1320 isValidNumber,
1321 getNumberType,
1322 AsYouType
1323} from 'libphonenumber-js/custom'
1324
1325import metadata from 'libphonenumber-js/metadata.full.json'
1326
1327parseNumber('+78005553535', metadata)
1328formatNumber({ phone: '8005553535', country: 'RU' }, metadata)
1329isValidNumber('+78005553535', metadata)
1330getNumberType('+78005553535', metadata)
1331new AsYouType('RU', metadata).input('+78005553535')
1332```
1333
1334And for [Common.js](https://auth0.com/blog/javascript-module-systems-showdown/) environment that would be:
1335
1336```js
1337var custom = require('libphonenumber-js/custom')
1338var metadata = require('libphonenumber-js/metadata.full.json')
1339
1340exports.parseNumber = function parseNumber() {
1341 var parameters = Array.prototype.slice.call(arguments)
1342 parameters.push(metadata)
1343 return custom.parseNumber.apply(this, parameters)
1344}
1345
1346exports.formatNumber = function formatNumber() {
1347 var parameters = Array.prototype.slice.call(arguments)
1348 parameters.push(metadata)
1349 return custom.formatNumber.apply(this, parameters)
1350}
1351
1352exports.isValidNumber = function isValidNumber() {
1353 var parameters = Array.prototype.slice.call(arguments)
1354 parameters.push(metadata)
1355 return custom.isValidNumber.apply(this, parameters)
1356}
1357
1358exports.getNumberType = function isValidNumber() {
1359 var parameters = Array.prototype.slice.call(arguments)
1360 parameters.push(metadata)
1361 return custom.getNumberType.apply(this, parameters)
1362}
1363
1364exports.AsYouType = function AsYouType(country) {
1365 custom.AsYouType.call(this, country, metadata)
1366}
1367
1368exports.AsYouType.prototype = Object.create(custom.AsYouType.prototype, {})
1369exports.AsYouType.prototype.constructor = exports.AsYouType
1370```
1371</details>
1372
1373Metadata should be re-generated each time the project is being deployed because Google constantly updates their metadata.
1374
1375<!-- ## To do -->
1376
1377<!--
1378## Automatic metadata update setup
1379
1380Create a daily (24 * 60 * 60) `launchd` job
1381
1382http://alvinalexander.com/mac-os-x/mac-osx-startup-crontab-launchd-jobs
1383
1384```sh
1385mkdir /Users/kuchumovn/work/libphonenumber-js-autoupdate
1386
1387git clone https://gitlab.com/catamphetamine/libphonenumber-js.git /Users/kuchumovn/work/libphonenumber-js-autoupdate
1388
1389cd /Users/kuchumovn/work/libphonenumber-js-autoupdate
1390
1391npm install
1392
1393chmod u+x /Users/kuchumovn/work/libphonenumber-js-autoupdate/autoupdate.sh
1394
1395nano ~/Library/LaunchAgents/com.gitlab.catamphetamine.libphonenumber-js.metadata-update.plist
1396
1397<?xml version="1.0" encoding="UTF-8"?>
1398<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
1399<plist version="1.0">
1400 <dict>
1401 <key>Label</key>
1402 <string>com.gitlab.catamphetamine.libphonenumber-js.metadata-update</string>
1403
1404 <key>ProgramArguments</key>
1405 <array>
1406 <string>/Users/kuchumovn/work/libphonenumber-js-autoupdate/autoupdate.sh</string>
1407 </array>
1408
1409 <key>Nice</key>
1410 <integer>1</integer>
1411
1412 <key>StartInterval</key>
1413 <integer>86400</integer>
1414
1415 <key>RunAtLoad</key>
1416 <true/>
1417
1418 <key>StandardErrorPath</key>
1419 <string>/tmp/libphonenumber.errors.txt</string>
1420
1421 <key>StandardOutPath</key>
1422 <string>/tmp/libphonenumber.output.txt</string>
1423 </dict>
1424</plist>
1425
1426launchctl load ~/Library/LaunchAgents/com.gitlab.catamphetamine.libphonenumber-js.metadata-update.plist
1427
1428launchctl list | grep 'libphonenumber-js'
1429```
1430-->
1431
1432### Maintenance
1433
1434Google periodically releases new metadata with the changes described in the [release notes](https://github.com/googlei18n/libphonenumber/blob/master/release_notes.txt). Sometimes those are minor non-breaking updates, sometimes those are major-version breaking updates.
1435
1436Metadata update process is automated through an "autoupdate" script: see `autoupdate.cmd` (Windows) or `autoupdate.sh` (Linux/macOS). The script detects changes to `PhoneNumberMetadata.xml` in Google `libphonenumber`'s repo and if there are changes then it pulls the latest metadata, processes it, commits the changes to GitHub, builds a new version of the library and releases it to NPM. So this library's metadata is supposed to be up-to-date. I could set up this script to run automatically but on my Windows machine `ssh-agent` doesn't work properly so I run the "autoupdate" script manually from time to time.
1437
1438Also Google sometimes (very rarely) updates their code: [`phonenumberutil.js`](https://github.com/googlei18n/libphonenumber/blob/master/javascript/i18n/phonenumbers/phonenumberutil.js) (`parseNumber()`, `formatNumber()`, `isValidNumber()`, `getNumberType()`), [`AsYouTypeFormatter.java`](https://github.com/google/libphonenumber/blob/master/java/libphonenumber/src/com/google/i18n/phonenumbers/AsYouTypeFormatter.java) (`AsYouType`), [`PhoneNumberMatcher`](https://github.com/googlei18n/libphonenumber/blob/master/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberMatcher.java) (`findPhoneNumbersInText()`). The latest sync-up was performed on Nov 8th, 2020.
1439
1440## Contributing
1441
1442After cloning this repo, ensure dependencies are installed by running:
1443
1444```sh
1445npm install
1446```
1447
1448This module is written in ES6 and uses [Babel](http://babeljs.io/) for ES5
1449transpilation. Widely consumable JavaScript can be produced by running:
1450
1451```sh
1452npm run build
1453```
1454
1455Once `npm run build` has run, you may `import` or `require()` directly from
1456node.
1457
1458After developing, the full test suite can be evaluated by running:
1459
1460```sh
1461npm test
1462```
1463
1464Test coverage must remain at 100%:
1465
1466```sh
1467npm run test-coverage
1468```
1469
1470When you're ready to test your new functionality on a real project, you can run
1471
1472```sh
1473npm pack
1474```
1475
1476It will `build`, `test` and then create a `.tgz` archive which you can then install in your project folder
1477
1478```sh
1479npm install [module name with version].tar.gz
1480```
1481
1482## Advertisement
1483
1484If you're looking for an international "2 days ago" javascript solution then check out [`javascript-time-ago`](https://gitlab.com/catamphetamine/javascript-time-ago).
1485
1486## License
1487
1488[MIT](LICENSE)