Home / Browser security notes: how browsers parse URLs

Browser security notes: how browsers parse URLs

Updated Nov 2026•Web security

A URL looks simple, but it is a small grammar with several optional parts: a scheme, optional credentials, a host, an optional port, a path, a query and a fragment. The standards describe a strict form. Browsers, which must cope with whatever users and pages throw at them, accept a much wider one. Security problems appear in the space between the two, because a filter written for the strict grammar and a browser that follows the lenient one will disagree about what a given string means.

Scheme handling

The scheme names the protocol and is case-insensitive. Standard schemes such as http and https are registered, but browsers also support pseudo-protocols that run code or render data directly, with javascript the best-known. The grammar limits the characters allowed in a scheme, yet historically some browsers skipped certain control characters or null bytes inside it, so a string that a filter would not recognise as a script scheme could still be run as one. Any check that matches on the scheme must normalise first, or better, use an allow-list of safe schemes rather than a block-list of dangerous ones.

The missing double slash

The authority section normally follows two slashes. Browsers are forgiving when those are absent or written oddly: a scheme followed directly by a host is commonly treated as if the slashes were there. For pseudo-protocols, text after what looks like a host may be treated as a comment while a newline-encoded character starts real code. The defender lesson is that string prefix checks such as 'starts with http' or 'contains the expected host' are not parsing. Use the platform URL parser and compare the resulting host field.

Credentials in the authority

A URL can carry a username and password before an at-sign. Browsers accept nearly any character there, with only a few exceptions. This is the basis of look-alike links: a familiar domain name placed in the credentials position, with the real host after the at-sign. Users glance at the start and trust it. Applications that compare or display URLs should parse out the host, ignore the credentials, and in many cases refuse URLs that contain credentials at all.

Hosts, ports and alternative notations

Hosts can be names, IPv4 or IPv6 addresses. Because many programs hand parsing to system libraries, an IPv4 address may be written in decimal, hexadecimal, octal or with fewer than four parts, and all of them reach the same machine. Server-side request filters that block a loopback address by matching its dotted form are bypassed trivially. Resolve the address and check the result. Non-default ports can also point a browser at a service that is not web at all, so outbound fetch features should restrict ports as well as hosts.

Encoding and internationalised names

Percent-encoding lets any byte be written as a percent sign and two hexadecimal digits, so one host can have several spellings. Non-ASCII text is encoded as bytes first, usually UTF-8, then percent-encoded. For domain names, international characters are converted to an ASCII form beginning with the prefix xn--. Because many scripts contain letters that look identical to Latin ones, an attacker can register a name that reads as a trusted brand. Browsers apply display rules to expose such names, but applications should not assume they will be shown safely.

Defender takeaways

  • Parse once with a well-maintained library and make decisions on the parsed fields.
  • Normalise and decode before comparing, and compare after, not before, decoding.
  • Prefer allow-lists of schemes, hosts and ports.
  • Reject control characters, backslashes and embedded credentials where they have no legitimate use.
  • Test filters with odd forms of the same address, not just the polite one.

Key takeaways

  • Browsers accept more forms of URL than the standard allows, and filters must match browser behaviour.
  • Use a real URL parser and judge the parsed host, not substrings.
  • Allow-list schemes, hosts and ports instead of blocking known-bad ones.
  • Decode and normalise before comparison; test unusual spellings of IP addresses.
  • Treat credentials in URLs and look-alike internationalised names as spoofing risks.