phone number standards

Sent logo
Sent TeamMar 8, 2026 / phone number standards / Article

Estonia Phone Number Format: +372 Code, Validation & Examples

Complete guide to Estonia phone numbers (+372): format examples, mobile vs landline validation, E.164 standard implementation, and developer best practices for Estonian numbering.

Estonia Phone Numbers: Format, Area Code & Validation Guide

Complete guide to Estonian phone numbers (+372), covering format specifications, mobile and landline examples, validation patterns, and implementation best practices for developers. Estonia's advanced digital infrastructure and closed numbering plan (no area codes) make it essential to understand the streamlined +372 system for seamless integration with Estonian digital services.

Quick Reference

  • Country: Estonia
  • Country Code: +372
  • International Prefix: 00 (dialed before the country code when calling internationally from Estonia)
  • National Prefix: None

Example Numbers:

  • Geographic (landline): +372 6XX XXXX (7 digits)
  • Mobile: +372 5XXX XXXX (7-8 digits)
  • Toll-free: +372 8002 XXX
  • Premium rate: +372 900 XXXX

Understanding the Estonian Numbering System

Estonia's numbering system supports a digital-first society through:

  • Advanced Digital Services Integration: Estonia ranks 9th among 27 EU member states in the Digital Economy and Society Index (DESI) 2022, enabling seamless integration with e-government platforms, e-residency services, online voting, and digital contract signing using ID cards.
  • E-government Initiatives: Over 93.7% internet penetration rate (as of early 2024) supports comprehensive digital public services where phone numbers serve as authentication identifiers.
  • Mobile-First Communication Approach: Estonia had 1.92 million active cellular mobile connections in early 2024, equating to 145.7% of the total population – reflecting widespread use of multiple connections for personal and work purposes.
  • Cross-border Digital Services within the EU: Aligns with EU standards for telecommunications interoperability, with cross-border data exchange agreements in place (notably with Finland for population data and commercial registers).

Estonia Phone Number Format Specifications

General Structure

Estonian phone numbers follow a closed numbering plan (implemented May 1, 2003). Geographic area codes are absent and all calls within Estonia are local:

  • Country Code: +372 (always use the '+' prefix for international compatibility)
  • Service Identifier: The first digit after the country code indicates the service type:
    • 3: Geographic (fixed-line) - ranges include 32x, 33x, 35x, 38x, 39x, 43x-48x
    • 5: Mobile - covers 5xx (7 digits) and 5xxx (8 digits)
    • 6: VoIP and other non-geographic numbers - ranges 60x-68x
    • 8: Toll-free and mobile - 8000-8009 for freephone, 81xx-87xx for mobile
    • 9: Premium rate - 900 xxxx format
  • Subscriber Number: The remaining digits form the subscriber's unique number.

Format Examples by Service Type

Estonia uses ITU E.164 standard for international numbering. Total number length in E.164 format (including country code +372) is 10-15 digits depending on service type.

Service TypeFormat ExampleNumber Length (without country code)E.164 Total Length
Geographic+372 6XX XXXX7 digits11 digits
Mobile (7-digit)+372 5XX XXXX7 digits11 digits
Mobile (8-digit)+372 5XXX XXXX8 digits12 digits
VoIP+372 6XX XXXX7-8 digits11-12 digits
Toll-free+372 8002 XXX7 digits (8002-8009 prefixes)11 digits
Premium Rate+372 900 XXXX7 digits11 digits
M2M+372 8XXX...Up to 12 digitsUp to 16 digits

How to Validate Estonia Phone Numbers (+372)

Prerequisites

Before implementing Estonian phone number handling, ensure you:

  • Understand the closed numbering plan – no trunk codes or area codes are used; all domestic calls use 7-8 digit numbers directly
  • Support E.164 format – store and process numbers using the international standard (+372XXXXXXXX)
  • Account for number portability – numbers are portable between locations and operators since the 2003 numbering reform
  • Handle variable lengths – mobile numbers can be 7 or 8 digits; M2M numbers extend up to 12 digits

Validation Patterns and Code Examples

Use regular expressions for robust validation:

javascript
const patterns = {
  // Geographic: 3xx xxxx (7 digits), ranges: 32x, 33x, 35x, 38x, 39x, 43x-48x, 60x-68x, 71x-79x, 88x
  geographic: /^(\+372)?([3][2358]|[34][3-8]|[67][0-8]|[7][1-9]|88)\d{5}$/,

  // Mobile: 5xx xxxx (7 digits) or 5xxx xxxx (8 digits), also 81xx-87xx ranges
  mobile: /^(\+372)?(5\d{6,7}|8[1-7]\d{6})$/,

  // VoIP: 6xx xxxx (7-8 digits)
  voip: /^(\+372)?6\d{6,7}$/,

  // Toll-free: 8000-8009 ranges with 4 additional digits
  tollFree: /^(\+372)?800[0-9]\d{3}$/,

  // Premium rate: 900 xxxx
  premium: /^(\+372)?900\d{4}$/,

  // Emergency and special numbers
  emergency: /^112$/,
  shortCode: /^1\d{2,3}$/  // 3-4 digit short codes like 1247, 1343
};

function validateEstonianNumber(number, type = 'mobile') {
  // Normalize: remove spaces, hyphens, parentheses
  let normalized = number.replace(/[\s\-\(\)]/g, '');

  // Handle different input formats
  if (normalized.startsWith('00372')) {
    normalized = '+372' + normalized.substring(5);
  } else if (normalized.startsWith('372') && !normalized.startsWith('+')) {
    normalized = '+372' + normalized.substring(3);
  } else if (!normalized.startsWith('+') && normalized.length >= 7) {
    // Assume domestic format, prepend +372
    normalized = '+372' + normalized;
  }

  // Validate against pattern
  if (!patterns[type]) {
    throw new Error(`Unknown number type: ${type}`);
  }

  const isValid = patterns[type].test(normalized);

  // Return both validation result and normalized number
  return {
    valid: isValid,
    normalized: isValid ? normalized : null,
    type: type
  };
}

// Example usage with different input formats
console.log(validateEstonianNumber('5123 4567', 'mobile'));        // { valid: true, normalized: '+3725123467' }
console.log(validateEstonianNumber('+372 51234567', 'mobile'));    // { valid: true, normalized: '+37251234567' }
console.log(validateEstonianNumber('003725123 4567', 'mobile'));   // { valid: true, normalized: '+3725123467' }

Common Pitfalls:

  • Variable mobile number length: Mobile numbers have either 7 or 8 digits (5xx xxxx vs 5xxx xxxx). Your regex must accommodate both
  • Multiple mobile prefixes: Mobile services use both 5xx and 8[1-7]x ranges – don't limit validation to only 5xx
  • Country code handling: Users may input numbers with +372, 00372, 372, or no prefix. Normalize before validation
  • Special numbers exclusion: Emergency (112) and short codes (116, 1247, 1343) should be handled separately and not validated as regular numbers

Best Practices

Storage Format:

Always store numbers in E.164 format (+372XXXXXXXX). This ensures international compatibility and simplifies processing.

javascript
// Example: Storing in database
function storePhoneNumber(rawNumber, userId) {
  const validation = validateEstonianNumber(rawNumber);

  if (!validation.valid) {
    throw new Error('Invalid Estonian phone number');
  }

  // Store in E.164 format
  return db.users.update({
    id: userId,
    phone: validation.normalized,  // E.g., '+3725123467'
    phone_verified: false,
    updated_at: new Date()
  });
}

Display Format:

Format numbers for readability based on the user's context:

javascript
function formatPhoneDisplay(e164Number, context = 'domestic') {
  if (!e164Number.startsWith('+372')) return e164Number;

  const digits = e164Number.substring(4); // Remove +372

  if (context === 'domestic') {
    // Estonian users: "5123 4567" or "51 234 567"
    if (digits.length === 7) {
      return `${digits.substring(0, 3)} ${digits.substring(3)}`;
    } else if (digits.length === 8) {
      return `${digits.substring(0, 4)} ${digits.substring(4)}`;
    }
  }

  // International context: full E.164
  return e164Number;
}

Database Schema Considerations:

  • Use VARCHAR(16) to accommodate E.164 format (max 15 digits + plus sign).
  • Index phone numbers for lookup performance: CREATE INDEX idx_phone ON users(phone);
  • Consider adding a phone_country_code column if supporting multiple countries for faster filtering.
  • Store verification status separately: phone_verified BOOLEAN DEFAULT FALSE.

Network Infrastructure and Coverage

Estonia boasts a world-class telecommunications infrastructure, with substantial recent investment in 5G deployment:

  • Extensive 4G/5G Coverage: 4G/LTE covers over 99% of the population across all three major operators (Telia, Elisa, Tele2). 5G deployment accelerated following spectrum auctions in 2022-2023 (700 MHz, 3.5 GHz, and 26 GHz bands).
  • High Data Throughput: Average mobile download speeds exceed 58.6 Mbps (Telia) to 30+ Mbps (other operators) nationwide, with urban areas seeing 100+ Mbps on 5G networks.
  • Excellent Network Reliability: Network uptime approaches 99.9% in population centers, supported by comprehensive infrastructure sharing arrangements.

Major Operators and Market Share

According to TTJA 2024 data:

OperatorMarket Share (Subscribers)Coverage Notes
Telia Estonia44%Largest network, extensive 5G in Tallinn (150+ base stations), best overall coverage
Elisa Estonia32%Claims 70% population 5G coverage, competitive pricing for families
Tele2 Estonia24%Budget operator, coverage approximately 50% of Telia/Elisa, first mmWave 26GHz 5G base station (2023)

All three operators provide fixed and mobile services, with Telia and Elisa also offering substantial fiber broadband infrastructure.

Advanced Considerations

Number Portability

Number portability allows users to switch operators while keeping their number. TTJA regulations mandate:

Timeline:

  • Mobile numbers: 3-25 working days (average: 3-6 working days)
  • Landline numbers: 3-39 working days (includes technical facility identification)

Process:

  1. Customer submits request to new operator (receiving operator) or terminates with current operator
  2. Receiving operator initiates portability verification via Number Reservation Database (NBA)
  3. Former operator confirms portability date
  4. Number transfers on confirmed date
  5. Process is free of charge for customers

Important Notes:

  • Customers can suspend the portability request until the former operator confirms the transfer date.
  • A conditional 30-day termination window applies if initiated with the current operator.
  • Numbers are portable between locations and operators under Estonia's closed numbering plan.

Implementation Consideration:

Currently, there is no publicly documented API for real-time portability checks from TTJA. Operators manage portability through the NBA system. For applications requiring current operator identification, consider:

  • Maintain an operator prefix lookup table (updated quarterly from TTJA data)
  • Cache known number-to-operator mappings
  • Handle portability as an eventual consistency issue (numbers may take 3-6 days to fully port)

Error Handling

Implement comprehensive error handling for Estonian phone numbers:

javascript
class EstonianPhoneError extends Error {
  constructor(code, message, details = {}) {
    super(message);
    this.code = code;
    this.details = details;
  }
}

function validateWithErrors(number) {
  // Check for special numbers first
  const cleaned = number.replace(/\D/g, '');

  if (cleaned === '112') {
    throw new EstonianPhoneError(
      'SPECIAL_NUMBER',
      'Emergency number 112 cannot be used for registration',
      { isEmergency: true }
    );
  }

  if (/^1\d{2,3}$/.test(cleaned)) {
    throw new EstonianPhoneError(
      'SHORT_CODE',
      'Short codes (116, 1247, 1343, etc.) are not valid for user registration',
      { isShortCode: true }
    );
  }

  // Validate length
  if (cleaned.length < 7 || cleaned.length > 15) {
    throw new EstonianPhoneError(
      'INVALID_LENGTH',
      `Phone number must be 7-15 digits, got ${cleaned.length}`,
      { length: cleaned.length }
    );
  }

  // Validate service prefix
  const validation = validateEstonianNumber(number);
  if (!validation.valid) {
    throw new EstonianPhoneError(
      'INVALID_FORMAT',
      'Number does not match Estonian numbering plan',
      { input: number }
    );
  }

  return validation.normalized;
}

// Network error handling with retry
async function sendSMSWithRetry(phone, message, maxRetries = 3) {
  let lastError;

  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await smsProvider.send(phone, message);
    } catch (error) {
      lastError = error;

      if (error.code === 'INVALID_NUMBER') {
        throw error; // Don't retry invalid numbers
      }

      if (attempt < maxRetries) {
        await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
      }
    }
  }

  throw new EstonianPhoneError(
    'NETWORK_ERROR',
    `Failed to send SMS after ${maxRetries} attempts`,
    { originalError: lastError }
  );
}

Special Numbers to Handle:

  • Emergency: 112 (European emergency number)
  • Short codes: 116 (Harmonized European Short Codes), 1247 (State helpline), 1343 (Electric circuit breakdown), 1524 (Rescue service info)
  • International freephone: 8000 xxxx, 8001 xxxx ranges

GDPR Compliance

Estonia is an EU member state. When handling Estonian phone numbers, ensure GDPR compliance:

Data Minimization:

javascript
// Only collect what you need
const userSchema = {
  phone: String,           // Required for authentication
  phone_verified: Boolean, // Required for security
  // Don't store: call logs, SMS content, carrier info (unless necessary)
};

Purpose Limitation:

  • Document why you collect phone numbers (e.g., "two-factor authentication")
  • Don't use for marketing without separate consent
  • Delete when purpose is fulfilled

Storage Security:

javascript
// Encrypt at rest
const crypto = require('crypto');

function encryptPhone(phone, key) {
  const iv = crypto.randomBytes(16);
  const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);
  const encrypted = Buffer.concat([cipher.update(phone, 'utf8'), cipher.final()]);
  const tag = cipher.getAuthTag();
  return { encrypted: encrypted.toString('hex'), iv: iv.toString('hex'), tag: tag.toString('hex') };
}

// Encrypt in transit (use HTTPS/TLS)
app.use((req, res, next) => {
  if (!req.secure && process.env.NODE_ENV === 'production') {
    return res.redirect('https://' + req.headers.host + req.url);
  }
  next();
});

User Consent:

javascript
// Explicit opt-in for phone collection
const consentForm = {
  phone_consent: {
    granted: true,
    purpose: 'Two-factor authentication',
    timestamp: new Date().toISOString(),
    ip_address: req.ip
  }
};

// Allow users to withdraw consent and delete data
app.post('/api/delete-phone', authenticateUser, async (req, res) => {
  await db.users.update({ id: req.user.id, phone: null, phone_verified: false });
  await db.audit.log({ user: req.user.id, action: 'PHONE_DELETED', timestamp: new Date() });
  res.json({ success: true });
});

Data Retention:

  • Define retention periods: e.g., "Phone numbers retained while account is active + 30 days post-deletion"
  • Implement automated deletion: schedule jobs to purge phone data per retention policy
  • Maintain audit logs of deletions for compliance verification

Integration Best Practices

Normalization Function:

javascript
function normalizeEstonianPhone(input) {
  if (!input) return null;

  // Remove all non-digit characters except +
  let cleaned = input.replace(/[^\d+]/g, '');

  // Handle different prefixes
  if (cleaned.startsWith('+372')) {
    return cleaned;
  } else if (cleaned.startsWith('00372')) {
    return '+372' + cleaned.substring(5);
  } else if (cleaned.startsWith('372')) {
    return '+372' + cleaned.substring(3);
  } else if (/^\d{7,8}$/.test(cleaned)) {
    // Assume domestic Estonian number
    return '+372' + cleaned;
  }

  return null; // Invalid format
}

Webhook Implementation:

For real-time phone verification status updates:

javascript
app.post('/webhooks/sms-provider', express.json(), (req, res) => {
  const { phone, status, timestamp } = req.body;

  // Verify webhook signature
  const signature = req.headers['x-webhook-signature'];
  if (!verifyWebhookSignature(req.body, signature)) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

  // Update verification status
  db.users.update({
    phone: normalizeEstonianPhone(phone),
    phone_verified: status === 'verified',
    phone_verified_at: new Date(timestamp)
  });

  res.json({ received: true });
});

Testing Strategies:

  • Unit tests: Validate all number format variations (with/without country code, spaces, hyphens)
  • Integration tests: Test against real Estonian numbers from each operator
  • Use test numbers: Coordinate with SMS providers for test phone numbers that don't send actual SMS
  • Recommended tools: libphonenumber (Google's library supports Estonian numbers)
javascript
// Example test suite
describe('Estonian Phone Validation', () => {
  test('validates 7-digit mobile', () => {
    expect(validateEstonianNumber('5123456', 'mobile').valid).toBe(true);
  });

  test('validates 8-digit mobile', () => {
    expect(validateEstonianNumber('51234567', 'mobile').valid).toBe(true);
  });

  test('normalizes various input formats', () => {
    const inputs = ['+372 5123 4567', '00372 51234567', '372 5123 4567', '5123 4567'];
    inputs.forEach(input => {
      const result = normalizeEstonianPhone(input);
      expect(result).toMatch(/^\+3725\d{7,8}$/);
    });
  });

  test('rejects emergency numbers', () => {
    expect(() => validateWithErrors('112')).toThrow('SPECIAL_NUMBER');
  });
});

Regular Updates:

Stay informed about changes to Estonian numbering regulations:

For comprehensive guidance on international phone standards and SMS best practices, explore these related guides:

Additional Resources