libphonenumber-csharp 9.0.36

Build status codecov NuGet OpenSSF Scorecard

C# port of Google's libphonenumber library.

The code was rewritten from the Java source mostly unchanged, please refer to the original documentation for sample code and API documentation.

The original Apache License 2.0 was preserved.

Tip

Try the interactive demo → — parse, format, validate, and find phone numbers in your browser. No install required; runs entirely via WebAssembly.

See this for details about the port.

Phone number metadata is updated in the Google repo approximately every two weeks. This library is automatically updated by a scheduled github action to include the latest metadata, usually within a day. See Metadata updates for how that works and how to run it manually.

Installation

Run the following command to add this library to your project

dotnet add package libphonenumber-csharp

Available on NuGet as package libphonenumber-csharp.

Examples

Parsing a phone number

using PhoneNumbers;

var phoneNumberUtil = PhoneNumberUtil.GetInstance();
var e164PhoneNumber = "+44 117 496 0123";
var nationalPhoneNumber = "2024561111";
var smsShortNumber = "83835";
var phoneNumber = phoneNumberUtil.Parse(e164PhoneNumber, null);
phoneNumber = phoneNumberUtil.Parse(nationalPhoneNumber, "US");
phoneNumber = phoneNumberUtil.Parse(smsShortNumber, "US");

Formatting a phone number

using PhoneNumbers;

var phoneNumberUtil = PhoneNumberUtil.GetInstance();
var phoneNumber = phoneNumberUtil.Parse("+14156667777", "US");
var formattedPhoneNumber = phoneNumberUtil.Format(phoneNumber, PhoneNumberFormat.INTERNATIONAL);
var formattedPhoneNumberNational = phoneNumberUtil.Format(phoneNumber, PhoneNumberFormat.NATIONAL);

Console.WriteLine(formattedPhoneNumber.ToString()); // +1 415-666-7777
Console.WriteLine(formattedPhoneNumberNational.ToString()); // (415) 666-7777

Check if a phone number is valid

using PhoneNumbers;

var phoneNumberUtil = PhoneNumberUtil.GetInstance();
var phoneNumber = phoneNumberUtil.Parse("+14156667777", "US");
var isValid = phoneNumberUtil.IsValidNumber(phoneNumber);

Console.WriteLine(isValid); // true

Get the type of a phone number

using PhoneNumbers;

var phoneNumberUtil = PhoneNumberUtil.GetInstance();
var phoneNumber = phoneNumberUtil.Parse("+14156667777", "US");
var numberType = phoneNumberUtil.GetNumberType(phoneNumber);

Console.WriteLine(numberType); // PhoneNumberType.FIXED_LINE_OR_MOBILE

See PhoneNumberType.cs for the various possible types of phone numbers

Get the region code for a phone number

using PhoneNumbers;

var phoneNumberUtil = PhoneNumberUtil.GetInstance();
var phoneNumber = phoneNumberUtil.Parse("+14156667777", null);
var regionCode = phoneNumberUtil.GetRegionCodeForNumber(phoneNumber);

Console.WriteLine(regionCode); // US

Get the time zones for a phone number

using PhoneNumbers;

var phoneNumberUtil = PhoneNumberUtil.GetInstance();
var timeZonesMapper = PhoneNumberToTimeZonesMapper.GetInstance();
var phoneNumber = phoneNumberUtil.Parse("+12128120000", null);
var timeZones = timeZonesMapper.GetTimeZonesForNumber(phoneNumber);

Console.WriteLine(string.Join(", ", timeZones)); // America/New_York

Returns a List<string> of IANA time zone identifiers. For numbers that span multiple time zones (e.g. a country-level lookup), the list will contain more than one entry. Returns ["Etc/Unknown"] for invalid or unrecognised numbers.

Use GetTimeZonesForGeographicalNumber instead if you have already validated the number and want to skip the internal type check.

Get the carrier name for a phone number

using PhoneNumbers;

var phoneNumberUtil = PhoneNumberUtil.GetInstance();
var carrierMapper = PhoneNumberToCarrierMapper.GetInstance();
var phoneNumber = phoneNumberUtil.Parse("+917503397672", null);
var carrierName = carrierMapper.GetNameForNumber(phoneNumber, Locale.English);

Console.WriteLine(carrierName); // Aircel

Note: Carrier data reflects the original network allocation. If the country supports mobile number portability, the number may have since moved to a different carrier. Use GetSafeDisplayName to return an empty string in those regions.

Features

  • Parsing/formatting/validating phone numbers for all countries/regions of the world.
  • GetNumberType - gets the type of the number based on the number itself; able to distinguish Fixed-line, Mobile, Toll-free, Premium Rate, Shared Cost, VoIP and Personal Numbers (whenever feasible).
  • IsNumberMatch - gets a confidence level on whether two numbers could be the same.
  • GetExampleNumber/GetExampleNumberByType - provides valid example numbers for 218 countries/regions, with the option of specifying which type of example phone number is needed.
  • IsPossibleNumber - quickly guessing whether a number is a possible phone number by using only the length information, much faster than a full validation.
  • AsYouTypeFormatter - formats phone numbers on-the-fly when users enter each digit.
  • FindNumbers - finds numbers in text input
  • PhoneNumberToCarrierMapper - looks up the carrier name originally assigned to a mobile or pager number, with locale-aware output and a safe-display mode for regions with mobile number portability.

See PhoneNumberUtil.cs for the various methods and properties available.

Why keep libphonenumber-csharp up to date?

A lot of the functionality depends on updated metadata that is published by the google repository, see example here.

This means that if you don't keep the package up to date, methods like IsValidNumber will return false for newer numbers that rely on the updated metadata

Therefore, we recommend you keep this nuget package as up to date as possible using automated means (such as dependabot) as metadata changes published by the google repository is frequent, usually a few times a month.

For more information on metadata usage, please refer to the main repository faq

ToDo

  • update / add / port new unit tests and logging from java source

How to unfold automatic generated files

  • Install Jetbrains - Resharper for Visual Studio
  • File by file, right click and "Cleanup code"
  • Check the unfolded file

Running tests locally

dotnet test csharp/PhoneNumbers.sln

Metadata updates

The create_new_release_on_new_metadata_update workflow runs daily and drives lib/github-actions-metadata-update.sh. When the latest google/libphonenumber release is newer than the published NuGet package, it copies the upstream resources/, regenerates csharp/PhoneNumbers/LocaleData.cs, builds and tests, then commits, pushes and creates a matching GitHub release.

Before doing any of that it inspects the upstream diff and stops if it contains .java or .proto files, because changes to the Java sources may need porting by hand and an unattended metadata bump would silently skip them.

Skipping the java (or proto) check

If you have reviewed the upstream diff and the Java changes don't need porting (for example test-only or build-file changes), you can run the update anyway:

  • From the Actions UI — open create_new_release_on_new_metadata_update, click Run workflow, and tick skip_java_check (and/or skip_proto_check). Scheduled runs always leave both unticked.

  • Locally — pass the flag or set the environment variable:

    bash lib/github-actions-metadata-update.sh --skip-java-check "$GITHUB_TOKEN"
    # or
    SKIP_JAVA_CHECK=true bash lib/github-actions-metadata-update.sh "$GITHUB_TOKEN"
    

    --skip-proto-check / SKIP_PROTO_CHECK work the same way, and --help lists every option.

Skipping a check means the release ships upstream metadata from a version whose Java-side changes were not ported, so read the upstream diff first — the script prints the offending filenames before it stops.

Dry runs

--dry-run (or the dry_run workflow input) runs every read-only step — version lookups, repository checks, the upstream diff gates, the upstream clone — reports what a real run would do, and stops before the first change to the working tree. Nothing is copied, generated, committed, pushed or released, no token is required, and the clean-main requirement is relaxed to a warning so it works from a feature branch:

# what would tonight's scheduled run do?
bash lib/github-actions-metadata-update.sh --dry-run

UPSTREAM_TAG and DEPLOYED_VERSION override the two version lookups, which lets you replay any historical release pair — useful for seeing how a given release trips the gates:

UPSTREAM_TAG=v9.0.33 DEPLOYED_VERSION=9.0.32 \
  bash lib/github-actions-metadata-update.sh --dry-run

Running it against a fork

Nothing about the target repository is hard-coded. The script commits and pushes through whatever checkout it runs in, and takes the repository to release from GITHUB_REPOSITORY — set automatically by GitHub Actions, and otherwise derived from the origin remote. So a fork releases to itself, and the dry-run summary names the repository it would publish to. UPSTREAM_REPOSITORY (default google/libphonenumber) and NUGET_PACKAGE_ID (default libphonenumber-csharp) are overridable the same way.

Contributing

See CONTRIBUTING.md

Donations

Buy me a beer

No packages depend on libphonenumber-csharp.

.NET 10.0

  • No dependencies.

.NET 8.0

  • No dependencies.

.NET 9.0

  • No dependencies.

.NET Standard 2.0

Version Downloads Last updated
9.0.36 1 08/06/2026
9.0.35 1 08/06/2026
9.0.34 2 08/06/2026
9.0.33 1 08/06/2026
9.0.32 0 06/05/2026
9.0.31 0 05/23/2026
9.0.30 0 05/07/2026
9.0.29 0 04/25/2026
9.0.28 0 04/14/2026
9.0.27 0 04/02/2026
9.0.26 0 03/14/2026
9.0.25 0 02/27/2026
9.0.24 0 02/14/2026
9.0.23 0 01/30/2026
9.0.22 0 01/16/2026
9.0.21 0 12/18/2025
9.0.20 0 12/05/2025
9.0.19 0 11/20/2025
9.0.18 0 11/07/2025
9.0.17 0 10/24/2025
9.0.16 0 10/11/2025
9.0.15 0 09/26/2025
9.0.14 0 09/16/2025
9.0.13 0 08/29/2025
9.0.12 0 08/16/2025
9.0.11 0 08/04/2025
9.0.10 0 07/18/2025
9.0.9 0 07/08/2025
9.0.8 0 06/25/2025
9.0.7 0 06/09/2025
9.0.6 0 05/28/2025
9.0.5 0 05/08/2025
9.0.4 0 04/25/2025
9.0.3 0 04/11/2025
9.0.2 0 03/28/2025
9.0.1 0 03/23/2025
8.13.55 0 02/14/2025
8.13.54 0 01/31/2025
8.13.53 0 01/21/2025
8.13.52 0 12/13/2024
8.13.51 0 12/02/2024
8.13.50 0 11/16/2024
8.13.49 0 11/04/2024
8.13.48 0 10/23/2024
8.13.47 0 10/04/2024
8.13.46 0 09/25/2024
8.13.45 0 09/06/2024
8.13.44 0 08/26/2024
8.13.43 0 08/09/2024
8.13.42 0 07/26/2024
8.13.41 0 07/25/2024
8.13.40 0 07/03/2024
8.13.39 0 06/15/2024
8.13.38 0 06/05/2024
8.13.37 0 05/17/2024
8.13.36 0 05/03/2024
8.13.35 1 08/06/2026
8.13.34 0 04/05/2024
8.13.33 0 03/25/2024
8.13.32 0 03/12/2024
8.13.31 1 08/06/2026
8.13.30 0 02/09/2024
8.13.29 0 01/26/2024
8.13.28 0 01/25/2024
8.13.27 0 12/21/2023
8.13.26 0 11/29/2023
8.13.25 0 11/20/2023
8.13.24 0 10/31/2023
8.13.23 0 10/17/2023
8.13.22 0 09/29/2023
8.13.21 0 09/20/2023
8.13.20 0 09/07/2023
8.13.19 0 08/22/2023
8.13.18 0 08/03/2023
8.13.17 0 07/27/2023
8.13.16 0 07/11/2023
8.13.15 0 07/11/2023
8.13.14 0 06/15/2023
8.13.13 1 08/06/2026
8.13.12 0 06/15/2023
8.13.11 0 04/27/2023
8.13.10 0 04/20/2023
8.13.9 0 04/10/2023
8.13.8 0 03/27/2023
8.13.7 0 03/03/2023
8.13.6 0 02/10/2023
8.13.5 1 08/07/2026
8.13.4 0 01/09/2023
8.13.3 0 12/22/2022
8.13.2 0 12/08/2022
8.13.1 0 11/28/2022
8.13.0 0 11/08/2022
8.12.57 0 10/14/2022
8.12.56 0 09/23/2022
8.12.55 0 09/09/2022
8.12.54 0 08/22/2022
8.12.53 0 08/08/2022
8.12.52 1 08/06/2026
8.12.51.1 0 07/12/2022
8.12.50 0 06/13/2022
8.12.49 0 06/01/2022
8.12.48 0 05/18/2022
8.12.47 0 05/18/2022
8.12.46 0 04/15/2022
8.12.45 0 03/14/2022
8.12.44 0 03/09/2022
8.12.43 0 02/14/2022
8.12.42 0 02/14/2022
8.12.41 0 02/14/2022
8.12.40 1 08/06/2026
8.12.39 0 02/14/2022
8.12.38 1 08/06/2026
8.12.37 0 12/15/2021
8.12.36 0 12/15/2021
8.12.35 0 12/15/2021
8.12.34 0 10/07/2021
8.12.33 0 09/23/2021
8.12.32 0 09/11/2021
8.12.31 0 09/11/2021
8.12.30 0 08/18/2021
8.12.29 0 08/18/2021
8.12.28 0 07/23/2021
8.12.27 0 07/08/2021
8.12.26 0 06/25/2021
8.12.25 1 08/07/2026
8.12.24 0 05/31/2021
8.12.23 0 05/13/2021
8.12.22 0 04/30/2021
8.12.21 0 04/08/2021
8.12.19 0 03/02/2021
8.12.18 1 08/07/2026
8.12.17 0 01/27/2021
8.12.16 0 01/15/2021
8.12.15 1 08/07/2026
8.12.14 1 08/06/2026
8.12.13 0 11/18/2020
8.12.11 0 10/09/2020
8.12.10 0 09/29/2020
8.12.9 0 09/02/2020
8.12.8 1 08/06/2026
8.12.7 0 07/21/2020
8.12.6 1 08/06/2026
8.12.5 0 07/06/2020
8.12.4 1 08/06/2026
8.12.3 0 05/08/2020
8.12.2 0 04/23/2020
8.12.1 1 08/06/2026
8.12.0 0 03/20/2020
8.11.5 0 03/03/2020
8.11.4 0 02/13/2020
8.11.3 0 02/03/2020
8.11.2 0 01/16/2020
8.11.1 0 12/12/2019
8.11.0 0 11/29/2019
8.10.23 0 11/18/2019
8.10.22 0 11/14/2019
8.10.21 0 10/17/2019
8.10.20 1 08/07/2026
8.10.19 0 09/21/2019
8.10.18 0 09/17/2019
8.10.17 0 08/16/2019
8.10.16 0 08/05/2019
8.10.15 0 07/18/2019
8.10.14 0 07/01/2019
8.10.13 0 05/31/2019
8.10.12 1 08/06/2026
8.10.11 0 05/07/2019
8.10.10 1 08/07/2026
8.10.9 1 08/06/2026
8.10.8 1 08/06/2026
8.10.7 1 08/06/2026
8.10.6 0 02/22/2019
8.10.5 0 02/08/2019
8.10.4 0 01/25/2019
8.10.3 0 01/11/2019
8.10.2 0 12/07/2018
8.10.1 1 08/06/2026
8.10.0 0 11/29/2018
8.9.16 0 10/19/2018
8.9.15 0 10/06/2018
8.9.14 0 09/21/2018
8.9.13 0 09/07/2018
8.9.12 0 08/25/2018
8.9.11 1 08/07/2026
8.9.10 0 07/12/2018
8.9.9 0 06/29/2018
8.9.8 0 06/15/2018
8.9.7 0 05/30/2018
8.9.6 0 05/16/2018
8.9.5 0 05/04/2018
8.9.4 0 04/17/2018
8.9.3 0 04/05/2018
8.9.2 0 03/19/2018
8.9.1 0 03/08/2018
8.9.0 0 02/22/2018
8.8.11 0 02/08/2018
8.8.10 0 01/25/2018
8.8.9 0 01/10/2018
8.8.8 0 12/08/2017
8.8.7 0 12/01/2017
8.8.6 0 11/17/2017
8.8.5 0 10/31/2017
8.8.4 0 10/17/2017
8.8.3 0 10/06/2017
8.8.2 0 09/22/2017
8.8.1 0 09/08/2017
8.8.0 0 08/22/2017
8.7.1 0 08/03/2017
8.7.0.1 0 07/21/2017
8.6.0.1 0 07/18/2017
8.6.0 1 08/06/2026
8.3.1.2 0 06/24/2017
8.3.1.1 0 03/13/2017
8.3.1 0 03/04/2017
7.7.4 0 11/13/2016
7.5.1 0 08/06/2016
7.2.5 0 02/11/2016
7.0.11 0 10/05/2015
7.0.9 0 08/16/2015
7.0.5.5 0 05/27/2015
7.0.5.4 0 05/23/2015
7.0.5.3 0 04/28/2015
7.0.5.1 0 04/27/2015
7.0.5 0 04/25/2015
4.10.0.62 1 08/06/2026
4.10.0.61 0 08/09/2012
4.10.0.59 0 07/27/2012
4.10.0.55 0 07/19/2012
4.9.0.52 0 07/13/2012
4.9.0.43 0 07/10/2012
4.9.0.42 0 07/09/2012
4.8.0.35 0 06/22/2012
4.8.0.33 0 06/16/2012
4.8.0.31 0 06/07/2012
4.8.0.30 0 05/31/2012
4.8.0.24 0 05/09/2012
4.7.0.21 0 04/28/2012
4.7.0.19 0 04/25/2012
4.6.0.16 0 03/30/2012
4.6.0.13 0 02/10/2012
4.5.0.9 0 01/30/2012
4.5.0.6 0 01/21/2012
4.5.0.4 0 01/20/2012
4.4.0.1 0 01/10/2012
3.8.0.400 0 11/28/2011
3.8.0.399 0 11/27/2011
3.8.0.394 0 11/24/2011
3.8.0.342 0 09/17/2011
3.7.1.342 0 09/17/2011
3.7.1.312 0 08/05/2011
3.7.1.306 0 08/05/2011