Recursive AI

Parse a phone number in C#

OneContact is a free, open-source contact data library for .NET from Recursive AI. MIT or Apache-2.0, no native dependencies, no network access.

Split a phone number into its calling code, national digits and extension.

Terminal
dotnet add package RecursiveAI.OneContact

Requires .NET 10 (net10.0); .NET 9 and earlier aren’t supported.

C#
using RecursiveAI.OneContact;
var phone = PhoneNumber.Parse(
    "(202) 555-0123 ext. 42", Region.US);
Console.WriteLine(phone.CountryCode);
Console.WriteLine(
    phone.NationalSignificantNumber);
Console.WriteLine(phone.Extension);
Text
1
2025550123
42

Download this example (.zip): unzip, then dotnet run.

Full program

C#
using RecursiveAI.OneContact;
 
var phone = PhoneNumber.Parse("020 7946 0123 ext. 42", Region.Parse("GB"));
Console.WriteLine($"Calling code: {phone.CountryCode}");
Console.WriteLine($"National number: {phone.NationalSignificantNumber}");
Console.WriteLine($"Extension: {phone.Extension}");
Console.WriteLine($"Region: {phone.Region}");
Console.WriteLine($"Valid: {phone.IsValid}");
Console.WriteLine($"Canonical: {phone.Canonical}");

dotnet run prints:

Text
Calling code: 44
National number: 2079460123
Extension: 42
Region: GB
Valid: True
Canonical: +442079460123;ext=42

A national number needs a default region. When parsing fails, Parse throws ContactParseException; use the variation for a Boolean result instead.

Variations

Parse international input without a default region, without throwing for rejected input:

C#
using RecursiveAI.OneContact;
 
if (PhoneNumber.TryParse("+1 202-555-0123", out var phone))
    Console.WriteLine(phone.Canonical);
else
    Console.WriteLine("Cannot parse");
Text
+12025550123

The short answer

Use OneContact’s PhoneNumber.Parse with the input’s default region, then read CountryCode, NationalSignificantNumber and Extension. For international text beginning with a plus sign, the region argument can be omitted. For user-entered national text, pass the region explicitly.

The snippet at the top parses a US number; the full program parses a British one. Both use fictional sample numbers written directly in the source. There are no files to download before running, no credentials to configure and no service to call.

How do I parse a phone number in C#?

Treat parsing as interpretation, not slicing. The country calling code can have different lengths. National input can include a national prefix, spaces, brackets or an extension. The parser applies the region’s rules and returns the parts instead of asking you to infer them from fixed character positions.

Use NationalSignificantNumber for the national digits as text. The API also exposes a numeric NationalNumber, but a numeric representation alone does not carry significant leading zeros. NationalSignificantNumber includes them. Don’t convert a phone number into an integer just to store it: it is an identifier with dialing rules, not a quantity.

An extension is a separate part. The example prints it separately and also shows how Canonical carries it as ;ext=42. E164 omits extensions, so choosing that property as your only stored value can discard a part of what the user entered. Decide which representation the receiving system supports before normalizing a batch.

The default region supplies context for national input; it is not a claim that every parsed number belongs to that region. International input can identify another calling code. Region reports the lookup result for the number, while CountryCode reports the calling code. These are distinct pieces of information, not interchangeable country identifiers.

How do I validate a parsed phone number in C#?

Parsing success and validity are separate. Read IsValid if you need the number to match a known number type in the numbering metadata. Read GetPossibility() if you need a length-oriented explanation such as too short. The full program prints validity alongside the parts so a caller does not confuse a structured result with a confirmed working line.

For form input, prefer the TryParse variation. It returns false for input the parser cannot read, letting your application display a useful error without catching a parse exception. With no region, non-international input is rejected with phone.region-required; supply the actual region or ask for a plus-prefixed number. Don’t substitute the machine’s culture as country context unless that is truly the intended input contract.

The phone notes document accepted prefixes, punctuation, Unicode decimal digits, vanity numbers and extension syntax. They also list the reason codes and the explicit-metadata parser. Keep a single parsed value for later formatting and checks rather than repeatedly manipulating the original string. That makes the distinction between the original text, parsed parts and output format visible throughout your import or form-handling code.

As the OneContact release overview states: “Version 1.0 runs on rules and markup alone.”

All onecontact recipes