384

There are the Uri.IsWellFormedUriString and Uri.TryCreate methods, but they seem to return true for file paths, etc.

How do I check whether a string is a valid (not necessarily active) HTTP URL for input validation purposes?

1

12 Answers 12

629

Try this to validate HTTP URLs (uriName is the URI you want to test):

Uri uriResult;
bool result = Uri.TryCreate(uriName, UriKind.Absolute, out uriResult) 
    && uriResult.Scheme == Uri.UriSchemeHttp;

Or, if you want to accept both HTTP and HTTPS URLs as valid (per J0e3gan's comment):

Uri uriResult;
bool result = Uri.TryCreate(uriName, UriKind.Absolute, out uriResult) 
    && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps);
Sign up to request clarification or add additional context in comments.

19 Comments

Should this read uriResult.Scheme instead of uriName.Scheme? I'm using the overload to TryCreate that takes String instead of Uri as it's first parameter.
You may want to add more conditions to the uriResult.Scheme == ... Specifically https. It depends on what you need this for, but this small change was all I needed for it to work perfectly for me.
To be clear per @Fiarr's comment, the "small change" needed to account for HTTPS in addition to HTTP URLs is: bool result = Uri.TryCreate(uriName, UriKind.Absolute, out uriResult) && uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps;
@KailashP is right - I don't think I like this code without an extra check: && uriResult != null!
Looks like this technique fails 22 out of 75 tests dotnetfiddle.net/XduN3A
|
206
+350

This method works fine both in http and https. Just one line :)

if (Uri.IsWellFormedUriString("https://www.google.com", UriKind.Absolute))

MSDN: IsWellFormedUriString

6 Comments

This will return true for non-HTTP URIs (i.e. any other scheme such as file:// or ldap://. This solution should be coupled with a check against the scheme - e.g. if (uri.Scheme != Uri.UriSchemeHttp && uri.Scheme != Uri.UriSchemeHttps) ...
Is this RFC3986 compliant?
@Squiggle That's exactly what I want it to check, everything since I'm making a Downloader. So, this answer is the best method for me.
Problem is that IsWellFormedUriString renders spaces at the end as valid part of an URL. And no it don't thinks they are %20s, since adding a valid symbol after the spaces results in invalid URL: "a" - valid "a " - valid ?! "a a" - invalid ?!?
CAUTION: This will return true for url like javascript:alert("xss")
|
43

Try that:

bool IsValidURL(string URL)
{
    string Pattern = @"^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+$";
    Regex Rgx = new Regex(Pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase);
    return Rgx.IsMatch(URL);
}

It will accept URL like that:

  • http(s)://www.example.com
  • http(s)://stackoverflow.example.com
  • http(s)://www.example.com/page
  • http(s)://www.example.com/page?id=1&product=2
  • http(s)://www.example.com/page#start
  • http(s)://www.example.com:8080
  • http(s)://127.0.0.1
  • 127.0.0.1
  • www.example.com
  • example.com

2 Comments

Underrated comment right here.
http(s)://www.example.com/page << example of URL consist of METHOD PROTOCOL (http(s)://) + TYPE OF SERVER(www) + HOST NAME(example) + TOP LEVEL OF DOMAIN NAME (com) + PATH(page)
31
    public static bool CheckURLValid(this string source)
    {
        Uri uriResult;
        return Uri.TryCreate(source, UriKind.Absolute, out uriResult) && uriResult.Scheme == Uri.UriSchemeHttp;
    }

Usage:

string url = "htts://adasd.xc.";
if(url.CheckUrlValid())
{
  //valid process
}

UPDATE: (single line of code) Thanks @GoClimbColorado

public static bool CheckURLValid(this string source) => Uri.TryCreate(source, UriKind.Absolute, out Uri uriResult) && uriResult.Scheme == Uri.UriSchemeHttps;

Usage:

string url = "htts://adasd.xc.";
if(url.CheckUrlValid())
{
  //valid process
}

4 Comments

This does not appear to handle www urls. IE: www.google.com is shown as invalid.
@ZauberParacelsus "www.google.com" is invalid. URL mean should start with "http","ftp","file" etc. string should be "http:// www.google.com" without space
Today, the out parameter can make an improvement Uri.TryCreate(source, UriKind.Absolute, out Uri uriResult) && uriResult.Scheme == Uri.UriSchemeHttps
this doesnt work for random string like abc,tassdds etc..
22

All the answers here either allow URLs with other schemes (e.g., file://, ftp://) or reject human-readable URLs that don't start with http:// or https:// (e.g., www.google.com) which is not good when dealing with user inputs.

Here's how I do it:

public static bool ValidHttpURL(string s, out Uri resultURI)
{
    if (!Regex.IsMatch(s, @"^https?:\/\/", RegexOptions.IgnoreCase))
        s = "http://" + s;

    if (Uri.TryCreate(s, UriKind.Absolute, out resultURI))
        return (resultURI.Scheme == Uri.UriSchemeHttp || 
                resultURI.Scheme == Uri.UriSchemeHttps);

    return false;
}

Usage:

string[] inputs = new[] {
                          "https://www.google.com",
                          "http://www.google.com",
                          "www.google.com",
                          "google.com",
                          "javascript:alert('Hack me!')"
                        };
foreach (string s in inputs)
{
    Uri uriResult;
    bool result = ValidHttpURL(s, out uriResult);
    Console.WriteLine(result + "\t" + uriResult?.AbsoluteUri);
}

Output:

True    https://www.google.com/
True    http://www.google.com/
True    http://www.google.com/
True    http://google.com/
False

6 Comments

This lets through single words like "mooooooooo" but used in conjunction with Uri.IsWellFormedUriString could be good
@Epirocks That's a good point. The problem is that http://mooooooooo is, in fact, a valid Uri. Therefore, you can't check for Uri.IsWellFormedUriString after inserting "http://" and if you check for it before, anything that doesn't have a Scheme will be rejected. Maybe what can be done is we check for s.Contains('.') instead.
moooooo by itself doesn't look like a url as it has no protocol on it. What I did was take out your regex match call, and &&'ed it with IsWellFormedUriString as well.
@Epirocks Exactly! The problem is that if you use IsWellFormedUriString before adding the http://, you'll end up rejecting things like google.com and if you use it after adding the http://, it'll still return true for http://mooooooooo. That's why I suggested checking if the string contains a . instead.
that's fine for me anyway I don't want to accept a url without http or https on it. So I use IsWellFormedUriString first, then use your function without regex. bool bResult = (Uri.IsWellFormedUriString(s, UriKind.Absolute) && ValidHttpURL(s, out uriResult)); Thanks
|
7

After Uri.TryCreate you can check Uri.Scheme to see if it HTTP(s).

Comments

5

As an alternative approach to using a regex, this code uses Uri.TryCreate per the OP, but then also checks the result to ensure that its Scheme is one of http or https:

bool passed =
  Uri.TryCreate(url, UriKind.Absolute, out Uri uriResult)
    && (uriResult.Scheme == Uri.UriSchemeHttp
      || uriResult.Scheme == Uri.UriSchemeHttps);

1 Comment

Your answer came in lower quality posts. Please provide some explanation even though your code is self explanatory.
4

Problem: Valid URLs should include all of the following “prefixes”: https, http, www

  • Url must contain http:// or https://
  • Url may contain only one instance of www.
  • Url Host name type must be Dns
  • Url max length is 100

Solution:

public static bool IsValidUrl(string webSiteUrl)
{
   if (webSiteUrl.StartsWith("www."))
   {
       webSiteUrl = "http://" + webSiteUrl;
   }
        
   return Uri.TryCreate(webSiteUrl, UriKind.Absolute, out Uri uriResult)
            && (uriResult.Scheme == Uri.UriSchemeHttp
             || uriResult.Scheme == Uri.UriSchemeHttps) && uriResult.Host.Replace("www.", "").Split('.').Count() > 1 && uriResult.HostNameType == UriHostNameType.Dns && uriResult.Host.Length > uriResult.Host.LastIndexOf(".") + 1 && 100 >= webSiteUrl.Length;
}

Validated with Unit Tests

Positive Unit Test:

    [TestCase("http://www.example.com/")]
    [TestCase("https://www.example.com")]
    [TestCase("http://example.com")]
    [TestCase("https://example.com")]
    [TestCase("www.example.com")]
    public void IsValidUrlTest(string url)
    {
        bool result = UriHelper.IsValidUrl(url);

        Assert.AreEqual(result, true);
    }

Negative Unit Test:

    [TestCase("http.www.example.com")]
    [TestCase("http:www.example.com")]
    [TestCase("http:/www.example.com")]
    [TestCase("http://www.example.")]
    [TestCase("http://www.example..com")]
    [TestCase("https.www.example.com")]
    [TestCase("https:www.example.com")]
    [TestCase("https:/www.example.com")]
    [TestCase("http:/example.com")]
    [TestCase("https:/example.com")]
    public void IsInvalidUrlTest(string url)
    {
        bool result = UriHelper.IsValidUrl(url);

        Assert.AreEqual(result, false);
    }

Note: IsValidUrl method should not validate any relative url path like example.com

See:

Should I Use Relative or Absolute URLs?

Comments

3

This would return bool:

Uri.IsWellFormedUriString(a.GetAttribute("href"), UriKind.Absolute)

1 Comment

I think the OP specifically mentioned, he doesn't like Uri.IsWellFormedUriString as it gives true for file paths. Do you have a solution for this problem?
1
Uri uri = null;
if (!Uri.TryCreate(url, UriKind.Absolute, out uri) || null == uri)
    return false;
else
    return true;

Here url is the string you have to test.

1 Comment

null == url check is horribly reduntant
0

I've created this function to help me with URL validation, you can customize it as you like, note this is written in python3.10.6

def url_validator(url: str) -> bool:
    """
    use this func to filter out the urls to follow only valid urls
    :param: url
    :type: str
    :return: True if the passed url is valid otherwise return false
    :rtype: bool
    """

    #the following regex is copied from Django source code 
    # to validate a url using regax
    
    regex = re.compile(
        r"^(?:http|ftp)s?://"  # http:// or https://
        r"(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|"  # domain...
        r"localhost|"  # localhost...
        r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})"  # ...or ip
        r"(?::\d+)?"  # optional port
        r"(?:/?|[/?]\S+)$",
        re.IGNORECASE,
    )


    blocked_sites: list[str] = []

    for site in blocked_sites:
        if site in url or site == url:
            return False

    # if none of the above then ensure that the url is valid and then return True otherwise return False
    if re.match(regex, url):
        return True

    return False

Comments

0
def url_validator(url: str) -> bool:
    """
    use this func to filter out the urls to follow only valid urls
    :param: url
    :type: str
    :return: True if the passed url is valid otherwise return false
    :rtype: bool
    """

    #the following regex is copied from Django source code 
    # to validate a url using regax
    
    regex = re.compile(
        r"^(?:http|ftp)s?://"  # http:// or https://
        r"(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|"  # domain...
        r"localhost|"  # localhost...
        r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})"  # ...or ip
        r"(?::\d+)?"  # optional port
        r"(?:/?|[/?]\S+)$",
        re.IGNORECASE,
    )


    blocked_sites: list[str] = []

    for site in blocked_sites:
        if site in url or site == url:
            return False

    # if none of the above then ensure that the url is valid and then return True otherwise return False
    if re.match(regex, url):
        return True

    return False

1 Comment

Thank you for your interest in contributing to the Stack Overflow community. This question already has quite a few answers—including one that has been extensively validated by the community. Are you certain your approach hasn’t been given previously? If so, it would be useful to explain how your approach is different, under what circumstances your approach might be preferred, and/or why you think the previous answers aren’t sufficient. Can you kindly edit your answer to offer an explanation?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.