Recursive AI

Parse a URL 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.

Turn a URL into a normalized value and read its host, path and query. Normalization removes fragments and recognized tracking parameters. Beyond the URL components available through .NET’s System.Uri, OneContact provides contact-oriented canonicalization, a versioned comparison key and Public Suffix List domain boundaries.

Terminal
dotnet add package RecursiveAI.OneContact

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

C#
using RecursiveAI.OneContact;
 
var url = WebAddress.Parse(
    "https://EXAMPLE.com/shop#top");
Console.WriteLine(url.Canonical);
Console.WriteLine(url.Host);
Text
https://example.com/shop
example.com

Unzip the example, then dotnet run.

Full program

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

C#
using RecursiveAI.OneContact;
 
var url = WebAddress.Parse(
    "HTTPS://Example.com:443/shop?id=7&utm_source=news#top");
Console.WriteLine(url.Canonical);
Console.WriteLine($"Host: {url.Host}");
Console.WriteLine($"Path: {url.Path}");
Console.WriteLine($"Query: {url.Query}");

dotnet run prints:

Text
https://example.com/shop?id=7
Host: example.com
Path: /shop
Query: id=7

Rejected URL text makes TryParse return false; Parse instead throws ContactParseException.

Variations

Accept a URL without an explicit scheme:

C#
using RecursiveAI.OneContact;
 
if (WebAddress.TryParse("example.com:8080/shop", out var url))
    Console.WriteLine(url.Canonical);
else
    Console.WriteLine("Invalid URL");
Text
https://example.com:8080/shop

The short answer

Call WebAddress.Parse and read Host, Path and Query from the resulting value. Use Canonical when you want OneContact’s normalized contact URL. The full program prints https://example.com/shop?id=7: the hostname is lowercased, the default HTTPS port disappears, and the tracking parameter and fragment are removed.

This is useful for cleaning website fields in a contact database. It is not a lossless round trip of the original URL. Keep the original input separately when your application needs to reproduce exactly what someone entered. The web address documentation defines the normalization and comparison rules.

How do I parse a URL in C#?

The full program supplies one complete URL and prints the parsed components. Host excludes the scheme and path. Path is the path portion, and Query is the query content without its leading question mark. Port is nullable, so a URL with no retained explicit port does not need a made-up numeric default in your data model.

For form input or imported rows, use TryParse rather than treating every rejection as an exception. The variation shows the boolean overload. Missing schemes are assumed to be HTTPS; a host followed by a port remains a host-and-port input. This is convenient for website fields where people commonly enter a bare hostname.

OneContact follows the WHATWG URL parsing model, including internationalized domain processing and IP hosts. Parsing accepts non-website schemes too. Check IsWebsite if your field is meant to hold only HTTP and HTTPS website addresses; a syntactically accepted URL is not automatically suitable for a clickable website field.

How do I get query string parameters from a URL in C#?

Query gives you the retained query string, not a dictionary of individually decoded parameters. In this example it is exactly id=7. Decide whether you need the contact-normalized query or the original query before doing further processing: OneContact intentionally removes its documented list of tracking parameter names, including the utm_source used above.

Use .NET’s HttpUtility.ParseQueryString to read the retained query, including repeated values:

C#
using RecursiveAI.OneContact;
using System.Web;
 
var url = WebAddress.Parse(
    "https://example.com/shop?id=7&tag=red&tag=blue");
var query = HttpUtility.ParseQueryString(url.Query ?? "");
Console.WriteLine(query["id"]);
Console.WriteLine(string.Join(", ", query.GetValues("tag") ?? []));
Text
7
red, blue

Do not split a query and assume every name occurs only once. Applications can give repeated parameters their own meaning, and decoding rules belong to the application consuming the query. OneContact’s task here is URL parsing and canonicalization, not interpreting another website’s search or checkout API. Credentials, path case and query parameters outside the documented removal list remain in the canonical form.

How do I normalize a URL in C#?

Use Canonical for the cleaned URL and Key for OneContact’s more aggressive comparison form. Those outputs serve different purposes. The key can collapse subdomains to a registrable domain, lowercase path letters and normalize default documents; the canonical URL preserves more of the address’s actual structure.

For a website field that users will navigate to, store the canonical URL rather than substituting its key. Keep a versioned comparison key separately if you need contact matching. A parser does not fetch the URL, resolve its hostname or establish that a destination is reachable. A successful parse answers a syntax-and-normalization question, not a network availability question.

All onecontact recipes