Phonelint
Formatting

What E.164 is, and why your list probably isn't in it

Published 2026-09-08 · Phonelint

Almost every rejected message, failed API call and mysteriously undeliverable contact traces back to the same thing: the number was not in E.164, and the system on the other end refused to guess what you meant.

E.164 is the ITU standard that gives every phone number on earth exactly one canonical written form. It is a short rule, and once your list follows it, an entire category of problems disappears.

The rule

An E.164 number is a plus sign, then digits, and nothing else — no spaces, no brackets, no dashes, no leading zero. Maximum fifteen digits after the plus.

+14155552671      US, 11 digits
+442071838750     UK, 12 digits
+2348031234567    Nigeria, 13 digits
+61291234567      Australia, 11 digits

Those digits break into three parts:

The four things that break it

1. The trunk prefix that should have been dropped

This is the big one, and it is the mistake that survives longest because the number still looks right. Most countries put a digit in front of a number when you dial it domestically — a trunk prefix, usually 0. A London number is written 020 7183 8750 at home. The 0 is dialling instruction, not part of the number. Internationally it is dropped:

020 7183 8750   ->  +44 20 7183 8750   correct
020 7183 8750   ->  +44 020 7183 8750  wrong -- extra 0

The same applies to Nigeria (0803… becomes +234803…), Australia, India, Germany, most of Europe and most of Africa. It does not apply to the NANP, which has no trunk prefix — 1 there is the country code itself, not a trunk digit, which is exactly why the two get confused.

Why it matters: a number with a stray trunk zero is one digit too long for its plan. Some gateways strip it silently, some reject the message, and some accept it and bill you for a delivery that never happens. The third case is the expensive one, because nothing in your reporting tells you it went wrong.

2. The double prefix

00, 011 and 810 are international access codes — what you dial to get out of your own country. They are not part of the number and they are not interchangeable with +. 0044… in a field that expects E.164 is malformed. So is +0044…, which manages both mistakes at once.

3. Country assumed instead of stored

A column of 5551234 and 7183 8750 is not a phone list, it is a list of fragments. Nothing in those digits says which country they belong to, and no tool can tell you — including this one. A seven-digit string is a valid subscriber number in dozens of numbering plans simultaneously.

If your source system stored the country separately (a billing address, a signup locale, a store region), you need that column joined back on before conversion. If it did not, the honest answer is that those rows cannot be recovered from the digits alone. Segment them and treat them as a data-collection problem, not a formatting one.

4. Formatting characters that survived the export

(415) 555-2671, 415.555.2671, +44 (0) 20 7183 8750. The last one is the nastiest: it is a common British house style that embeds the trunk zero in brackets as a courtesy to domestic callers. Strip the punctuation naively and you get +442007183875 — the zero has silently become part of the number.

Converting a list, in order

  1. Strip everything that is not a digit or a leading plus. Spaces, brackets, dashes, dots, and the non-breaking spaces that come out of spreadsheet exports.
  2. Normalise the international access code. A leading 00 or 011 becomes +.
  3. Establish the country for every row. From the country code if the number already carries one, otherwise from a separate column. Rows where you have neither get set aside — do not guess.
  4. Drop the trunk prefix for that country, if the remaining national number starts with it. This is per-country, which is why a find-and-replace does not work.
  5. Check the result against the country's numbering plan — correct length, and an actual allocated block rather than a plausible-looking one.

Steps one and two are a regular expression. Steps three to five are why phone formatting libraries exist: the rules are per-country, they change, and there are roughly two hundred of them.

Well-formed is not the same as real

This is the distinction most cleaning scripts miss, and it is worth being precise about.

+1 999 999 9999 is perfect E.164. Right length, valid structure, passes every regex you can write. It is also not a phone number — the NANP never allocated the 999 area code, so nothing is on the other end.

Checking the shape of a number tells you it could exist. Checking it against the numbering plan tells you whether the block it sits in was ever handed to a carrier. Those are different questions, and only the second one saves you money on a send.

What a numbering-plan check cannot tell you is whether the specific handset is switched on, or who is holding it today. Block allocation is the floor: numbers outside an allocated block are definitively dead, and that is where the bulk of a typical list's waste sits.

Store it in E.164, always

Convert on the way in, not on the way out. Store the canonical +-prefixed string in your database and format it for display at the point of display. Every system that has ever had a phone-number data-quality problem got there by storing whatever the user typed and hoping to sort it out later.

Try it on a number right now

The free checker on the homepage runs the same engine the desktop app uses — validity, country, line type and carrier, one number at a time.

Check a number free