urlparse() Without a Scheme Misreads the Host (tested)
urlparse() assumes the string it's given follows URL syntax, starting with a scheme. We measured what happens to a plain string like example.com/path that's missing http:// or https:// — and the host doesn't end up where you'd expect.
1. Without a scheme, the whole string becomes the path
from urllib.parse import urlparse
r = urlparse("example.com/path")
print(r)
print("hostname:", r.hostname)
ParseResult(scheme='', netloc='', path='example.com/path', params='', query='', fragment='')
hostname: None
Measured: with no http:///https:// prefix, urlparse() has no way to recognize example.com as a host — the entire string lands in .path, and .netloc/.hostname come back empty/None. No exception is raised; the result just silently has no host.
2. A colon in the string can make it worse — a fake "scheme"
r2 = urlparse("example.com:8080/path")
print(r2)
print("hostname:", r2.hostname)
ParseResult(scheme='example.com', netloc='', path='8080/path', params='', query='', fragment='')
hostname: None
Measured: this is the sharper version of the bug. example.com:8080/path looks like host-plus-port, but the colon right after example.com matches URL scheme syntax (scheme:rest), so urlparse() reads example.com as the scheme, not the host, and 8080/path becomes the path. .hostname is still None — the actual host is nowhere in the parsed result.
3. Fix: always ensure a scheme is present before parsing
r3 = urlparse("https://example.com:8080/path")
print("hostname:", r3.hostname, "port:", r3.port)
hostname: example.com port: 8080
Measured: with an explicit scheme, .hostname and .port are both parsed correctly. The reliable fix confirmed here is to check for and prepend a scheme (e.g. default to https://) before calling urlparse() on any URL that might arrive without one — from user input, a config file, or a copy-pasted value — rather than trusting .netloc/.hostname to be populated from a schemeless string.
Frequently asked questions
Why is urlparse().hostname None for a URL like example.com/path?
We measured urlparse() requiring a scheme (like https://) to recognize the host portion of a string. Without one, the entire input is parsed as .path, leaving .netloc and .hostname empty.
Why did urlparse() treat part of my host as the scheme?
We confirmed that a schemeless string containing a colon, like example.com:8080/path, matches URL scheme syntax (word followed by a colon), so urlparse() reads the part before the colon as .scheme instead of as a hostname.
How do I safely parse a URL that might be missing http:// or https://?
We verified prepending a default scheme (e.g. checking for '://' and adding 'https://' if absent) before calling urlparse() reliably produces the correct .hostname and .port.
Does urlparse() raise an error for a URL without a scheme?
No — in our test it ran silently and returned a ParseResult with an empty or misassigned host field, with no indication anything was wrong with the input.
Is this urlparse() behavior different for host:port strings specifically?
Yes — we measured host:port/path strings being more likely to misparse than a bare host/path, because the colon before the port number matches scheme syntax and gets read as one.
Written with AI assistance. Measured on 2026-10-04 with Python 3.13.5's built-in urllib.parse module: ran urlparse() on a URL-like string missing its scheme, both with a bare host/path and with a host:port/path, comparing .netloc/.hostname to the same string with https:// added. PlainHeaders is our extension; Python's urllib.parse module is built in.