Phone Number Validation Test Cases: Formats & Edge Cases

Download 13 phone formatting test cases as CSV or JSON. Test region-aware parsing, leading zeros and E.164 output; explore international edge cases.

By Vincent RuanPublished September 4, 2026Last updated October 1, 202611 min read

Download phone number formatting test cases

13 fixed cases · Version 1 · Updated 2026-09-06. Each row includes the original input, test context, expected action, expected value and reason.

Test policy: These are offline contact-field formatting assertions, not carrier-validity or reachability verdicts. context supplies the default parsing region (US or GB); explicit + input is already international. This example policy normalizes NFKC digits and common display punctuation, supports 00 as an international prefix only for GB, and rejects extensions, letters, empty fields and emergency short codes. Preserve + and leading zeros through imports. A live-number validator may reject reserved fiction/drama numbers; that does not invalidate a formatting assertion. No SMS or calling operation belongs in this fixture run.

Preview cases and import instructions

JSON is an array of records. CSV uses the same keys and values. Load CSV through an import dialog with every column set to Text: automatic conversion can change leading zeros, plus signs, dates or strings that resemble formulas. JSON preserves Unicode and escaped control characters for automated tests. Empty expectedValue means rejection; it is not a replacement value to store.

Run the input through your implementation with the documented context, compare the action and expectedValue, then check storage and export round trips. Adjust policy-dependent cases to your product before using them as pass/fail gates. Keep the v1 filename with your test results.

First five cases. Quoted inputs use JSON notation so spaces remain visible.
CaseInputExpectedValue
phone-us-national"(415) 555-0142"normalize"+14155550142"
phone-us-country"1-415-555-0142"normalize"+14155550142"
phone-us-e164"+14155550142"accept"+14155550142"
phone-gb-national"020 7946 0958"normalize"+442079460958"
phone-gb-mobile"07700 900123"normalize"+447700900123"

Policy background: libphonenumber parsing and validation FAQ · Ofcom drama numbers. Sources explain the standards and design tradeoffs; they do not endorse every application choice in this fixture set.

Illustration for this article: Download 13 phone formatting test cases as CSV or JSON. Test region-aware parsing, leading zeros and E.164 output; explore international edge cases.

Names taught us to distrust validation, and birthdays taught us to distrust arithmetic. The third field in this series looks the easiest. A phone number is digits, and an international standard, E.164, says exactly how to write one. Yet phone-number code fails constantly, in a particular way.

A name is stored and displayed, and a birthday is calculated against. A phone number is interpreted. The same ten digits mean different things depending on the country's plan, whether the person typed the domestic or the international form, and what a spreadsheet did to the leading zero. Every phone validator is a small parser of the world's numbering plans, and those plans were never designed to be parsed.

What E.164 actually specifies — and what it leaves out

E.164 is the ITU-T recommendation that defines the international numbering plan [itu-e164]. A number in international format is a plus sign, a country code of one to three digits, and the national number. The whole thing, country code included, may be at most 15 digits [e164-wiki]. There are no spaces, brackets, hyphens, trunk prefix or extension. That is the entire specification: a prefix, a maximum length and a plus.

The trouble lives in what E.164 leaves out. It sets no minimum length. It says nothing about which numbers exist, or how people in each country write them. It hands the national part to roughly two hundred national plans that disagree about almost everything. Is the length fixed? Does the domestic form start with a prefix that must be removed? Is a leading zero that prefix or a real digit? A validator that 'checks E.164' checks the envelope. Everything below opens the letter.

PartLondon (Ofcom drama range)United States (fiction range)
Domestic form020 7946 0958(415) 555-0142 or 1-415-555-0142
Trunk prefix (dropped)0none — the 1 is the country code
Country code441
Area / destination code20415
Subscriber number7946 0958555 0142
E.164+442079460958 (12 digits)+14155550142 (11 digits)
E.164 ceiling15 digits15 digits
The same London number in its two written forms. In the domestic form the 0 is a trunk prefix; in E.164 it does not exist. The US number shows the North American twist: the 1 people dial for long distance is the country code itself, so there is nothing to strip.

The edge cases that actually break systems

The leading zero is not always a prefix

Across most of Europe, Africa and Asia, a domestic number starts with a 0 that is not part of the number. It is the trunk prefix, which tells the exchange 'a full national number follows', and it is dropped in international format. That is the rule everyone learns. It is wrong for nearly a quarter of the countries our generator supports.

Italy is the famous exception. Since 1998 the leading 0 of an Italian landline has been a permanent part of the number, dialled from abroad too. A Rome number written 06 6982 1234 is +39 06 6982 1234, zero and all [italy-wiki]. Strip the zero and you get a shorter, still plausible, different number. Mexico joined the group on 3 August 2019, when the regulator abolished the 01, 044 and 045 prefixes and made every number a flat ten digits [mexico-wiki]. A validator built on the old rule became wrong overnight. Its tests kept passing, because the fixtures encoded the same rule.

Even where a trunk prefix exists, it is not always a single zero. Russia's is 8, left over from the Soviet plan [russia-wiki]. Hungary's is the two-digit 06 [hungary-wiki]. A strip-one-zero rule leaves the 6 behind and makes a wrong number of the right length. Brazil's domestic long-distance form is a 0 plus a two-digit code for the chosen carrier. Those three digits change from call to call, so no constant can match them.

Google's libphonenumber team keeps a list of falsehoods programmers believe about phone numbers. One of them reads: 'a leading zero in numbers formatted for domestic usage can always be discarded when dialing from abroad'. Italy is the worked example [falsehoods].

Domestic trunk prefixCountries (of our 38)What strip-the-zero does
0, dropped in international formAustria, Australia, Belgium, China (geographic numbers only), Finland, France, Germany, India, Indonesia, Ireland, Israel, Japan, Netherlands, Nigeria, Romania, South Korea, Sweden, Switzerland, Taiwan, Thailand, Turkey, Ukraine, United Kingdom, VietnamCorrect — 24 countries
None — the leading digit belongs to the numberDenmark, Greece, Hong Kong, Italy, Mexico, Norway, Poland, Portugal, SpainCorrupts the number by deleting a significant digit — 9 countries
None — the 1 dialled for long distance is the country codeUnited States, CanadaHarmless by luck: there is no zero to strip
8RussiaLeaves the 8 in place: an 11-digit national number that fits no plan
06HungaryStrips the 0 and keeps the 6: a wrong number of the right length
0 + a two-digit carrier-selection codeBrazilLeaves the carrier code in: two extra digits that look like an area code
Trunk prefixes across the 38 countries our generator supports, from each regulator's numbering plan as filed with the ITU. The right-hand column is what the popular 'strip the leading zero, prepend the country code' shortcut does to each group.

Length is fixed only in North America

The North American Numbering Plan gives every number exactly ten digits after the country code. That is why so much US-written software assumes a phone number has one length. Germany has an open plan: area codes and subscriber numbers both vary, and there is no single national length [germany-wiki]. Our plan table records German national numbers from 6 to 13 digits, and Austria's from 4 to 13. Hong Kong has no area codes and no trunk prefix, and every number is a flat eight digits.

Ukraine (+380), Bangladesh (+880) and Hong Kong (+852) have three-digit country codes. That breaks any parser that peels off 'the first one or two digits'. E.164's only length rule is the 15-digit ceiling, so a 16-digit string is definitely invalid. One of our own bugs produced exactly that, as we will see.

Length is not even stable for one number. On 6 October 2019, every landline in Metro Manila's area code 2 grew from seven digits to eight by regulatory order [ph-wiki]. On 22 April 2000, the UK's Big Number Change replaced London's 0171 and 0181 with a single 020 and lengthened local numbers to eight digits [bnc-wiki]. Stored numbers did not update themselves on either date. A validator that rejected the new length would have rejected every resident of the capital. Numbering plans are law, and law changes. A test suite pinned to today's plan is a snapshot, not a proof.

A country code is not a country

Software loves to derive a country from a dial code, and that loses information both ways. Country code 1 is not the United States. The North American Numbering Plan spans twenty-five regions in twenty countries, so a +1 number may be in Jamaica, Bermuda or Guam [nanp-wiki]. Russia and Kazakhstan share code 7 [russia-wiki]. Code 44 also covers Guernsey, Jersey and the Isle of Man, none of which is in the United Kingdom, and 39 serves both Italy and Vatican City [cc-list].

The list of codes also grows. Kosovo's +383 only entered service in 2017 [cc-list]. A hardcoded list of country codes is a list of the countries that existed when the developer last looked. The libphonenumber falsehoods list includes 'each country calling code corresponds to exactly one country' and its twin, 'each country has only one country calling code' [falsehoods]. Both are false.

Digits that are not digits, and letters that are

1-800-FLOWERS is a real, dialable phone number. The letters map to digits through the keypad layout in ITU-T E.161 [e161]. So letters are legitimate input, and a system that rejects them rejects a number the network accepts. Extensions are the opposite problem. '415-555-0142 x204' is common in business contacts, but E.164 has no slot for an extension. The tel URI scheme in RFC 3966 gives it its own parameter, ';ext=', so it is never glued to the digits [rfc3966]. Store the extension in its own field. Never append it: +14155550142204 is a different, valid-looking 14-digit number.

Then there are digits that are not ASCII. In Egypt, phone numbers are often written in Arabic-Indic numerals. Japanese and Chinese keyboards produce full-width digits like 123 [falsehoods]. Most cleaning code, including ours, deletes everything that is not 0 to 9. That is fine for generated output. For a user typing in Cairo, it deletes the whole number and reports the field as empty. If you have international users, convert Unicode digits before you strip, or at least fail with a message instead of a blank.

The spreadsheet eats the zero

Phone numbers spend a surprising share of their lives in spreadsheets, and a spreadsheet treats a column of digits as numbers. Leading zeros vanish: the UK drama number 07700 900123 becomes 7700900123. In Italy, where the zero matters, the damage is permanent. Long values switch to scientific notation, so 447700900123 shows as 4.477E+11 and may be exported that way.

Excel keeps 15 significant digits and rounds anything longer to zeros. Microsoft's own guidance lists phone numbers among values to store as text [excel]. E.164's 15-digit ceiling fits inside that limit with nothing to spare: one stray digit and the last becomes a zero. Any pipeline that passes contacts through a spreadsheet needs a fixture with a leading zero to prove it survives.

A phone number is not an identity

The deepest falsehood is the one data models encode: that a phone number identifies one person. Numbers are recycled. The FCC runs a Reassigned Numbers Database because disconnected numbers are reissued, and the new holder gets the old holder's messages [rnd]. With portability, the area code no longer reveals location or carrier, and a number can outlive several moves and phones [falsehoods].

Households share landlines. One person carries a work number, a personal number and one from a previous country. Short codes and emergency numbers like 911, 112 and 999 are valid to dial and invalid as contact details. A unique constraint on a phone column, or a login that treats 'same phone' as 'same person', is a bug waiting for the first recycled number.

Numbers that are safe to put in test data

Random digits are the one thing not to use. Most random ten-digit strings belong to someone, and a staging system that texts its whole contact table is a classic incident. Numbering authorities reserve ranges for this reason. North America has the 555-0100 to 555-0199 block with any real area code; the history is in why fake phone numbers start with 555. The UK has Ofcom's drama ranges, such as 020 7946 0xxx and 07700 900xxx [fictitious-wiki].

Sandboxes publish their own. Twilio's test credentials treat +15005550006 as a valid, available number and +15005550001 as an invalid one, every time. An integration test can exercise both branches without a real line [twilio]. Every number in the table below comes from one of these ranges.

A phone-number fixture set worth copying

InputWhat it exercisesExpected behaviour
+14155550142Canonical E.164 in the NANP fiction rangeAccepted and stored exactly as given
(415) 555-0142Domestic formatting with brackets and hyphenNormalised to +14155550142
415-555-0142 x204An extensionExtension kept in its own field — never appended, never dropped
1-800-FLOWERSLetters as digits (E.161)Mapped to +18003569377, or rejected with an explicit message — never stored as letters
06 6982 1234 (Italy)Leading zero that is part of the number+390669821234 — not +39669821234
06 1 234 5678 (Hungary)Two-digit trunk prefix+3612345678
8 495 123 45 67 (Russia)Trunk prefix that is not zero+74951234567
01 55 1234 5678 (Mexico)A prefix abolished in 2019Rejected, or normalised to +525512345678 deliberately — never accepted as a 12-digit number
030 12345678 and 0201 123456 (Germany)Variable national lengthBoth valid: +493012345678 and +49201123456
2123 4567 (Hong Kong)Eight flat digits, no prefix, three-digit country code+85221234567
+44 (0) 20 7946 0958The bracketed-zero convention+442079460958 — the (0) is dropped
00442079460958The 00 international access prefix in GBSame number as the row above with GB parsing context; 00 is not universal
+4420794609581234Sixteen digitsRejected: over E.164's 15-digit ceiling
911 and 112Emergency numbersDialable, but rejected as a contact number
+81312345678Full-width digitsNormalised to +81312345678, or rejected with a message — never silently emptied
07700 900123 (UK drama range)A leading zero through export and importSurvives a CSV or spreadsheet round trip as text, then normalises to +447700900123
+15005550001A provider's documented invalid test numberThe sandbox returns 'invalid' every time — the negative branch is testable
Phone-number fixtures and the failure each one exercises. 'Normalise' means convert to E.164 in the form's country. Our generator's own converter returns these values for the domestic and international rows; it rejects the bracketed-zero, full-width and lettered forms, which a user-facing normaliser should handle.

As with the birthday fixtures, run each row through the record's whole life, not just the form. Store it, show it in national and international format, export it, import it, and check that what comes back is what went in. The Italy, Hungary and Russia rows catch a strip-the-zero normaliser. The Germany and Hong Kong rows catch a length check. The full-width and letter rows catch a normaliser that deletes what it does not understand. The drama-range row catches the spreadsheet someone added after the tests were written.

How our generator handles phone numbers — including the bugs we shipped

Every profile from our identity generator has a phone number in its country's national display format. Next to it sits a phoneE164 field for anyone who needs a standard value. The first version built that field the way most code does: strip the non-digits, add the dial code. Two bugs shipped together. A British number that faker produced as 0865 907 8593 became +4408659078593, trunk prefix still inside. A German number already in international form, +49-9019-07665907, became +4949901907665907. That is the country code twice and sixteen digits, over E.164's ceiling.

How common is that? We ran the retired shortcut over today's sample of 14,400 numbers outside North America. It produces 501 values over 15 digits, 3,627 with the country code repeated, and 6,566 with the trunk prefix left inside.

The obvious fix, stripping a leading zero before adding the dial code, would have been worse. It is wrong for eleven of our 38 countries: the nine where the leading digit matters and the two in North America with no zero at all. It also mishandles Russia's 8, Hungary's 06 and Brazil's carrier code. What shipped instead is a plan per country: the trunk prefix, if any, and the allowed range of national lengths, taken from each regulator's plan as filed with the ITU [itu-plans].

The converter tries candidates and checks them, instead of transforming and hoping. It builds every reading the digits could have: already international, with a trunk prefix, bare, or with a zero and a carrier code. It accepts the first reading that fits the country's lengths. If none fits, it leaves the field empty.

That empty-field rule is what caught the second bug. A Swedish number faker emitted as +46182195 has a six-digit national part, one short of the plan's minimum. The international reading failed, so the converter fell through to the bare reading. It added the country code to a string that already had it, producing +4646182195. Re-run over today's sample, that retired converter would get 33 Swedish, 50 Belgian, 28 Italian and 1 South Korean number wrong.

The fix was a rule about ambiguity. An explicit plus sign or a leading 00 says, without doubt, that what follows is international. If that reading does not fit the plan, there is no other reading to try. The honest description is that faker's template produced something Sweden's plan does not allow, and there is no correct E.164 for it.

Today's measurement covers 400 generated identities for each of our 38 countries, 15,200 phone numbers in all. 93.5% carry an E.164 value, and 32 countries convert fully. No value exceeds 15 digits, repeats its country code or falls outside its plan's length range. Six countries fall short:

CountryWith E.164Why the rest have none
Mexico23.5%Faker's template makes nine digits where the 2019 plan requires ten
Finland23.5%Faker has no Finnish phone data, so it falls back to US-style numbers with extensions
Italy38.5%The template writes a plus and another country's code, such as +40 or +77
Belgium77.3%Some numbers are ten digits, or seven after +32, where the plan allows eight or nine
Sweden91.8%Some international numbers have a six-digit national part, one below the minimum
South Korea99.8%One number in 400 has a six-digit national part
Share of generated numbers with an E.164 value, for the six countries below 100%. Measured on 1 October 2026 over 400 numbers each.

In every case the cause is upstream, in faker's locale data. We leave the field empty rather than launder those numbers into something that looks right. A consumer can handle a missing value. A plausible wrong one spreads into fixtures nobody rechecks. The full results, country by country, are in the measurement file.

The honest limit: valid structure is not the exact right digits. A length range cannot catch a strip that removes one digit too many. For Britain, Italy or Germany, that turns a legal ten-digit number into a legal nine-digit one, and Austria's 4-to-13 range barely limits anything. What pins the conversion is a verified national-to-E.164 example per country. The test suite round-trips 23 of them, and all pass. A worked example is the only check that catches a real mis-conversion.

The industry answer to exact digits is libphonenumber, whose metadata models what our schema cannot, such as Brazil's carrier codes. We chose not to use it for two reasons that matter to a fixture generator. Its metadata changes between releases, so the same seed would silently produce a different number after an upgrade and break the determinism this site guarantees. And it would add roughly half a megabyte to pages we keep small.

Use libphonenumber for richer parsing. Neither it nor we can prove a number is assigned or reachable. Our US phone tool uses the 555 fiction block, but other countries' format examples are not a guarantee that every output is unassigned.

The conclusion is the one this series keeps reaching: validate less, test more. Accept the letters, the full-width digits, the Arabic-Indic numerals and the thirteen-digit German number. Reject only what no plan on earth allows. Spend the effort you save on fixtures that walk each country's rules, and on totals that catch what row checks never will: how many numbers exceed 15 digits, and how many repeat their own country code.

For the earlier fields in this series, start with names and birthdays. For email inputs, download the fixed validation cases (JSON). For North American rules in depth, see how US area codes work. For more US fiction-range samples, the phone number generator offers state and area-code selection, three output formats and batches of up to 100. Use the API documentation for programmatic profiles. The downloadable cases above are fixed formatting checks, not a live-number verification service.

References & sources

  1. E.164: The international public telecommunication numbering plan — ITU-T
  2. E.164 — structure and the 15-digit maximum — Wikipedia
  3. Falsehoods programmers believe about phone numbers — Google libphonenumber
  4. Telephone numbers in Italy — the leading zero retained since 1998 — Wikipedia
  5. Telephone numbers in Mexico — the 3 August 2019 change to ten-digit dialling — Wikipedia
  6. Telephone numbers in Russia — trunk prefix 8, country code shared with Kazakhstan — Wikipedia
  7. Telephone numbers in Hungary — the 06 domestic prefix — Wikipedia
  8. Telephone numbers in Germany — an open numbering plan of variable length — Wikipedia
  9. Telephone numbers in the Philippines — the 6 October 2019 eight-digit migration — Wikipedia
  10. Big Number Change — 22 April 2000 — Wikipedia
  11. North American Numbering Plan — twenty-five regions in twenty countries — Wikipedia
  12. List of country calling codes — Wikipedia
  13. E.161: Arrangement of digits, letters and symbols on telephones — ITU-T
  14. RFC 3966: The tel URI for Telephone Numbers — IETF
  15. Last digits are changed to zeros when you type long numbers in cells of Excel — Microsoft Learn
  16. Reassigned Numbers Database — FCC
  17. Test credentials and magic phone numbers — Twilio
  18. Fictitious telephone number — reserved ranges by country — Wikipedia
  19. National numbering plans filed with the ITU (E.164 country filings) — ITU-T

Frequently asked questions

What is E.164 format?

E.164 is the ITU-T recommendation that defines international phone numbering. A number in E.164 format is a plus sign, a country code of one to three digits, and the national number, at most 15 digits in all, for example +442079460958. It has no spaces, brackets, hyphens, trunk prefix or extension. It is a storage format, not a display format. It says nothing about which numbers exist or how a country writes them at home.

Why do Italian phone numbers keep the leading zero in international format?

Because in Italy the zero is part of the number, not a trunk prefix. Since 1998 Italian landlines have kept their leading zero permanently. So a Rome number written 06 6982 1234 is dialled from abroad as +39 06 6982 1234, zero included. Most countries drop the zero in international format. That is why a generic 'strip the leading zero' rule corrupts every Italian landline. Denmark, Greece, Mexico, Norway, Poland, Portugal and Spain have no trunk prefix either.

How long can a phone number be?

E.164 caps the full international number at 15 digits, counting the country code but not the plus. There is no international minimum. National numbers run from five digits on Saint Helena to thirteen in Germany and Austria, whose open plans have no fixed length. A validator that requires exactly ten digits accepts North America and rejects most of the world.

Can I use a phone number as a unique identifier for a person?

Not safely. Numbers are recycled after disconnection, and the FCC runs a Reassigned Numbers Database because reused numbers reach the wrong person. Households share landlines, and one person often has several numbers. With number portability, a number can move between carriers and cities unchanged. Treat a phone number as a contact channel that needs re-checking, not as a primary key.

What phone numbers are safe to use in test data?

Use ranges a numbering authority has reserved, so they can never ring a real line. In North America that is 555-0100 to 555-0199 with any real area code. In the UK it is Ofcom's drama ranges, such as 020 7946 0xxx and 07700 900xxx. For payment or messaging sandboxes, use the provider's test numbers, such as Twilio's +15005550006. Never invent digits at random: most random ten-digit strings are someone's real number.

Update history

  1. Re-ran the 15,200-number measurement and updated every figure: 32 countries now convert fully, and South Korea and Finland's causes are named correctly. Added what the retired shortcut does to today's numbers, and rewrote the prose in shorter sentences.
  2. Added the 13 downloadable test cases and retitled the post for phone number validation test cases.
  3. Linked the new email address test cases from the closing section.
  4. Published, with the measurement over 15,200 generated numbers and the two E.164 bugs we shipped.

More on phone numbers, texting and numbering plans

Put this to work