Tutorial · Python

Validate phone numbers in Python

Use the phonenumbers library for offline validation and formatting, and an API call when you need the carrier and line type.

Updated October 1, 2026 · 2 min read

Offline validation with phonenumbers

pip install phonenumbers
import phonenumbers
from phonenumbers import PhoneNumberFormat, PhoneNumberType, carrier, geocoder

def check(number: str, default_region: str = "US") -> dict:
    try:
        parsed = phonenumbers.parse(number, default_region)
    except phonenumbers.NumberParseException:
        return {"valid": False}
    return {
        "valid": phonenumbers.is_valid_number(parsed),
        "e164": phonenumbers.format_number(parsed, PhoneNumberFormat.E164),
        "international": phonenumbers.format_number(parsed, PhoneNumberFormat.INTERNATIONAL),
        "mobile": phonenumbers.number_type(parsed) == PhoneNumberType.MOBILE,
        "region": phonenumbers.region_code_for_number(parsed),
        "location": geocoder.description_for_number(parsed, "en"),
        "original_carrier": carrier.name_for_number(parsed, "en"),
    }

print(check("0803 123 4567", "NG"))
# {'valid': True, 'e164': '+2348031234567', 'international': '+234 803 123 4567',
#  'mobile': True, 'region': 'NG', 'location': 'Nigeria', 'original_carrier': 'MTN'}

phonenumbers is the Python port of Google’s libphonenumber. It is the right tool for format checks and normalisation, and it runs without network access.

Adding carrier and line type with the API

The bundled carrier data only knows which network a number block was issued to, and is empty for the US and Canada. The numlookupapi API returns carrier and line type for any number:

import os
import requests

def lookup(number: str, country: str | None = None) -> dict:
    params = {"country_code": country} if country else {}
    res = requests.get(
        f"https://api.numlookupapi.com/v1/validate/{number}",
        params=params,
        headers={"apikey": os.environ["NUMLOOKUP_API_KEY"]},
        timeout=10,
    )
    res.raise_for_status()
    return res.json()

data = lookup("+14158586273")
print(data["valid"], data["line_type"], data["carrier"])
# True mobile AT&T Mobility LLC

Batch lookups: requests.post("https://api.numlookupapi.com/v1/validate", json={"numbers": [...]}, headers=...) validates up to 100 numbers per call.

Django form field example

from django import forms
import phonenumbers

class SignupForm(forms.Form):
    phone = forms.CharField()

    def clean_phone(self):
        raw = self.cleaned_data["phone"]
        try:
            parsed = phonenumbers.parse(raw, "US")
        except phonenumbers.NumberParseException:
            raise forms.ValidationError("Enter a valid phone number.")
        if not phonenumbers.is_valid_number(parsed):
            raise forms.ValidationError("Enter a valid phone number.")
        return phonenumbers.format_number(parsed, phonenumbers.PhoneNumberFormat.E164)

Store the E.164 value and run the API lookup asynchronously (e.g. in a Celery task) if you need carrier or VoIP detection.

Frequently asked questions

How do I validate a phone number in Python?

Install phonenumbers, parse the number with phonenumbers.parse(number, 'US') and call phonenumbers.is_valid_number(parsed). It checks length and prefixes against Google's numbering-plan data.

How do I get the carrier of a phone number in Python?

phonenumbers.carrier.name_for_number(parsed, 'en') returns the network a number block was assigned to (not reliable for ported numbers or US numbers). For the carrier from current data, call a lookup API such as numlookupapi.

How do I format a phone number to E.164 in Python?

phonenumbers.format_number(parsed, phonenumbers.PhoneNumberFormat.E164) returns '+14155552671'.

Phone number API

Validate numbers like this in your app

numlookupapi checks any phone number worldwide in one request and returns validity, line type, carrier, location and every standard format as JSON.

Read the documentation

100 free requests every month. No credit card required.

GET https://api.numlookupapi.com/v1/validate/+12069220880

{
  "valid": true,
  "number": "12069220880",
  "local_format": "2069220880",
  "international_format": "+12069220880",
  "country_prefix": "+1",
  "country_code": "US",
  "country_name": "United States of America",
  "location": "Seattle",
  "line_type": "landline",
  "e164_format": "+12069220880",
  "national_format": "(206) 922-0880"
}

Keep reading

Start using our Phone number API for free today!

Get 100 requests / month for free