---
title: "Parse a postal address in C#"
url: https://recursiveai.org/onecontact/cookbook/parse-postal-address/
description: "Parse a postal address into street, city, state and postal code in C# with OneContact. Run the .NET example with no network access."
version: "1.0.0"
---

# Parse a postal address 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/) · [Download example (.zip)](https://recursiveai.org/onecontact/cookbook/parse-postal-address/parse-postal-address.zip)

Split a postal address into fields with an explicit country. Free-text parsing is available for the supported countries, not every country for which the library knows address fields and formatting rules.

```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 address = PostalAddress.Parse(
    "123 Main St, Springfield, IL 62704",
    Region.US);
Console.WriteLine(address.Locality);
```

```text
Springfield
```

Unzip [the example](https://recursiveai.org/onecontact/cookbook/parse-postal-address/parse-postal-address.zip), then `dotnet run`.

Free-text parsing supports the United States (including Puerto Rico, the US Virgin Islands, Guam, American Samoa, the Northern Mariana Islands and the US Minor Outlying Islands), Canada, Mexico, Australia, the United Kingdom (plus Jersey, Guernsey and the Isle of Man), Austria, Belgium, Croatia, Czechia, Denmark, Estonia, Finland, France, Germany, Hungary, Ireland, Italy, Latvia, Lithuania, Luxembourg, Malta, the Netherlands, Poland, Portugal, Romania, Slovakia, Slovenia, Spain, Sweden, Switzerland, Norway, Iceland, Liechtenstein, Andorra, Monaco, San Marino and Vatican City, plus French Guiana, Guadeloupe, Martinique, Réunion and Mayotte. This is the [documented free-text coverage](https://recursiveai.org/onecontact/docs/address-structural/#coverage); knowing a country’s field layout does not mean its free-text parser is available.

## Full program

The download includes a fuller example with invented input embedded in `Program.cs`:

```csharp
using RecursiveAI.OneContact;

var address = PostalAddress.Parse(
    "123 Main St, Springfield, IL 62704", Region.US);
Console.WriteLine(address.StreetLines[0]);
Console.WriteLine(address.Locality);
Console.WriteLine(address.AdminArea);
Console.WriteLine(address.PostalCode);
```

`dotnet run` prints:

```text
123 MAIN ST
Springfield
IL
62704
```

Rejected text makes `TryParse` return false; `Parse` throws `ContactParseException` when it cannot parse the address.

## Variations

Handle unrecognized address text without an exception:

```csharp
using RecursiveAI.OneContact;

if (PostalAddress.TryParse("not an address", Region.US,
    out var address))
    Console.WriteLine(address.Canonical);
else
    Console.WriteLine("Address not parsed");
```

```text
Address not parsed
```

## Related recipes

- [Extract contact information from HTML in C#](https://recursiveai.org/onecontact/cookbook/extract-contacts-from-html/)
- [Parse a URL in C#](https://recursiveai.org/onecontact/cookbook/parse-url/)
- [Get the domain from a URL in C#](https://recursiveai.org/onecontact/cookbook/get-domain-from-url/)
- [Format a postal address by country in C#](https://recursiveai.org/onecontact/cookbook/format-postal-address/)

## The short answer

Use `PostalAddress.Parse(text, country)` to split a supported free-text address into fields. The snippet at the top passes `Region.US` and prints the locality; the full program also prints the street, administrative area and postal code. For imported or user-entered text that may fail, use the `TryParse` variation.

An explicit country supplies context for interpreting the address. A short street or postal code is not enough to reliably determine a country. Version 1.0 uses rules; it refuses text those rules cannot read rather than providing a trained-model fallback. The [address documentation](https://recursiveai.org/onecontact/docs/address-structural/) distinguishes free-text parsing from the structural layer.

## How can I parse an address into its individual components in C#?

Read `StreetLines`, `Locality`, `AdminArea` and `PostalCode` from the parsed value. These names avoid assuming that every country has a US-style city and state. Street lines are a collection, not one universal street string. The full program indexes the first line only because its supplied input is a single-street-line example.

The input on this page is invented and included directly in the program. Notice that the returned street is `123 MAIN ST`, not an exact copy of the input capitalization. Parsing can standardize recognized address elements. Keep the source text too when your application needs an audit trail or wants a person to compare the parsed result with what was submitted.

Consult the supported-country list above before accepting free text for a new region; formatting known fields and parsing free text have different coverage.

Use the boolean `TryParse` overload with an explicit region. It returns false on a rejected value, as the variation shows for `not an address`. Do not read fields from the output value after failure or silently substitute an empty address into a customer record.

For an import interface, preserve the original row and let the user correct it or enter fields manually. The detailed parsing overloads return `ParseDetail` for callers that need reason codes. Unsupported free-text countries report `address.free-text-refused`; text without enough country evidence is a different problem from text that is malformed for a known country.

## How do I standardize a Canadian address?

```csharp
using RecursiveAI.OneContact;
var address = PostalAddress.Parse("123 Main St, Toronto ON M5V 2T6", Region.CA);
Console.WriteLine(address.Canonical);
```

```text
123 MAIN ST, TORONTO ON M5V 2T6
```

Use `Region.CA` when the text is Canadian rather than attempting to interpret it as a US address first. The country selects the rules and the expected roles of the province and postal code. The [United States and Canada rules](https://recursiveai.org/onecontact/docs/address-rules-us-ca/) describe what the parser standardizes in those countries.

Keep parsing, structural checks and deliverability as separate decisions. `Validate()` checks an address against country structure, including required fields and postal-code patterns. It does not consult a postal delivery database. A well-formed address that does not exist can pass. Neither successful parsing nor an empty validation-issue list establishes that a resident or business receives mail there.

If your application already has separate address fields, construct the address with `PostalAddress.Create` instead of joining fields into a guessed string and parsing them again. That avoids discarding information merely to recover it through free-text rules.
