An absolute URL carries everything: scheme, host, path, and the rest. A relative URL leaves parts out and expects them to be filled in from a base URL, usually the address of the page it appears on. This is what lets a site link to about.html without repeating its own domain everywhere.
The kinds of relative reference
How much gets filled in depends on the shape of the reference:
- Absolute-path (
/help/index.html): keeps the base's scheme and host, replaces the whole path. The leading slash means "from the root of the site." - Relative-path (
page.html,./page.html,../page.html): resolved relative to the directory of the current page../means the current directory, and each../climbs one level up before the rest of the path is applied. - Scheme-relative (
//cdn.example.com/lib.js): keeps only the base's scheme and takes a new host. On an https page it loads over https; on http, over http. - Query-only (
?page=2) and fragment-only (#section): keep everything and change only the query or the fragment.
Why it matters
The resolution rules (defined in 3986) are exact, which is good, because small mistakes produce broken links: a missing leading slash makes a link relative to the wrong directory, and an extra ../ climbs above where you meant. A page can also set an explicit base with a <base> tag, which quietly changes how every relative link on the page resolves, a classic source of "why is this link pointing there."
There is a security angle too. Because ../ walks up the path, and because scheme-relative and path-relative references behave differently, a URL that is built by pasting user input into a path can sometimes be steered somewhere unintended. When a URL is assembled from parts rather than written whole, it is worth resolving it fully to see where it actually lands.
The base is the part nobody checks
Resolving a relative URL needs a base, and the base is often not what the code believes it is. A <base> element in the document, a redirect that changed the effective location, or a proxy that rewrote the path can all move it — and the same relative reference then resolves somewhere else entirely.
This is why relative URLs are a recurring source of security surprise rather than merely a convenience. A reference that points inside your application when resolved against the intended base can point outside it when resolved against a base an attacker influenced.
Resolve explicitly against a base you control, and treat any resolution that crosses an origin as a decision rather than a detail — because the parser will perform it silently and correctly, and correctness is not the property at issue.