---
title: "Parse a phone number in C#"
url: https://recursiveai.org/onecontact/cookbook/parse-phone-number/
description: "Parse a phone number in C# with OneContact: free, open-source .NET code, a runnable example and real output."
version: "1.0.0"
---

# 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.

[NuGet](https://www.nuget.org/packages/RecursiveAI.OneContact) · [GitHub](https://github.com/recursive-ai-oss/onecontact-csharp) · [Docs](https://recursiveai.org/onecontact/docs/)

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

```shell
dotnet add package RecursiveAI.OneContact
```

Requires [.NET 10](https://dotnet.microsoft.com/download/dotnet/10.0) (net10.0); .NET 9 and earlier aren’t supported.

```csharp
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)](https://recursiveai.org/onecontact/cookbook/parse-phone-number/parse-phone-number.zip)**: unzip, then `dotnet run`.

## Full program

```csharp
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:

```csharp
using RecursiveAI.OneContact;

if (PhoneNumber.TryParse("+1 202-555-0123", out var phone))
    Console.WriteLine(phone.Canonical);
else
    Console.WriteLine("Cannot parse");
```

```text
+12025550123
```

## Related recipes

- [Validate a phone number in C#](https://recursiveai.org/onecontact/cookbook/validate-phone-number/)
- [Format a phone number as E.164 in C#](https://recursiveai.org/onecontact/cookbook/format-phone-number-e164/)
- [Validate an email address in C#](https://recursiveai.org/onecontact/cookbook/validate-email-address/)
- [Extract email addresses from text in C#](https://recursiveai.org/onecontact/cookbook/extract-emails-from-text/)

## 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](https://recursiveai.org/onecontact/docs/phones/) 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](https://recursiveai.org/onecontact/docs/overview/) states: “Version 1.0 runs on rules and markup alone.”
