Anatomy of a URL

HTTP & the web · Essentials · 8 min

Every request starts from a URL, and many bugs come from building or encoding one incorrectly.

A URL names a resource and says how to reach it. Take https://api.example.com:8443/v1/users?sort=name&page=2#top:

  • scheme https: the protocol. http and https are the web's; the scheme also implies a default port (80 for http, 443 for https).
  • host api.example.com: a domain name (or an IP address) that DNS will resolve.
  • port 8443: optional; omitted when it's the default.
  • path /v1/users: which resource on that server, hierarchical like folders.
  • query ?sort=name&page=2: key/value parameters, separated by &, typically for filtering, searching and pagination.
  • fragment #top: a position inside the document. It's handled by the browser and never sent to the server.

Scheme plus host plus port make the origin (https://api.example.com:8443), the unit the browser's security model is built on.

URLs may only contain a limited set of ASCII characters, so everything else is percent-encoded: a space becomes %20, & inside a value becomes %26, and é becomes its UTF-8 bytes %C3%A9. In HTML form data and query strings a space is often written + instead. Never build query strings by concatenating raw user input; use a URL library (URL and URLSearchParams in JavaScript, urllib.parse in Python) that encodes correctly.

Relative URLs like ../img/a.png or /login are resolved against the current page's URL.

Example

const u = new URL("https://api.example.com:8443/v1/users?sort=name&page=2#top");
console.log(u.protocol, u.hostname, u.port);  // https: api.example.com 8443
console.log(u.pathname, u.search, u.hash);    // /v1/users ?sort=name&page=2 #top
console.log(u.origin);                        // https://api.example.com:8443
console.log(u.searchParams.get("page"));      // 2

// Build query strings safely: values get encoded
const q = new URL("https://example.com/search");
q.searchParams.set("q", "fish & chips");
q.searchParams.set("city", "Zürich");
console.log(q.href);
// https://example.com/search?q=fish+%26+chips&city=Z%C3%BCrich

console.log(new URL("../img/a.png", "https://site.com/blog/post/").href);
// https://site.com/blog/img/a.png

Remember

  • scheme://host:port/path?query#fragment
  • Origin = scheme + host + port
  • The fragment is never sent to the server
  • Use a URL library to encode query values

Watch out for

  • Concatenating user input into a query string, so a & or # in the value breaks the URL.

Check yourself

  1. Which part of https://shop.com/cart?id=5#summary is NOT sent to the server?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: developer.mozilla.org/en-US/docs/Learn_web_development/Howto/Web_mechanics/What_is_a_URL

Builds on

Nothing: this is a foundation.

Unlocks