What E.164 is, and why your list probably isn't in it
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:
- Country code — one to three digits (
1for the NANP,44for the UK,234for Nigeria). - National destination code — the area or mobile-network
code. In the US this is the three-digit area code; in the UK it is the
20in an020London number. - Subscriber number — the rest.
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
- 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.
- Normalise the international access code. A leading
00or011becomes+. - 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.
- 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.
- 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