URI validation
string validation
programming
web development
coding tips

How to check that a uri string is valid

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Checking whether a URI string is valid sounds straightforward, but "valid" can mean several different things. A string may be syntactically valid as a URI and still be unusable for your application because the scheme is wrong, the host is missing, or the destination violates a security policy. In .NET, the practical approach is to parse first and then apply rules that match the real use case.

Start with Uri.TryCreate

The safest first step is Uri.TryCreate. It answers the syntax question without turning ordinary bad input into exceptions.

csharp
1using System;
2
3public class Program
4{
5    public static void Main()
6    {
7        string input = "https://example.com/products?id=42";
8
9        bool ok = Uri.TryCreate(input, UriKind.Absolute, out Uri? uri);
10
11        Console.WriteLine(ok);
12        Console.WriteLine(uri?.Host);
13    }
14}

If this returns true, the runtime was able to interpret the string as a URI. That still does not mean the application should accept it.

That distinction is the core of practical URI validation: parseability is only the first gate.

Decide Whether Relative URIs Are Allowed

One common bug is mixing up relative URI references and absolute URLs. A value like /images/logo.png can be a valid relative URI, but it is not a full web address.

csharp
1using System;
2
3public class Program
4{
5    public static void Main()
6    {
7        string input = "/images/logo.png";
8
9        Console.WriteLine(Uri.TryCreate(input, UriKind.Relative, out _));
10        Console.WriteLine(Uri.TryCreate(input, UriKind.Absolute, out _));
11    }
12}

If the field is meant to store external links, callbacks, or redirect targets, UriKind.Absolute is usually the right requirement. If the field is meant to store an internal path fragment, relative URIs may be acceptable. The validation rule should come from the contract, not from guesswork.

Add Scheme and Host Rules

After parsing succeeds, apply the business rules that matter. For a normal web link, you often want an absolute URI with http or https and a non-empty host.

csharp
1using System;
2
3public static class UriValidator
4{
5    public static bool IsValidHttpUri(string input)
6    {
7        if (!Uri.TryCreate(input, UriKind.Absolute, out var uri))
8            return false;
9
10        if (uri.Scheme != Uri.UriSchemeHttp && uri.Scheme != Uri.UriSchemeHttps)
11            return false;
12
13        return !string.IsNullOrWhiteSpace(uri.Host);
14    }
15}
16
17public class Program
18{
19    public static void Main()
20    {
21        Console.WriteLine(UriValidator.IsValidHttpUri("https://example.com"));
22        Console.WriteLine(UriValidator.IsValidHttpUri("ftp://example.com"));
23        Console.WriteLine(UriValidator.IsValidHttpUri("not a uri"));
24    }
25}

This gives you a much more useful definition of valid than syntax alone.

Separate Validity from Trust

A URI can be well formed and still be unsafe. That matters for redirect parameters, file download URLs, webhook endpoints, and any feature that triggers an outbound request. In those cases, validation must go beyond parsing.

Typical policy checks include:

  • Allowing only specific schemes such as https.
  • Rejecting embedded credentials in the authority section.
  • Restricting hosts to an allowlist.
  • Blocking loopback or private-network destinations for server-side fetches.
  • Enforcing maximum length limits for storage and logging.

Those are application rules, not URI grammar rules, but they are often the reason the validator exists in the first place.

Validate for the Actual Scenario

Consider redirect validation. If the application accepts a returnUrl, parseability is not enough. You probably want the destination to stay inside a trusted domain and require HTTPS.

csharp
1using System;
2
3public static class RedirectValidator
4{
5    public static bool IsAllowedRedirect(string input)
6    {
7        if (!Uri.TryCreate(input, UriKind.Absolute, out var uri))
8            return false;
9
10        if (uri.Scheme != Uri.UriSchemeHttps)
11            return false;
12
13        return uri.Host.Equals("example.com", StringComparison.OrdinalIgnoreCase) ||
14               uri.Host.EndsWith(".example.com", StringComparison.OrdinalIgnoreCase);
15    }
16}

That function is intentionally stricter than a generic URI parser because the risk is different.

Prefer TryCreate Over Exception-Driven Parsing

new Uri(input) is fine when the input is already trusted and parse failure would represent a real bug. For user input and external data, invalid values are normal, so TryCreate produces cleaner control flow and avoids noisy logs.

It also keeps validation code cheap and predictable under load, which matters in APIs and batch import jobs where invalid input is expected rather than exceptional.

Common Pitfalls

  • Treating parse success as complete application validation.
  • Allowing relative URIs when the application really requires absolute URLs.
  • Forgetting to restrict schemes and unintentionally accepting file or ftp.
  • Trusting any host for redirect or fetch operations.
  • Using exception-based parsing in a normal validation path.

Summary

  • Use Uri.TryCreate to answer the syntax question safely.
  • Decide explicitly whether the input may be relative or must be absolute.
  • Add scheme, host, and security rules after parsing succeeds.
  • Treat redirect and fetch targets as trust decisions, not just format checks.
  • Define "valid" in terms of the application contract, not only URI grammar.

Course illustration
Course illustration

All Rights Reserved.