Use the Public Suffix List to get the registrable domain—the public suffix plus the label before it—rather than guessing from the last two parts of a hostname.
dotnet add package RecursiveAI.OneContactRequires .NET 10 (net10.0); .NET 9 and earlier aren’t supported.
using RecursiveAI.OneContact; var url = WebAddress.Parse( "https://shop.example.co.uk/cart"); Console.WriteLine(url.RegistrableDomain);
example.co.ukUnzip the example, then dotnet run.
Full program
The download includes a fuller example with invented input embedded in Program.cs:
using RecursiveAI.OneContact; var url = WebAddress.Parse("https://shop.example.co.uk/cart"); Console.WriteLine(url.Host); Console.WriteLine(url.PublicSuffix); Console.WriteLine(url.RegistrableDomain);
dotnet run prints:
shop.example.co.uk co.uk example.co.uk
An invalid URL makes Parse throw ContactParseException; RegistrableDomain is null for IP hosts and hosts that are themselves public suffixes.
Variations
Choose whether private suffixes count:
using RecursiveAI.OneContact.Web; Console.WriteLine(PublicSuffixList.GetRegistrableDomain( "ada.github.io")); Console.WriteLine(PublicSuffixList.GetRegistrableDomain( "ada.github.io", includePrivateSection: false));
ada.github.io github.io
Related recipes
- Extract contact information from HTML in C#
- Parse a URL in C#
- Parse a postal address in C#
- Format a postal address by country in C#
The short answer
Parse the URL with WebAddress.Parse and read RegistrableDomain. For https://shop.example.co.uk/cart, the host is shop.example.co.uk, the public suffix is co.uk, and the registrable domain is example.co.uk. Taking only the last two labels would incorrectly produce co.uk.
OneContact ships a pinned Public Suffix List and performs the lookup locally. The public suffix is the part under which registrations are organized; the registrable domain adds the label immediately to its left. The Public Suffix List documentation explains the shipped data and lookup rules.
How do I get just the domain name from a URL in C#?
First decide which meaning of “domain” your feature needs. Host is the complete hostname, including subdomains. PublicSuffix is the suffix recognized by the list. RegistrableDomain is the base registration unit for that suffix. Print all three while building an importer so that the intended boundary is visible.
Use the host when a specific subdomain matters, such as separate service endpoints. Use the registrable domain when grouping website addresses at a broader domain boundary. Neither answer identifies the legal owner of a website. One company can operate several domains, and several organizations can share hosting infrastructure.
The URL wrapper also handles removing the scheme, port and path before consulting the list. Do not pass an entire URL directly to the hostname-only PublicSuffixList methods. Those methods expect a domain name and return null for input containing URL punctuation such as a slash or colon.
How do I get a domain without the subdomain in C#?
Use RegistrableDomain, not a rule that simply strips www.. Hosts can have arbitrary subdomain labels, and suffixes can contain more than one label. The list also has wildcard and exception rules; counting dots cannot reproduce those boundaries reliably.
An IP address has no registrable domain. A host that is itself a public suffix has none either. Keep the nullable result in your data model rather than turning an absent answer into a fake domain. If your interface needs a fallback display value, the full host is still available, but it should not be labeled as a registrable domain.
How do I use the Public Suffix List in C#?
For a domain you already have, call PublicSuffixList.GetRegistrableDomain or GetPublicSuffix. The variation demonstrates the private-section option. With the default setting, ada.github.io is a registrable domain because github.io is a private suffix. With private rules excluded, the boundary moves and the result is github.io.
Choose the setting to match your grouping policy and use it consistently. Including private rules keeps different hosted tenants apart at that boundary; ignoring them groups at the underlying registration boundary. The lookup accepts Unicode and Punycode labels and returns lowercase answers, keeping the script used by the domain input.
The data is bundled, not downloaded during a lookup. That makes results reproducible for the installed package, but it also means the list is the package’s pinned snapshot rather than a live view of registration policy. A registrable-domain result is not a DNS lookup, ownership check or promise that the name is available to register.