PythonMastery
Python programs · Useful programs · intermediate

URL validation in Python

Check whether a string is a web address starting with http:// or https://, first with a regular expression, then with urllib.parse.urlparse().

This program checks whether a string looks like a web address: http:// or https://, then a domain name with at least one dot, then an optional port and path.

The program

python
import re

URL_PATTERN = re.compile(r"https?://([A-Za-z0-9-]+\.)+[A-Za-z]{2,}(:\d{1,5})?(/\S*)?")


def is_valid_url(url):
    return URL_PATTERN.fullmatch(url) is not None


tests = [
    "https://www.example.com",
    "http://example.org/docs/page?id=7#top",
    "https://example.com:8080/api",
    "www.example.com",
    "ftp://example.com",
    "https://exa mple.com",
    "https://localhost:8000",
]
for url in tests:
    print(f"{url:40} {is_valid_url(url)}")
output
https://www.example.com                  True
http://example.org/docs/page?id=7#top    True
https://example.com:8080/api             True
www.example.com                          False
ftp://example.com                        False
https://exa mple.com                     False
https://localhost:8000                   False

How it works

Another way: urllib.parse

The standard library can split a URL into its parts. That is easier to read than a long regex, and you can then check each part:

python
from urllib.parse import urlparse

parts = urlparse("https://example.com:8080/docs/page?id=7#top")
print("scheme:  ", parts.scheme)
print("host:    ", parts.hostname)
print("port:    ", parts.port)
print("path:    ", parts.path)
print("query:   ", parts.query)
print("fragment:", parts.fragment)


def is_web_url(url):
    parts = urlparse(url)
    return parts.scheme in ("http", "https") and bool(parts.hostname) and " " not in url


print(is_web_url("https://www.example.com"), is_web_url("www.example.com"))
output
scheme:   https
host:     example.com
port:     8080
path:     /docs/page
query:    id=7
fragment: top
True False

urlparse() does not raise an error for a bad URL. It splits whatever you give it, so you still have to check that the parts you need are there.

Learn the idea: Regular Expressions, pip & the Standard Library: Batteries Included