Description
What is the E.164 format?
The E.164 phone number format comes from ITU-T Recommendation E.164, the international public telecommunication numbering plan. An E.164 number is the full international form of a phone number: a country calling code of one to three digits followed by the national subscriber number, at most 15 digits in total, written with a leading + and nothing else. There are no spaces, dashes or brackets, and no trunk 0 of the kind used for domestic dialling, so a Mumbai mobile written locally as 098198 12345 becomes +919819812345.
For the WhatsApp Cloud API, E.164 is the safe shape for the recipient in the to field of the messages endpoint. Meta accepts a + sign and common separators in send requests but strongly recommends including the country code with the +: if the + is left out, the business number's own country code may be prepended, which can send the message to the wrong number or nowhere. In webhooks the customer appears as wa_id, the same digits without the + (919819812345), and the send response's contacts array echoes your input next to the wa_id that WhatsApp resolved, which Meta notes may not always match the input.
Normalising to E.164 is a data-quality job, not cosmetic formatting. Indian contact lists mix bare 10-digit mobiles, numbers with a leading 0, +91 with spaces, 0091 prefixes and landlines with STD codes; each must become one canonical string before it is stored, deduplicated, matched against opt-in records or messaged. E.164 is also distinct from the phone number ID, the numeric Graph API node ID that identifies your business number in API paths, and from an SMS sender ID, the registered header shown in place of a number.
Key takeaways
- E.164 writes every phone number one way: +, country code, subscriber number, with no spaces, dashes or trunk 0, and at most 15 digits.
- An Indian mobile in E.164 is +91 followed by 10 digits starting 6, 7, 8 or 9, for example +919819812345.
- Send the full number with its country code in the Cloud API
tofield; webhooks return the sender aswa_id, digits only. - Normalise once, at the point of capture, and store the E.164 string; guessing the country later causes misdelivery.
- The phone number ID is Meta's internal ID for your business number: it is never dialled and never E.164.
Mechanics
How does the E.164 format work?
step 1 — Strip the formatting
Remove spaces, dashes, dots and brackets, plus the (0) some people write after the country code. Keep only the digits and a leading +.
step 2 — Replace international prefixes
A leading
00(or another country's exit code, such as 011 from the US) is the dialling prefix for an international call: replace it with +.step 3 — Drop the trunk 0 and add the country code
A leading 0 is a domestic trunk prefix. Remove it and add the country code; for an Indian 10-digit mobile starting 6–9 that is +91. Never guess the country for numbers that could belong to several.
step 4 — Validate length and pattern
E.164 allows at most 15 digits after the +, and an Indian mobile is exactly +91 plus 10 digits. A maintained library (libphonenumber or one of its ports) checks that a number is valid for its country.
step 5 — Store E.164 and derive the rest
Keep the +-prefixed string as the canonical value. Derive the digits-only form for matching webhook senders and building wa.me links, and a spaced format for display.
Usage
The E.164 format in code
import phonenumbersfrom phonenumbers import NumberParseException, PhoneNumberFormatdef to_e164(raw: str, default_region: str = "IN") -> str | None:try:num = phonenumbers.parse(raw, default_region)except NumberParseException:return Noneif not phonenumbers.is_valid_number(num):return Nonereturn phonenumbers.format_number(num, PhoneNumberFormat.E164)to_e164("098198 12345") # '+919819812345'to_e164("+91-98198-12345") # '+919819812345'to_e164("0091 9819812345") # '+919819812345'to_e164("12345") # None: reject, don't guess
Example
Example: Cleaning a festive list in Surat
A Surat saree retailer exports 18,000 contacts from its billing software before a Navratri broadcast. The phone column mixes 98250 12345, 098250-12345, +91 98250 12345 and 919825012345, and many customers appear twice. Normalising every row to E.164 collapses 1,240 duplicates and flags 310 entries that are landlines or too short to be valid. Matching the cleaned list against the opt-in register by E.164 string, rather than by raw text, also catches 95 customers who had opted out under a differently formatted number.
Properties
The E.164 format: key facts and limits
- Standard
- ITU-T Recommendation E.164
- Maximum length
- 15 digits (country code + subscriber number)
- Country code
- 1–3 digits; India is 91
- Indian mobile
- +91 then 10 digits starting 6–9
- Cloud API to field
- Full number with country code; + recommended
- Webhook wa_id
- Digits only, no + (919819812345)
Why it matters
Why does the E.164 format matter?
Phone numbers are the join key of a WhatsApp programme: opt-in records, CRM contacts, the suppression list and webhook senders all meet on them. If one system stores 09819812345, another +91 98198 12345 and the webhook says 919819812345, one customer becomes three contacts, opt-outs are missed, duplicates are messaged twice and replies never match the customer record. One E.164 rule at every entry point prevents all of that, and avoids the misdelivery Meta warns about when the country code is missing.
Caveats
Common mistakes with the E.164 format
Sending without the country code
Meta's docs warn that without the + the business number's country code may be prepended: sent from an Indian number, 16315551234 can become +9116315551234, and the send ends in error 131026 (Message Undeliverable) or reaches a stranger. Always send the full international number.
Assuming every 10-digit number is Indian
US and Canadian national numbers are also 10 digits, and NRI customers often give them. Assume +91 only when the source is known to be Indian; otherwise capture the country in the form.
Comparing raw strings
An opt-out recorded as 098250 12345 won't match a send to +919825012345. Normalise both sides before every lookup against consent and suppression records.
Storing numbers as integers
Numeric columns drop the +, and spreadsheets turn long numbers into 9.19819E+11 and lose digits. Store E.164 as text.
Confusing E.164 with the phone number ID
The ID in
/{PHONE_NUMBER_ID}/messagesis Meta's node ID for your business number, not a dialable number. Putting the display number there fails the request.
Questions
E.164 FAQs
- What does E.164 format look like for an Indian number?
- +91 followed by the 10-digit mobile number, with no spaces and no leading 0, for example +919819812345. Landlines drop the trunk 0 of the STD code: 022 2345 6789 becomes +912223456789.
- Should the WhatsApp API to field include the + sign?
- Yes, it is recommended. Meta accepts the + and separators, and warns that without the + the business number's country code may be prepended, which can deliver the message to the wrong number.
- Is wa_id the same as an E.164 number?
- Nearly: wa_id is the WhatsApp ID, usually the E.164 digits without the +. It is returned by WhatsApp and may not match the number you sent, so store both and match on the normalised form.
- How many digits can an E.164 number have?
- At most 15, counting the country code but not the +. Country codes are one to three digits long, so the national part is correspondingly shorter.
Notes
Best practices for the E.164 format
- Use a country picker plus a national-number field in forms, and build the E.164 value from both.
- Normalise at import time and reject numbers that fail validation instead of guessing.
- Keep the raw input alongside the E.164 value for audits and support questions.
- Since usernames arrived, some webhooks omit the phone number, so plan to key records on the BSUID as well.