Skip to main content

Validating Phone Numbers

Validation determines whether a parsed phone number is legitimate according to that country’s numbering plan. Understanding the difference between “possible” and “valid” numbers is crucial.
This library validates number patterns only. It cannot determine if a number is actually in service with a telecommunication provider.

Valid vs Possible Numbers

A valid number matches a specific pattern from the country’s numbering plan:
$phoneUtil = PhoneNumberUtil::getInstance();
$number = $phoneUtil->parse('0117 496 0123', 'GB');

$isValid = $phoneUtil->isValidNumber($number);
var_dump($isValid); // bool(true)
This checks:
  • Correct number of digits
  • Valid area code
  • Matches known patterns for the region
Rule of thumb: A valid number is always possible, but a possible number may not be valid.

Validation Methods

isValidNumber()

The primary validation method for most use cases:
$phoneUtil = PhoneNumberUtil::getInstance();

// Parse and validate a UK number
$ukNumber = $phoneUtil->parse('0117 496 0123', 'GB');
var_dump($phoneUtil->isValidNumber($ukNumber)); // bool(true)

// Parse and validate a US number
$usNumber = $phoneUtil->parse('(650) 253-0000', 'US');
var_dump($phoneUtil->isValidNumber($usNumber)); // bool(true)

// Invalid number
$invalidNumber = $phoneUtil->parse('123', 'GB');
var_dump($phoneUtil->isValidNumber($invalidNumber)); // bool(false)

isValidNumberForRegion()

Validate that a number belongs to a specific region:
$phoneUtil = PhoneNumberUtil::getInstance();
$number = $phoneUtil->parse('0117 496 0123', 'GB');

// Check if valid for GB
var_dump($phoneUtil->isValidNumberForRegion($number, 'GB')); // bool(true)

// Check if valid for FR (it's not)
var_dump($phoneUtil->isValidNumberForRegion($number, 'FR')); // bool(false)
Use this when you need to ensure a number is from a specific country, such as validating local phone numbers for a regional business.

isPossibleNumber()

Quick check for possible validity:
$phoneUtil = PhoneNumberUtil::getInstance();

// Can accept PhoneNumber object
$number = $phoneUtil->parse('0117 496 0123', 'GB');
var_dump($phoneUtil->isPossibleNumber($number)); // bool(true)

// Or string with region
var_dump($phoneUtil->isPossibleNumber('01174960123', 'GB')); // bool(true)

isPossibleNumberWithReason()

Get detailed information about why a number is possible or not:
$phoneUtil = PhoneNumberUtil::getInstance();
$number = $phoneUtil->parse('0117 496 0123', 'GB');

$result = $phoneUtil->isPossibleNumberWithReason($number);
var_dump($result); // int(0) (ValidationResult::IS_POSSIBLE)

// Too short number
$shortNumber = $phoneUtil->parse('123', 'GB');
$result = $phoneUtil->isPossibleNumberWithReason($shortNumber);
var_dump($result); // int(2) (ValidationResult::TOO_SHORT)

Complete Validation Example

1

Parse the Input

$phoneUtil = PhoneNumberUtil::getInstance();

try {
    $number = $phoneUtil->parse($userInput, $userRegion);
} catch (\libphonenumber\NumberParseException $e) {
    // Handle parsing error
    return ['error' => 'Cannot parse phone number'];
}
2

Check if Possible

if (!$phoneUtil->isPossibleNumber($number)) {
    $reason = $phoneUtil->isPossibleNumberWithReason($number);
    
    switch ($reason) {
        case \libphonenumber\ValidationResult::TOO_SHORT:
            return ['error' => 'Phone number is too short'];
        case \libphonenumber\ValidationResult::TOO_LONG:
            return ['error' => 'Phone number is too long'];
        default:
            return ['error' => 'Phone number is invalid'];
    }
}
3

Validate the Number

if (!$phoneUtil->isValidNumber($number)) {
    return ['error' => 'Phone number is not valid for any region'];
}
4

Optional: Check Region

// If you need to ensure it's from a specific region
if (!$phoneUtil->isValidNumberForRegion($number, 'GB')) {
    return ['error' => 'Phone number must be a UK number'];
}
5

Success

// Number is valid, format for storage
$e164 = $phoneUtil->format(
    $number,
    \libphonenumber\PhoneNumberFormat::E164
);

return ['success' => true, 'number' => $e164];

Validation for Specific Number Types

You can validate that a number is of a specific type:
$phoneUtil = PhoneNumberUtil::getInstance();
$number = $phoneUtil->parse('07400 123456', 'GB');

// Check if it's a mobile number
$type = $phoneUtil->getNumberType($number);

if ($type === \libphonenumber\PhoneNumberType::MOBILE) {
    echo "This is a mobile number";
} elseif ($type === \libphonenumber\PhoneNumberType::FIXED_LINE) {
    echo "This is a landline";
}

// Validate as possible for specific type
$result = $phoneUtil->isPossibleNumberForTypeWithReason(
    $number,
    \libphonenumber\PhoneNumberType::MOBILE
);

Real-World Validation Patterns

function validatePhoneNumberInput(
    string $input,
    string $region
): array {
    $phoneUtil = PhoneNumberUtil::getInstance();
    
    try {
        $number = $phoneUtil->parse($input, $region);
        
        if (!$phoneUtil->isValidNumber($number)) {
            return [
                'valid' => false,
                'error' => 'Invalid phone number format'
            ];
        }
        
        return [
            'valid' => true,
            'number' => $phoneUtil->format(
                $number,
                \libphonenumber\PhoneNumberFormat::E164
            ),
            'type' => $phoneUtil->getNumberType($number)
        ];
        
    } catch (\libphonenumber\NumberParseException $e) {
        return [
            'valid' => false,
            'error' => 'Cannot parse phone number'
        ];
    }
}

Common Validation Scenarios

Some numbers are valid but can’t be dialed from outside their country:
$phoneUtil = PhoneNumberUtil::getInstance();
$number = $phoneUtil->parse('1300 123 456', 'AU');

var_dump($phoneUtil->isValidNumber($number)); // bool(true)
var_dump($phoneUtil->canBeInternationallyDialled($number)); // bool(false)
Sometimes you want to accept numbers from several countries:
function isValidForAnyRegion(
    PhoneNumber $number,
    array $allowedRegions
): bool {
    $phoneUtil = PhoneNumberUtil::getInstance();
    
    foreach ($allowedRegions as $region) {
        if ($phoneUtil->isValidNumberForRegion($number, $region)) {
            return true;
        }
    }
    
    return false;
}

// Accept UK or US numbers
$isValid = isValidForAnyRegion($number, ['GB', 'US']);
Identify expensive premium rate numbers:
$phoneUtil = PhoneNumberUtil::getInstance();
$number = $phoneUtil->parse($input, $region);

$type = $phoneUtil->getNumberType($number);

if ($type === \libphonenumber\PhoneNumberType::PREMIUM_RATE) {
    // Show warning to user about potential costs
    echo "Warning: This is a premium rate number";
}

Best Practices

Always Validate After Parsing

Just because a number parses doesn’t mean it’s valid

Use isValidNumber() for Production

The isPossibleNumber() check is less strict and should only be used for preliminary validation

Consider Number Types

Use getNumberType() to restrict to mobile, landline, or other specific types

Provide User Feedback

Use isPossibleNumberWithReason() to give specific error messages

Next Steps

Formatting Numbers

Learn how to format validated numbers for display

Error Handling

Handle validation errors gracefully

Validation API Reference

Complete ValidationResult enum documentation

PhoneNumberUtil API

Full API reference for validation methods

Build docs developers (and LLMs) love