ProvenPin Install

phonenumbers parse, format and validate E.164 numbers: working versions (tested 2026-10-16)

Normalize phone numbers to E.164 with Google's phonenumbers, tell possible apart from valid, and map numbers back to a region, all offline.

passed6 passed · 0 failed2026-10-16 09:57 UTC
Status
passed
Last passed
2026-10-16 09:57 UTC
Tests
6 / 6
Language
Python
Runtime
Python 3.13.16
pinned versions2
phonenumbers@9.0.41pytest@9.1.1
run it
uv venv -q .venv && uv pip install -q --python .venv/bin/python -r requirements.txt
.venv/bin/python -m pytest -q
test environment
Python 3.13.16
linux 6.17.0-1022-azure
x64
runner: github-actions 38883899161

The code

Exactly the files that passed. Your agent can pull them with get_recipe("phonenumbers-parse-format") (install), or see them on GitHub.

requirements.txt
phonenumbers==9.0.41
pytest==9.1.1
phone.py
import phonenumbers
from phonenumbers import PhoneNumberFormat


def parse_valid(raw: str, region: str | None = None) -> phonenumbers.PhoneNumber:
    number = phonenumbers.parse(raw, region)
    if not phonenumbers.is_valid_number(number):
        raise ValueError(f"not a valid number: {raw!r}")
    return number


def to_e164(raw: str, region: str | None = None) -> str:
    return phonenumbers.format_number(parse_valid(raw, region), PhoneNumberFormat.E164)


def country_of(raw: str, region: str | None = None) -> str | None:
    return phonenumbers.region_code_for_number(parse_valid(raw, region))
tests/test_phone.py
import phonenumbers
import pytest
from phonenumbers import NumberParseException, PhoneNumberFormat

from phone import country_of, parse_valid, to_e164


def test_normalizes_national_number_to_e164():
    assert to_e164("(650) 253-0000", "US") == "+16502530000"
    assert to_e164("+16502530000") == "+16502530000"


def test_region_hint_required_when_plus_is_missing():
    with pytest.raises(NumberParseException) as exc:
        phonenumbers.parse("6502530000", None)
    assert exc.value.error_type == NumberParseException.INVALID_COUNTRY_CODE


def test_possible_is_not_the_same_as_valid():
    number = phonenumbers.parse("+11999999999", None)
    assert phonenumbers.is_possible_number(number)
    assert not phonenumbers.is_valid_number(number)
    with pytest.raises(ValueError):
        to_e164("+11999999999")


def test_free_text_raises_before_validation():
    with pytest.raises(NumberParseException) as exc:
        phonenumbers.parse("call me maybe", "US")
    assert exc.value.error_type == NumberParseException.NOT_A_NUMBER


def test_formats_and_region_for_gb_number():
    number = parse_valid("+442083661177")
    assert phonenumbers.format_number(number, PhoneNumberFormat.INTERNATIONAL) == "+44 20 8366 1177"
    assert phonenumbers.format_number(number, PhoneNumberFormat.NATIONAL) == "020 8366 1177"
    assert country_of("+442083661177") == "GB"


def test_non_geographic_numbers_report_region_001():
    assert country_of("+80012345678") == "001"
pytest.ini
[pytest]
pythonpath = .

Connect to ProvenPin

Add the free MCP server so your agent can pull this recipe and others like it. Same setup as the docs.

terminal
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp

Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.