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.
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.
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.
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.
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
fileorftp. - Trusting any host for redirect or fetch operations.
- Using exception-based parsing in a normal validation path.
Summary
- Use
Uri.TryCreateto 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.

