sms compliance
sms compliance
E.164 Phone Number Format: Complete Validation & Conversion Guide (2025)
Master E.164 phone number validation, formatting, and conversion with regex patterns, JavaScript examples, and libphonenumber-js. Includes E.164 format examples, validator tools, security best practices, and Twilio integration for SMS and international calling.
E.164 Phone Number Format: Complete Guide to Validation & Implementation (2025)
Learn how to validate, format, and convert phone numbers to E.164 format—the international standard for telecommunications. This guide covers E.164 format examples, regex validation patterns, JavaScript implementation with libphonenumber-js, conversion tools, and integration with Twilio and SMS systems for global phone number handling.
What is E.164 Phone Number Format?
E.164 is the international telecommunication standard that defines the format for phone numbers worldwide. The ITU-T (International Telecommunication Union) establishes specifications for structuring phone numbers to enable global dialing across all networks and countries. The official ITU-T Recommendation E.164, titled "The international public telecommunication numbering plan," provides these specifications (ITU-T E.164, 2010).
An E.164 phone number has a maximum of 15 digits and follows this structure:
- Country Code (1–3 digits): Identifies the country (e.g., +1 for USA/Canada)
- National Destination Code (variable length): Identifies the area or carrier
- Subscriber Number: The remaining digits (maximum 12 digits combined with NDC) that identify the specific phone line
E.164 Format Example: +14155550123 (where +1 is USA, 415 is San Francisco area code, 5550123 is the subscriber number)
E.164 forms the foundation of global telecommunications, ensuring consistent call routing and interoperability between countries and network operators. It's the universal language for phone numbers, allowing systems to correctly identify and connect calls across all countries and carriers. This standardized format is essential for SMS delivery, international calling, VoIP services, and two-factor authentication systems.
Historical Context and Evolution: From ISDN to the Modern Era
First published in 1988 as the "Numbering Plan for the ISDN Era," E.164 has continuously evolved to keep pace with advancements in telecommunications. The standard expanded to accommodate growing global demand for phone numbers. The most substantial revision is E.164 (11/2010), approved November 18, 2010, with periodic amendments continuing through ITU Operational Bulletins (latest amendments published July 2020, Bulletin No. 1199) to address the complexities of modern communication, including:
- Mobile number portability: Allows users to retain their numbers when switching carriers across different networks.
- IP telephony integration: Supports VoIP and cloud-based communication systems.
- Emergency service requirements: Ensures reliable routing to emergency services (E911, E112).
- International roaming capabilities: Enables seamless communication while traveling abroad.
- Virtual and eSIM support: Accommodates digital-first phone numbers and embedded SIM technology.
E.164 is not a static standard but a dynamic framework adapting to the ever-changing landscape of global communication, including emerging technologies like virtual phone numbers and cloud telephony platforms.
E.164 Format Specifications: Understanding Phone Number Structure
The E.164 phone number structure consists of precisely defined components that enable global interoperability. Understanding this structure is essential for accurate validation and implementation across international telecommunications systems.
E.164 Number Structure: The Three Essential Components
An E.164 number consists of three key components, each playing a crucial role in accurate routing:
-
Country Code (CC): This 1–3 digit prefix identifies the country. For example, +1 is for North America, +44 for the UK, and +86 for China. The ITU-T assigns these codes (ITU-T E.164, 2010).
-
National Destination Code (NDC): This variable-length code identifies a specific geographic area, mobile network, or service within a country. National authorities manage these codes. NDC lengths vary both between and within countries depending on the numbering plan design.
-
Subscriber Number (SN): This is the remaining portion of the number, uniquely identifying the subscriber within the NDC zone. The combined length of NDC and SN cannot exceed 12 digits. Together, the NDC and SN form the National Significant Number.
Example Breakdown:
+1 (415) 555-0123
│ │ └────────── Subscriber Number (SN)
│ └─────────────── National Destination Code (NDC)
└──────────────────── Country Code (CC)Understanding these components is crucial when parsing and validating E.164 numbers.
E.164 Format Requirements and Validation Rules
E.164 numbers must adhere to strict formatting rules to ensure global compatibility:
1. Character Set
Only digits 0–9 are allowed per ITU-T E.164. A plus (+) prefix indicates international format for display but should be omitted from stored data. No spaces, hyphens, or other separators are allowed in the canonical format. This ensures consistency and simplifies processing.
2. Length Constraints
The minimum length is the CC length plus one digit. The maximum total length is 15 digits (comprising 1–3 digit country code plus up to 12 digits for the national number). Country-specific minimum lengths also apply, adding another layer of complexity to validation.
3. Structural Rules
Use a regular expression to enforce the basic E.164 format:
| Validation Type | Regex Pattern | Description |
|---|---|---|
| Basic E.164 Structure | ^\+[1-9]\d{1,14}$ | Validates structure only – does not verify country-specific rules |
| Storage Format | ^[1-9]\d{1,14}$ | For numbers stored without + prefix |
// Basic E.164 format regex - validates structure only
const e164Regex = /^\+[1-9]\d{1,14}$/;
// Examples:
// +14155550123 ✓ Valid
// +442071234567 ✓ Valid
// +861234567890 ✓ Valid
// 14155550123 ✗ Missing + prefix
// +01234567890 ✗ Starts with 0
// +1415555012345678 ✗ Exceeds 15 digitsImportant Note: This regex validates basic structure but does not verify country-specific rules or whether the number actually exists. For production validation, use specialized libraries like libphonenumber-js that maintain comprehensive country-specific rulesets.
How to Validate E.164 Phone Numbers: Implementation Guide
Implementing robust E.164 phone number validation requires a multi-layered approach that combines format checking, country-specific validation, and length verification. This section provides step-by-step implementation guidance for building reliable phone number validation into your applications.
Phone Number Validation Strategy: Multi-Layered Approach
A robust validation strategy incorporates multiple layers to ensure accuracy:
| Validation Layer | Purpose | Implementation |
|---|---|---|
| Basic Format Validation | Verify structure, catch invalid characters, confirm length | Use regex: /^\+[1-9]\d{1,14}$/ |
| Country-Specific Validation | Check country patterns and length restrictions | Maintain country-specific rule database or use validation library |
| Length Validation | Verify total number length including country code | Critical for countries with variable NDC lengths |
Implementation Example:
import { parsePhoneNumber, isValidPhoneNumber } from 'libphonenumber-js';
function validateE164(phoneNumber) {
// Layer 1: Basic format validation
const e164Regex = /^\+[1-9]\d{1,14}$/;
if (!e164Regex.test(phoneNumber)) {
return { valid: false, error: 'Invalid E.164 format' };
}
// Layer 2 & 3: Country-specific and length validation
try {
const parsed = parsePhoneNumber(phoneNumber);
return {
valid: parsed.isValid(),
country: parsed.country,
type: parsed.getType()
};
} catch (error) {
return { valid: false, error: error.message };
}
}How to Convert Phone Numbers to E.164 Format
Converting local or national phone numbers to E.164 format is a common requirement when processing user input. Follow these steps for accurate conversion:
Conversion Process:
- Remove all formatting characters: Strip spaces, hyphens, parentheses, and punctuation
- Remove leading zeros: If the number begins with 0 (common in national formats), remove it
- Prepend the country code: Add the appropriate country code with + prefix
- Validate the result: Verify the final number is 15 digits or fewer
E.164 Conversion Examples by Country:
| Country | National Format | E.164 Format | Notes |
|---|---|---|---|
| USA | (415) 555-0123 | +14155550123 | Remove parentheses and hyphens |
| UK | 020 7123 4567 | +442071234567 | Remove leading 0 and spaces |
| Germany | 030 12345678 | +493012345678 | Remove leading 0 and spaces |
| India | 98765 43210 | +919876543210 | Remove spaces, add country code |
Code Example:
import { parsePhoneNumber } from 'libphonenumber-js';
function convertToE164(phoneNumber, defaultCountry = 'US') {
try {
const parsed = parsePhoneNumber(phoneNumber, defaultCountry);
return parsed.format('E.164'); // Returns: +14155550123
} catch (error) {
throw new Error(`Conversion failed: ${error.message}`);
}
}
// Usage:
convertToE164('(415) 555-0123', 'US'); // +14155550123
convertToE164('020 7123 4567', 'GB'); // +442071234567
convertToE164('030 12345678', 'DE'); // +493012345678Common Edge Cases in Phone Number Validation
Real-world phone number validation requires handling several edge cases:
1. International Display Format
For user-friendliness, format numbers with appropriate separators for display (e.g., +1-415-555-0123). Store numbers in canonical E.164 format internally.
2. Multiple Input Formats
Users enter phone numbers inconsistently – with dashes, parentheses, spaces, or no formatting at all. Normalize all inputs before validation to ensure consistent processing.
3. Extension Numbers
Phone extensions (e.g., +1-415-555-0123 ext. 456) are not part of the E.164 standard. Store extensions separately:
// Store these separately in your database
{
phoneNumber: '+14155550123', // E.164 format
extension: '456' // Separate field
}4. Special Service Numbers
Handle these number types separately as they may not follow standard validation rules:
| Service Type | Example | Notes |
|---|---|---|
| Emergency | 911 (US), 112 (EU) | Not E.164 compliant; handle separately |
| Toll-free | +1-800-555-0123 | Valid E.164 but may have special routing |
| Premium rate | +1-900-555-0123 | Valid E.164 but require special handling |
| Short codes | 12345 (5–6 digits) | Not E.164; used for SMS services |
5. Vanity Numbers
Convert alpha-numeric vanity numbers (e.g., 1-800-FLOWERS) to numeric format:
function convertVanityNumber(vanityNumber) {
const keypadMap = {
'A': '2', 'B': '2', 'C': '2',
'D': '3', 'E': '3', 'F': '3',
'G': '4', 'H': '4', 'I': '4',
'J': '5', 'K': '5', 'L': '5',
'M': '6', 'N': '6', 'O': '6',
'P': '7', 'Q': '7', 'R': '7', 'S': '7',
'T': '8', 'U': '8', 'V': '8',
'W': '9', 'X': '9', 'Y': '9', 'Z': '9'
};
return vanityNumber
.toUpperCase()
.replace(/[A-Z]/g, char => keypadMap[char]);
}
// Usage:
convertVanityNumber('1-800-FLOWERS'); // 1-800-3569377Best Practices: Ensuring Data Integrity and User Experience
Implement E.164 effectively by following these best practices:
1. Storage
Always store phone numbers in the pure E.164 format, removing all formatting characters. This ensures data consistency and simplifies processing. E.164 numbers are limited to 15 digits, making storage requirements predictable. Use appropriate database field types:
- VARCHAR(15): Recommended for string storage with + prefix
- VARCHAR(16): If storing + prefix as character
- BIGINT: For numeric-only storage (without + prefix)
- Index this field for faster lookups in large contact databases
2. Display
Use local formatting conventions for user interfaces to enhance readability. However, always maintain the E.164 format internally for system operations. Consider cultural formatting preferences to provide the best user experience.
3. Validation
Implement progressive validation, checking the number at both input and processing stages. Use established libraries for complex validation logic. This minimizes errors and improves data quality.
4. Security & Privacy
Treat phone numbers as Personally Identifiable Information (PII). Implement these security measures:
| Security Measure | Implementation | Purpose |
|---|---|---|
| Encryption at rest | AES-256 encryption | Protect stored phone numbers |
| Hashing for lookups | SHA-256 with salt | Enable searches without exposing numbers |
| Rate limiting | Max 10 validation requests per IP per minute | Prevent enumeration attacks |
| Access logging | Audit trail of all phone number access | Compliance and security monitoring |
| TLS in transit | HTTPS/TLS 1.3 | Protect numbers during transmission |
Implementation Example:
const crypto = require('crypto');
// Encryption configuration
const algorithm = 'aes-256-gcm';
const keyLength = 32; // 256 bits
function encryptPhoneNumber(phoneNumber, encryptionKey) {
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv(algorithm, encryptionKey, iv);
let encrypted = cipher.update(phoneNumber, 'utf8', 'hex');
encrypted += cipher.final('hex');
const authTag = cipher.getAuthTag();
return {
encrypted,
iv: iv.toString('hex'),
authTag: authTag.toString('hex')
};
}
// Hash for searchable lookup (one-way)
function hashPhoneNumber(phoneNumber, salt) {
return crypto
.createHash('sha256')
.update(phoneNumber + salt)
.digest('hex');
}Key Management:
- Store encryption keys in a secure key management service (AWS KMS, Azure Key Vault, HashiCorp Vault)
- Rotate encryption keys quarterly
- Never store keys in application code or version control
Privacy Compliance:
- GDPR: Obtain explicit consent before storing phone numbers; provide data export and deletion capabilities
- CCPA: Allow California residents to opt out of phone number data sales
- Right to erasure: Implement hard deletion (not just soft delete) for phone numbers on request
5. API Rate Limiting
When using validation services or carrier lookup APIs, implement rate limiting and caching to prevent abuse and reduce costs. Consider implementing exponential backoff for failed validation attempts.
Caching Strategy:
| Data Type | TTL (Time To Live) | Justification |
|---|---|---|
| Valid numbers | 24 hours | Numbers rarely change; reduce API calls |
| Invalid numbers | 1 hour | May be typos users will correct |
| Carrier lookups | 7 days | Carrier information changes infrequently |
| Country metadata | 30 days | ITU updates are periodic |
const cache = new Map();
async function validateWithCache(phoneNumber) {
const cached = cache.get(phoneNumber);
if (cached && Date.now() - cached.timestamp < 86400000) { // 24 hours
return cached.result;
}
const result = await expensiveValidationAPI(phoneNumber);
cache.set(phoneNumber, { result, timestamp: Date.now() });
return result;
}Troubleshooting E.164 Phone Number Validation: Common Issues & Solutions
When implementing E.164 validation, developers frequently encounter specific issues that can cause validation failures or incorrect phone number handling. Here are the most common problems and their solutions:
Issue 1: Invalid Country Codes
Problem: Numbers fail validation due to incorrect or outdated country codes.
Solutions:
- Verify country codes against the official ITU-T E.164 list
- Check for recent country code changes (countries occasionally modify their codes)
- Validate the total number length against country-specific specifications
- Update your country code database quarterly
Monitoring ITU Changes:
Subscribe to ITU Operational Bulletins for official notifications of numbering plan changes. Recent examples include:
- Kosovo (+383) assigned in 2015
- South Sudan (+211) assigned in 2011
- Timor-Leste changed from +670 (temporary) to permanent assignment
Issue 2: Format Inconsistencies in User Input
Problem: Users submit phone numbers in various formats (with spaces, hyphens, parentheses), causing validation failures.
Solutions:
function normalizePhoneNumber(input) {
// Remove all formatting characters except + prefix
let normalized = input.replace(/[^+\d]/g, '');
// Handle international prefix variations
// Convert 00 (European) or 011 (North American) to +
normalized = normalized.replace(/^00/, '+');
normalized = normalized.replace(/^011/, '+');
// Ensure single + prefix at start
normalized = normalized.replace(/^\++/, '+');
return normalized;
}
// Test cases:
normalizePhoneNumber('(415) 555-0123'); // 4155550123
normalizePhoneNumber('+1-415-555-0123'); // +14155550123
normalizePhoneNumber('001 415 555 0123'); // +14155550123
normalizePhoneNumber('011 44 20 7123 4567'); // +442071234567Implement progressive validation at both input and processing stages to catch errors early.
Issue 3: Regional Numbering Variations
Problem: Variable NDC lengths and special number formats within countries cause validation errors.
Solutions:
- Account for variable NDC lengths within the same country
- Distinguish between mobile and landline formats (they often differ)
- Handle special service numbers separately (emergency services, toll-free, premium rate)
- Use established validation libraries that maintain country-specific rulesets
Special Number Ranges by Type:
| Number Type | Country | Range/Pattern | Example |
|---|---|---|---|
| Toll-free | US/Canada | +1-800/888/877/866/855/844/833 | +18005550123 |
| Toll-free | UK | +44-800/808 | +448005550123 |
| Premium rate | US | +1-900 | +19005550123 |
| Premium rate | UK | +44-871/872/873 | +448715550123 |
| Mobile | US | No specific prefix | +14155550123 |
| Mobile | UK | +44-7 | +447555550123 |
| Mobile | India | +91-6/7/8/9 | +919876543210 |
Issue 4: Failed Call Routing or Integration
Problem: Non-E.164 formatted numbers cause failed API calls, unsuccessful contact synchronization, or routing issues.
Solutions:
- Store numbers in pure E.164 format in your database
- Convert format at data entry points
- Validate format before passing to external APIs or telephony systems
- Log validation failures for debugging and monitoring
Debugging Checklist:
// Comprehensive validation logging
function validateAndLog(phoneNumber, context) {
const validationSteps = {
'has_plus_prefix': phoneNumber.startsWith('+'),
'correct_length': phoneNumber.length >= 8 && phoneNumber.length <= 16,
'digits_only_after_plus': /^\+\d+$/.test(phoneNumber),
'no_leading_zero': !phoneNumber.startsWith('+0'),
'within_max_length': phoneNumber.length <= 16
};
const failed = Object.entries(validationSteps)
.filter(([_, passed]) => !passed)
.map(([step, _]) => step);
if (failed.length > 0) {
console.error(`Validation failed for ${phoneNumber}`, {
context,
failed_checks: failed,
timestamp: new Date().toISOString()
});
}
return failed.length === 0;
}Best E.164 Phone Number Validation Libraries (2025)
Implementing E.164 validation from scratch is complex due to country-specific rules and frequent numbering plan updates. These actively maintained JavaScript libraries simplify validation and formatting while ensuring compliance with current international standards.
Library Comparison Overview
| Feature | libphonenumber-js | phone | google-libphonenumber |
|---|---|---|---|
| Bundle size | 145 KB | 85 KB | 550 KB |
| Last updated | v1.12.23 (Oct 2025) | v3.1.67 (Oct 2025) | v3.2.43 (Sep 2025) |
| TypeScript support | ✓ Full | ✓ Full | ✓ Full |
| Metadata updates | Automatic | Automatic | Automatic |
| Best for | Web applications | Mobile-focused apps | Server-side applications |
| Format validation | ✓ Comprehensive | ✓ Mobile only | ✓ Comprehensive |
| Number type detection | ✓ Yes | ✓ Yes | ✓ Yes |
| Carrier lookup | ✗ No | ✗ No | ✓ Yes |
When to choose which library:
- libphonenumber-js: Best for web applications where bundle size matters. Provides comprehensive validation with reasonable size.
- phone: Best when you only need mobile number validation. Smallest bundle size.
- google-libphonenumber: Best for server-side applications where bundle size is not a concern and you need the most comprehensive validation.
Using the phone Library
The phone npm package (v3.1.67, October 2025) provides robust E.164 standardization and validation for mobile phone numbers. It handles diverse input formats and ensures compliance with international standards. Note: This library focuses specifically on mobile number formats.
Installation and Setup
npm install phone --saveUsage Example
const { phone } = require('phone');
// Basic validation
const result = phone('+14155550123');
console.log(result.isValid); // true
console.log(result.phoneNumber); // +14155550123
console.log(result.countryCode); // US
// With country hint
const result2 = phone('4155550123', { country: 'US' });
console.log(result2.phoneNumber); // +14155550123
// Error handling
const invalid = phone('123');
if (!invalid.isValid) {
console.error('Invalid phone number');
}Using libphonenumber-js
libphonenumber-js is a lightweight implementation of Google's phone number library, optimized for web applications. It's based on Google's canonical libphonenumber but offers significantly better performance for JavaScript environments.
Installation and Setup
npm install libphonenumber-js --saveUsage Example
import { parsePhoneNumber, isValidPhoneNumber } from 'libphonenumber-js';
// Basic validation
console.log(isValidPhoneNumber('+14155550123')); // true
// Parse and extract details
const phoneNumber = parsePhoneNumber('+14155550123');
console.log(phoneNumber.country); // 'US'
console.log(phoneNumber.nationalNumber); // '4155550123'
console.log(phoneNumber.formatInternational()); // '+1 415 555 0123'
console.log(phoneNumber.formatNational()); // '(415) 555-0123'
console.log(phoneNumber.getType()); // 'MOBILE' or 'FIXED_LINE'
// Error handling
try {
const invalid = parsePhoneNumber('invalid');
} catch (error) {
console.error('Parse error:', error.message);
// Handle invalid input gracefully
}Key Features
- Lightweight Bundle: ~145 KB total (65 KB code + 80 KB min metadata) compared to Google's original implementation (~550 KB: 350 KB code + 200 KB metadata)
- Regular Updates: Metadata regularly updated to reflect ITU changes (latest sync: September 19, 2025)
- Type Safety: Full TypeScript support with type definitions
- Multiple Build Formats: Supports ES modules, CommonJS, and tree-shaking
- Flexible Metadata: Choose from min (~80 KB), mobile (~95 KB), or max (~145 KB) metadata sets based on your validation needs
Current Version: libphonenumber-js v1.12.23 (October 2025)
libphonenumber-js is ideal for web applications where bundle size is critical. For server-side applications where bundle size is less critical, Google's original libphonenumber implementation (available as google-libphonenumber v3.2.43 on npm) provides the most comprehensive validation.
Metadata Update Strategy:
Keep your validation library current to handle new numbering plans and country code changes:
// package.json
{
"dependencies": {
"libphonenumber-js": "^1.12.23"
},
"scripts": {
"update-phone-metadata": "npm update libphonenumber-js"
}
}Schedule automated updates quarterly or monitor the libphonenumber-js release notes for critical metadata updates.
Modern Considerations: E.164 in Today's Digital Landscape
As communication technology evolves, several modern considerations have emerged for E.164 implementation:
Virtual Phone Numbers and VoIP
Cloud telephony services and VoIP providers have introduced virtual phone numbers that follow E.164 formatting but may not correspond to traditional geographic locations. RFC 3824 defines procedures for using E.164 numbers with the Session Initiation Protocol (SIP), the foundation of modern VoIP systems. When validating these numbers:
- Verify that your validation logic accepts VoIP numbers (they're valid E.164 numbers)
- Consider carrier lookup services to identify number types (mobile, landline, VoIP)
- Handle porting scenarios where numbers move between carriers or technologies
- ENUM (E.164 Number Mapping): ENUM translates E.164 phone numbers into URIs, enabling SIP routing. If a SIP address exists for a number, calls route via IP networks; otherwise, they route through the PSTN.
ENUM Lookup Implementation:
const dns = require('dns').promises;
async function performEnumLookup(e164Number) {
// Convert +14155550123 to ENUM domain format
// Result: 3.2.1.0.5.5.5.5.1.4.1.e164.arpa
const enumDomain = e164Number
.replace('+', '')
.split('')
.reverse()
.join('.') + '.e164.arpa';
try {
const records = await dns.resolveNaptr(enumDomain);
// Parse NAPTR records for SIP URIs
const sipUris = records
.filter(r => r.service.includes('E2U+sip'))
.map(r => r.replacement);
return sipUris.length > 0 ? sipUris[0] : null;
} catch (error) {
// No ENUM record found - route via PSTN
return null;
}
}Carrier Lookup Services:
Use carrier lookup APIs to identify number types and routing:
- Twilio Lookup API: Identifies carrier, line type, and porting status
- Numverify API: Provides carrier and line type information
- HLR Lookup: Queries Home Location Register for real-time number status
eSIM and Digital-First Numbers
The rise of eSIM technology has created new patterns in phone number provisioning. GSMA specifications govern eSIM remote provisioning: SGP.22 v2.6 (October 2024) for consumer devices and SGP.32 for IoT devices. Key considerations:
- Numbers may be activated/deactivated more frequently through remote provisioning
- Multiple numbers may be associated with a single device
- Digital-first carriers may use non-traditional numbering patterns within E.164 constraints
- E.164 numbers are part of the operator profile data provisioned to the eSIM
Privacy and Data Protection
Modern privacy regulations require careful handling of phone numbers:
GDPR Compliance (European Union)
- Legal basis: Obtain explicit consent before storing phone numbers
- Right to access: Provide data export in machine-readable format
- Right to erasure: Implement hard deletion (not soft delete) within 30 days of request
- Data minimization: Only collect phone numbers when necessary for your service
- Audit logging: Track all access to phone number data
CCPA Compliance (California)
- Right to know: Disclose what phone number data you collect and how you use it
- Right to delete: Delete phone number data within 45 days of verified request
- Right to opt-out: Allow users to opt out of phone number data sales
- Non-discrimination: Don't penalize users who exercise privacy rights
Implementation Considerations
| Requirement | Technical Implementation | Compliance Standard |
|---|---|---|
| Data export | JSON/CSV export with all associated phone data | GDPR Art. 20 |
| Hard deletion | Purge from databases, backups, and logs | GDPR Art. 17 |
| Consent tracking | Store timestamp and consent method | GDPR Art. 7 |
| Access logging | Audit trail with user ID, timestamp, action | GDPR Art. 5 |
| Pseudonymization | Hash or tokenize for analytics | GDPR Art. 32 |
Pseudonymization Techniques:
const crypto = require('crypto');
// Option 1: Hashing (one-way, for analytics)
function pseudonymizePhone(phoneNumber, salt) {
return crypto
.createHash('sha256')
.update(phoneNumber + salt)
.digest('hex')
.substring(0, 16); // Truncate for storage efficiency
}
// Option 2: Tokenization (reversible, for operational needs)
const tokenStore = new Map();
let tokenCounter = 1000000;
function tokenizePhone(phoneNumber) {
const token = `PHN_${tokenCounter++}`;
tokenStore.set(token, phoneNumber);
return token;
}
function detokenizePhone(token) {
return tokenStore.get(token);
}Two-Factor Authentication (2FA) Considerations
When using phone numbers for 2FA:
Best Practices:
- Support international numbers to avoid excluding global users
- Implement fallback authentication methods for users without phone access
- Consider the security implications of SMS-based 2FA versus app-based alternatives
- Account for number recycling by carriers (old numbers reassigned to new users)
Security Concerns:
| Attack Type | Description | Mitigation |
|---|---|---|
| SIM swap attacks | Attacker transfers victim's number to their own SIM | Implement SIM change detection; require additional verification after SIM changes |
| SS7 vulnerabilities | Intercept SMS via telecom protocol exploits | Use app-based TOTP instead of SMS; implement message encryption |
| Number recycling | Carrier reassigns old number to new user | Implement number verification before account recovery; expire inactive accounts |
| Phishing | Social engineering to obtain 2FA codes | Educate users; implement rate limiting on 2FA attempts |
SIM Swap Detection:
// Track device fingerprints and detect SIM changes
async function detectSIMChange(userId, phoneNumber) {
const lastKnownDevice = await getLastDeviceFingerprint(userId);
const currentDevice = await getCurrentDeviceFingerprint();
if (lastKnownDevice !== currentDevice) {
// Possible SIM swap - require additional verification
await sendEmailVerification(userId);
await logSecurityEvent({
type: 'SIM_CHANGE_DETECTED',
userId,
phoneNumber: hashPhone(phoneNumber),
timestamp: Date.now()
});
return { verified: false, reason: 'Device change detected' };
}
return { verified: true };
}Voice vs SMS 2FA Delivery:
| Delivery Method | Pros | Cons | Best For |
|---|---|---|---|
| SMS | Widely supported; familiar to users | SS7 vulnerabilities; can be intercepted | Standard 2FA with low-value accounts |
| Voice call | Works without data connection; harder to intercept | Less convenient; risk of voicemail exposure | Fallback method; users without SMS |
| App-based TOTP | Most secure; no network dependency | Requires smartphone and app installation | High-value accounts; security-conscious users |
| Push notification | User-friendly; secure | Requires app installation and internet | Modern applications with dedicated apps |
Frequently Asked Questions About E.164 Format
What is E.164 format for phone numbers?
E.164 format is the ITU-T international standard for structuring phone numbers, consisting of a country code (1–3 digits), national destination code, and subscriber number, with a maximum total length of 15 digits. The format starts with a + symbol followed by digits only, for example: +14155550123. E.164 ensures global interoperability for telecommunications systems.
How do I convert a phone number to E.164 format?
To convert to E.164 format: (1) Remove all formatting characters (spaces, hyphens, parentheses), (2) Remove leading zeros if present, (3) Add the country code prefix with +, (4) Verify the number contains only digits and is 15 digits or fewer. Example: (415) 555-0123 becomes +14155550123. Use validation libraries like libphonenumber-js for automated conversion.
What is the regex for E.164 validation?
The basic E.164 regex pattern is: ^\+[1-9]\d{1,14}$
This matches a + symbol, followed by a non-zero digit, then 1–14 additional digits (total 2–15 digits after the +). Note: This validates structure only and does not verify country-specific rules or number validity.
Why is E.164 format important for international phone numbers?
E.164 format ensures global interoperability for telecommunications, enabling consistent phone number parsing, validation, and call routing across different countries, carriers, and systems. Without E.164 standardization, international calls would fail, SMS messages wouldn't deliver, and VoIP services couldn't properly route communications. The format eliminates ambiguity in phone number interpretation across 195+ country codes.
Can E.164 format include country codes?
Yes, E.164 format always includes the country code as the first 1–3 digits after the + symbol. The country code is mandatory in E.164 format to enable international dialing.
What's the difference between E.164 and national phone number formats?
E.164 is the international format that always includes the country code (e.g., +14155550123), while national formats are country-specific and omit the country code (e.g., (415) 555-0123 in the USA). National formats often include local formatting conventions like parentheses, hyphens, and spaces for readability. E.164 standardization enables global compatibility and unambiguous number identification across borders, making it essential for international telecommunications, SMS gateways, and VoIP systems.
Is the + symbol required in E.164 format?
The + symbol is used for display purposes to indicate the international format, but the stored E.164 format should contain only digits. The + helps distinguish international numbers from local formatting.
How do I validate E.164 phone numbers in JavaScript?
The most reliable method is using specialized validation libraries like libphonenumber-js or phone npm package, which maintain current country-specific rules:
import { isValidPhoneNumber, parsePhoneNumber } from 'libphonenumber-js';
// Simple validation
console.log(isValidPhoneNumber('+14155550123')); // true
// Detailed validation with error handling
function validatePhone(input) {
try {
const phone = parsePhoneNumber(input);
return {
valid: phone.isValid(),
country: phone.country,
type: phone.getType(),
formatted: phone.formatInternational()
};
} catch (error) {
return {
valid: false,
error: error.message
};
}
}
// Usage:
const result = validatePhone('+14155550123');
console.log(result);
// { valid: true, country: 'US', type: 'MOBILE', formatted: '+1 415 555 0123' }For basic format validation, use regex: /^\+[1-9]\d{1,14}$/, but note this doesn't verify country-specific rules or actual number validity.
How do I use E.164 format with Twilio for SMS?
Twilio requires phone numbers in E.164 format for SMS and voice calls. Convert numbers using libphonenumber-js before sending:
import { parsePhoneNumber } from 'libphonenumber-js';
import twilio from 'twilio';
const client = twilio(accountSid, authToken);
// Convert to E.164 before sending
const phoneNumber = parsePhoneNumber('(415) 555-0123', 'US').format('E.164');
await client.messages.create({
body: 'Your verification code is 123456',
from: '+14155551234',
to: phoneNumber // Must be E.164 format: +14155550123
});Learn more about Twilio E.164 requirements for SMS delivery.
What is the minimum length for E.164 phone numbers?
The E.164 format minimum length varies by country but typically ranges from 8 to 15 digits total (including country code). For example, US numbers are always 11 digits (+1 followed by 10 digits), while some countries like the Solomon Islands may have shorter numbers. Use validation libraries to check country-specific minimum lengths.
Conclusion: Implementing E.164 Phone Number Validation
By understanding and implementing the E.164 international phone number format, you ensure accurate and reliable global communication for your applications. This comprehensive guide has equipped you with:
- Technical knowledge of E.164 format specifications and structure
- Validation strategies using regex patterns and validation libraries
- Implementation examples with libphonenumber-js and the phone library
- Best practices for security, privacy, and modern telecommunications
- Troubleshooting solutions for common phone number validation issues
Whether you're building authentication systems, international calling features, or SMS messaging platforms, proper E.164 implementation is critical for global interoperability. Stay updated on ITU-T revisions and maintain your country code databases for optimal performance.
Ready to implement E.164 validation in your application? Start with libphonenumber-js for lightweight web applications or Google's libphonenumber for comprehensive server-side validation. Both libraries handle the complexity of country-specific rules, allowing you to focus on building great user experiences with reliable international phone number support.
Frequently Asked Questions
What is the E.164 phone number format?
E.164 is an international standard defining the format of phone numbers for global communication. It ensures consistent call routing and compatibility between different countries and network operators. This format is essential for accurate identification and connection with phone numbers worldwide, supporting various communication technologies like mobile, IP telephony, and international roaming.
How to validate E164 phone numbers?
E.164 validation involves a multi-layered approach. Start with basic format validation using a regex to check the structure. Then, perform country-specific checks using a database of regional rules and restrictions. Finally, validate the total number length, accounting for variable NDC lengths within certain countries. This comprehensive strategy helps ensure data integrity.
Why is E.164 important for global communication?
E.164 is crucial for seamless international communication by providing a standardized format for phone numbers. This facilitates consistent call routing, network interoperability, and reliable access to emergency services. It supports essential features such as mobile number portability and international roaming capabilities, accommodating advancements in communication technologies.
How to format phone numbers for international calls?
For international calls, use the plus sign (+) followed by the country code, national destination code, and subscriber number. For example, +1-415-555-0123. This format ensures correct routing across global networks. Remember to store phone numbers in the pure E.164 format without any formatting characters for consistency.
What is the maximum length of an E.164 number?
The maximum length of an E.164 number is 15 digits. This includes the country code (1-3 digits), national destination code (typically 2-4 digits), and subscriber number. The minimum length is the country code length plus at least one additional digit. These length constraints are essential for global compatibility.
How to convert local phone numbers to E.164?
To convert local numbers to E.164, first remove any non-digit characters like spaces, hyphens, or parentheses. Then, prepend the appropriate country code. For instance, a US number (415) 555-0123 would become +14155550123. This ensures consistent handling regardless of the original input format.
When should I use libphonenumber-js for E.164?
Consider using libphonenumber-js when building web applications that require E.164 validation and formatting, especially if minimizing bundle size is a priority. It offers a smaller footprint than Google's full phone number library while providing essential features for accurate handling of international phone numbers.
What are the three components of an E.164 number?
An E.164 number comprises three key components: the Country Code (CC), National Destination Code (NDC), and Subscriber Number (SN). The CC identifies the country, the NDC specifies a region within the country, and the SN uniquely identifies the individual subscriber. These components are crucial for correct routing and identification of phone numbers.
How does E.164 handle mobile number portability?
E.164 supports mobile number portability, allowing users to keep their numbers when switching carriers. This ensures continuous connectivity and prevents disruption of communication services. This feature is managed within the NDC framework within each country or region.
Can I use libraries for E.164 validation in JavaScript?
Yes, JavaScript libraries like `phone` and `libphonenumber-js` simplify E.164 validation. These libraries provide efficient and accurate methods to check phone number compliance with international standards, handling diverse input formats and edge cases.
What is the history of E.164?
Initially introduced in 1984 for ISDN, E.164 has evolved to support modern telecommunications, including IP telephony, mobile number portability, and emergency services. Its maximum length was expanded from twelve to fifteen digits in 1997. This continuous evolution maintains its relevance in the changing communication landscape.
How to handle invalid country codes in E.164?
When dealing with invalid country codes, cross-check them against the official ITU-T list. Also, verify the number's length complies with country-specific rules. Regularly updating your country code database is vital, as these codes can change, potentially invalidating existing data.
Why store E.164 numbers without formatting?
Storing E.164 numbers without formatting, such as spaces or hyphens, ensures data consistency and simplifies processing. This 'pure' format facilitates accurate comparisons, validation, and integration with various systems and databases. Always use local formatting only for display purposes.