Phone Validation

2 endpoints for parsing and validating phone numbers in any format, with carrier and line-type detection.

Endpoint Purpose
GET /v1/geo/phone-validate Validate a single phone number; returns E.164, carrier, line type
POST /v1/geo/phone-validate-batch Validate up to 50 numbers in one request

Python SDK Examples

Validate a single phone number

phone_validate parses a number in any national or international format and validates it against E.164 rules using the phonenumbers library (Google libphonenumber).

from toolkitapi import Geo

with Geo(api_key="tk_...") as geo:
    result = geo.phone_validate("(212) 555-0100", country="US")

    print(result["valid"])           # True
    print(result["e164"])            # "+12125550100"
    print(result["national"])        # "(212) 555-0100"
    print(result["international"])   # "+1 212-555-0100"
    print(result["country_code"])    # 1
    print(result["country"])         # "US"
    print(result["line_type"])       # "fixed_line"
    print(result["carrier"])         # "Verizon" (or None if unknown)

Validate phone numbers from multiple countries

from toolkitapi import Geo

test_numbers = [
    ("+44 20 7946 0958",     "GB"),  # UK London number
    ("+49 30 1234567",       "DE"),  # German Berlin number
    ("+81 3-1234-5678",      "JP"),  # Japanese Tokyo number
    ("+61 2 9876 5432",      "AU"),  # Australian Sydney number
    ("07700 900123",         "GB"),  # UK mobile (no country prefix)
    ("not-a-number",         "US"),  # Invalid
]

with Geo(api_key="tk_...") as geo:
    for number, country in test_numbers:
        result = geo.phone_validate(number, country=country)
        status = "✓" if result["valid"] else "✗"
        e164 = result.get("e164", "—")
        line = result.get("line_type", "—")
        print(f"{status} {number:25} → {e164:18} [{line}]")

Output:

✓ +44 20 7946 0958         → +442079460958      [fixed_line]
✓ +49 30 1234567           → +493012345670      [fixed_line]
✓ +81 3-1234-5678          → +81312345678       [fixed_line]
✓ +61 2 9876 5432          → +61298765432       [fixed_line]
✓ 07700 900123             → +447700900123      [mobile]
✗ not-a-number             → —                  [—]

Validate and normalise a phone field on form submission

from toolkitapi import Geo

def normalise_phone(raw_input: str, default_country: str = "US") -> str | None:
    """Return E.164 format or None if the number is invalid."""
    with Geo(api_key="tk_...") as geo:
        result = geo.phone_validate(raw_input, country=default_country)
    return result["e164"] if result["valid"] else None

# Examples
print(normalise_phone("212-555-0100"))         # "+12125550100"
print(normalise_phone("07700 900123", "GB"))   # "+447700900123"
print(normalise_phone("abc"))                  # None

Batch validation

phone_validate_batch accepts up to 50 numbers and returns individual results plus a validation summary:

from toolkitapi import Geo

numbers = [
    "+12125550100",
    "+44 20 7946 0958",
    "not-valid",
    "+81 3-1234-5678",
    "+61 2 9876 5432",
    "000",
]

with Geo(api_key="tk_...") as geo:
    response = geo.phone_validate_batch(numbers, default_country="US")

print(f"Total:   {response['summary']['total']}")
print(f"Valid:   {response['summary']['valid']}")
print(f"Invalid: {response['summary']['invalid']}")
print(f"Line types: {response['summary']['line_types']}")

for r in response["results"]:
    status = "✓" if r["valid"] else "✗"
    print(f"  {status} {r['input']:20} → {r.get('e164', '—')}")

Clean a CSV of phone numbers

import csv
from toolkitapi import Geo

def clean_phone_csv(input_path: str, output_path: str, default_country: str = "US") -> None:
    """Read a CSV with a 'phone' column, validate, and write E.164 output."""
    with open(input_path, newline="") as f:
        rows = list(csv.DictReader(f))

    numbers = [row["phone"] for row in rows]

    # Process in chunks of 50 (API limit)
    results = []
    with Geo(api_key="tk_...") as geo:
        for i in range(0, len(numbers), 50):
            batch = numbers[i:i + 50]
            response = geo.phone_validate_batch(batch, default_country=default_country)
            results.extend(response["results"])

    for row, result in zip(rows, results):
        row["phone_e164"] = result.get("e164") or ""
        row["phone_valid"] = result["valid"]
        row["phone_line_type"] = result.get("line_type") or ""

    fieldnames = list(rows[0].keys())
    with open(output_path, "w", newline="") as f:
        writer = csv.DictWriter(f, fieldnames=fieldnames)
        writer.writeheader()
        writer.writerows(rows)

Filter out non-mobile numbers

from toolkitapi import Geo

leads = [
    "+12125550100",
    "+447700900123",
    "+14155552671",
    "+441632960961",
]

with Geo(api_key="tk_...") as geo:
    response = geo.phone_validate_batch(leads)

mobile_only = [
    r["e164"]
    for r in response["results"]
    if r["valid"] and r.get("line_type") in ("mobile", "fixed_line_or_mobile")
]
print("Mobile numbers:", mobile_only)

Response Fields

phone-validate response:

Field Type Description
input string Original input
valid bool Whether the number is valid
e164 string | null E.164 formatted number (e.g. +12125550100)
national string | null National format (e.g. (212) 555-0100)
international string | null International format
country_code int | null Numeric country dialling code
country string | null ISO 3166-1 alpha-2 country code
region string | null Geographic description (city/state)
carrier string | null Carrier name if known
line_type string | null mobile, fixed_line, voip, toll_free, etc.

phone-validate-batch response:

Field Type Description
total int Number of numbers submitted
results list Per-number result objects (same fields as single validate)
summary.valid int Count of valid numbers
summary.invalid int Count of invalid numbers
summary.line_types object Counts grouped by line type

Tip

Always store phone numbers in E.164 format (+12125550100) rather than whatever the user typed. E.164 is unambiguous, sortable, and works with SMS and voice APIs without additional formatting. Use phone_validate on input, store e164, and only convert back to national format for display.