Recursive AI

Find a phone number’s country, area and carrier 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.

Look up the country and area associated with a phone number. These are offline numbering-table descriptions.

Not GPS, not tracking: this lookup does not report the phone’s live location.

Terminal
dotnet add package RecursiveAI.OneContact.Phones.Geo

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

C#
using RecursiveAI.OneContact;
using RecursiveAI.OneContact.Phones.Geo;
var phone = PhoneNumber.Parse(
    "+44 20 7946 0123");
Console.WriteLine(phone.Region);
Console.WriteLine(PhoneGeocoder.Default
    .GetDescription(phone, "en"));
var carrier = PhoneCarrierMapper.Default
    .GetSafeDisplayName(phone, "en");
Console.WriteLine(carrier.Length == 0
    ? "unavailable" : carrier);
Text
GB
London
unavailable

unavailable means the safe lookup returned no carrier name.

Unzip the example, then dotnet run.

Full program

All sample input is written directly in the program.

C#
using RecursiveAI.OneContact;
using RecursiveAI.OneContact.Phones.Geo;
 
var phone = PhoneNumber.Parse("+44 20 7946 0123");
Console.WriteLine($"Region: {phone.Region}");
Console.WriteLine($"Area: {PhoneGeocoder.Default.GetDescription(phone, "en")}");
var carrier = PhoneCarrierMapper.Default.GetSafeDisplayName(phone, "en");
Console.WriteLine($"Safe carrier: {(carrier.Length == 0 ? "unavailable" : carrier)}");
foreach (var zone in PhoneTimeZoneMapper.Default.GetTimeZones(phone))
    Console.WriteLine($"Time zone: {zone}");

dotnet run prints:

Text
Region: GB
Area: London
Safe carrier: unavailable
Time zone: Europe/London

Invalid input makes PhoneNumber.Parse throw ContactParseException; the safe carrier lookup returns an empty string when it cannot give a safe answer.

Variations

Request a description in French. For this number, the lookup falls back to the English area name, so it still prints London:

C#
using RecursiveAI.OneContact;
using RecursiveAI.OneContact.Phones.Geo;
var phone = PhoneNumber.Parse("+44 20 7946 0123");
Console.WriteLine(PhoneGeocoder.Default
    .GetDescription(phone, "fr"));
Text
London

The short answer

For a C# phone number location lookup, parse the number with OneContact and read Region. Add RecursiveAI.OneContact.Phones.Geo for PhoneGeocoder, PhoneCarrierMapper and PhoneTimeZoneMapper. The example returns GB and London for a fictional British landline. It does not locate a handset, identify its owner or confirm that the line is active.

The carrier result is deliberately displayed as unavailable in this example. GetSafeDisplayName only answers for regions where number portability does not apply. An empty result is not an error and does not mean the phone has no carrier. These behaviors are documented in the geocoder and carrier notes.

Can you track a phone number’s location?

Not with this lookup. The geocoder describes the number using embedded tables. A returned area name is a description associated with a number range, not a measurement of where a person or device is now. There is no GPS input, location permission or live operator request in this program.

Use the result for a country or area label in a contact import, with wording that makes its meaning clear. “Number area: London” describes the result more accurately than “Current location: London”. Some numbers have no useful area description; callers must be able to display an empty result without inventing one.

Region and CountryCode are different properties. The former reports a region identifier, while the latter is the dialing code. If the application needs a country label, don’t turn the calling code into a country by string slicing. Parse first and use the metadata result. The phone parsing notes explain the core properties and the distinction between parsing and validity.

How do I find a phone number’s carrier in C#?

The mapper describes the carrier a number range was first assigned to. As the package documentation says: “Never treat the carrier as the current one, and never as proof of who operates a line.” Portability means a subscriber may have moved the number elsewhere.

The safe mapper in the snippet at the top avoids returning a name in portability regions. Keep that distinction in downstream storage too: don’t label a historical range assignment as a verified current provider. The full program converts the empty result into the readable label unavailable; the snippet at the top does the same.

The package references the core library and carries its own compiled tables. No separate dataset download is required to run the example. Language tags are explicit, so the result does not change with the process’s current culture.

How do I format a phone number internationally in C#?

Use the parsed number’s E164 property rather than the area description. Geographic descriptions are display text and are not dialing strings. An international number starts with its calling code; a national number needs a default region so the parser can interpret it.

The E.164 formatting recipe covers the output representation separately. Keep the original input when you need to explain an import result, and keep the parsed extension separately when the receiving system needs it: E.164 does not carry the extension. Neither a formatted number nor a geographic description confirms that a call will connect.

All onecontact recipes