URLs, Piece by Piece

Table of Contents

  1. A URL Is an Address with Parts
  2. The Scheme
  3. The Host
  4. The Port
  5. The Path
  6. The Query String
  7. The Fragment
  8. Spaces and Special Characters
  9. Absolute and Relative Links
  10. Try It Yourself

1. A URL Is an Address with Parts

A URL (Uniform Resource Locator) tells a client where a resource is and how to get it. It looks like one long string, but it's really several pieces glued together with punctuation:

https://shop.example.com:443/products/shoes?color=red&size=42#reviews
└─┬─┘   └──────┬───────┘ └┬┘└──────┬──────┘ └───────┬───────┘ └──┬──┘
scheme       host       port     path             query      fragment

Every piece answers a different question:

PartQuestion it answersExample
SchemeHow do I talk to the server?https
HostWhich server?shop.example.com
PortWhich program on that server?443
PathWhich resource on that server?/products/shoes
QueryAny extra options?color=red&size=42
FragmentWhich part of the page?reviews

Most URLs you see leave some of these out. Let's go through them one at a time.

2. The Scheme

The scheme comes first, followed by ://. It tells the client which protocol — which set of rules — to use.

  • https — HTTP, encrypted. Almost every site today.
  • http — HTTP, not encrypted. Fine for localhost while you develop; a bad idea anywhere else (chapter 4 explains why).

You'll see other schemes too: mailto: opens your email app (this site's contact page uses one), tel: dials a phone number, file:// opens a file on your own computer, and ws:///wss:// are for WebSockets.

When you type example.com without a scheme, the browser fills one in for you. Modern browsers try https:// first.

3. The Host

The host says which server to contact. It's usually a domain name, read from right to left, from most general to most specific:

       shop . example . com
        │       │       └── top-level domain (TLD)
        │       └────────── the domain someone registered
        └────────────────── a subdomain they created
  • Top-level domain (TLD): .com, .org, .dev, or a country code like .kh for Cambodia.
  • Domain: example.com — the name someone rents from a registrar, usually yearly.
  • Subdomain: shop, www, api, docs — anything to the left. The owner of example.com can create as many as they like, for free.

Your GitHub Pages address, dara-sok.github.io, is a subdomain: GitHub owns github.io and gives every user their own subdomain.

The host can also be an IP address directly, like http://192.168.1.1 for many home routers, or the special name localhost, which always means "this computer". Chapter 3 shows how names turn into numbers.

Domain names are not case-sensitive: EXAMPLE.com and example.com are the same.

4. The Port

One server computer can run many server programs at once — a website, a database, an SSH server. The port is a number from 0 to 65535 that says which program on that computer you want. Think of the IP address as a building and the port as the apartment number.

You almost never see ports in URLs, because each scheme has a default:

SchemeDefault port
http80
https443

So https://example.com really means https://example.com:443. You only write the port when it's not the default — which is why you've seen URLs like http://localhost:3000 in the NestJS and Docker tutorials. Development servers use ports like 3000, 5173, or 8080 so they don't clash with each other.

5. The Path

The path starts at the first / after the host and says which resource you want on that server:

https://dara-sok.github.io/my-site/about.html
                         └────────┬────────┘
                                path

On a simple static site like yours, the path maps straight onto folders and files, exactly like the file paths from Command Line Basics: /my-site/about.html is the file about.html inside the my-site folder on GitHub's server.

When the path ends in a folder — /my-site/ — the server looks for a default file, almost always index.html. That's why your home page had that name.

On a web app, the path doesn't have to match any file. A NestJS server might answer /users/42 by looking up user 42 in a database. The path is just a string; it's up to the server what it means.

Unlike the host, paths are usually case-sensitive: /About.html and /about.html can be different files.

6. The Query String

After a ? comes the query string: extra options, as key=value pairs separated by &.

https://www.google.com/search?q=phnom+penh&hl=km
                              └─────┬────────┘
                         q = "phnom penh", hl = "km"

Queries are used for things like search terms, filters, sorting, and page numbers: ?page=2, ?sort=price, ?color=red&size=42. The server (or JavaScript in the page) reads them and changes what it returns.

Two warnings:

  • Query strings are visible: in the address bar, in browser history, and in server logs. Never put passwords or secrets in a URL.
  • The order usually doesn't matter to the server, but to a cache (chapter 9) ?a=1&b=2 and ?b=2&a=1 can look like different URLs.

7. The Fragment

The fragment is everything after #. It points to a part of the page, not a different page:

https://example.com/guide#installation

The browser scrolls to the element with id="installation". The table of contents at the top of this chapter works exactly this way — click one and watch the address bar.

The important detail: the fragment is never sent to the server. The browser keeps it to itself. The server receives a request for /guide and nothing more; the scrolling happens entirely in the browser.

8. Spaces and Special Characters

URLs can only contain a limited set of characters. Spaces, Khmer letters, and symbols like & or ? (when they're data, not punctuation) must be percent-encoded: replaced with % followed by the character's byte value in hex — the same bytes and hex numbers from the Bits and Bytes chapter of How Computers Work.

CharacterEncoded
space%20 (or + in a query string)
&%26
/%2F
ក (Khmer letter)%E1%9E%80

That last one is three bytes because Khmer letters take three bytes in UTF-8. Browsers usually show you the readable version in the address bar, but send the encoded one. Copy a URL with a space or Khmer text in it and paste it into a text editor to see the real thing.

In HTML, a link can be written two ways.

An absolute URL includes everything:

<a href="https://dara-sok.github.io/my-site/about.html">About</a>

A relative URL leaves parts out, and the browser fills them in from the page you're on. Suppose you're on https://dara-sok.github.io/my-site/index.html:

You writeThe browser goes to
about.htmlhttps://dara-sok.github.io/my-site/about.html
./about.htmlsame as above — . means "this folder"
../other/https://dara-sok.github.io/other/ — .. means "up one folder"
/about.htmlhttps://dara-sok.github.io/about.html — starts from the root of the host
#contactthe same page, scrolled to id="contact"

The . and .. work exactly like cd in the terminal. The one that trips people up is the leading /: on GitHub Pages, your site lives in /my-site/, so /about.html skips right past it and gives you a 404. That's why the Git series used plain relative links like about.html.

10. Try It Yourself

  1. Label the parts. Write out the scheme, host, port, path, query, and fragment for each of these. Some parts are missing — say which, and what the default would be.
    • https://www.youtube.com/watch?v=dQw4w9WgXcQ&t=42
    • http://localhost:3000/api/users/7
    • https://dara-sok.github.io/my-site/#contact
  2. Watch the fragment stay home. Open your site (or any page with headings) with DevTools → Network open. Click a table-of-contents link or add #something to the address. No new request appears — the browser just scrolls.
  3. See encoding. Search Google for something in Khmer. Copy the address bar and paste it into a text editor. Find the %E1%9E… bytes.
  4. Change the query. On a shopping or search site, change a value in the query string by hand — page=1 to page=2, for example — and press Enter. You just did what the site's "next" button does.

Next, we'll follow the host part of the URL and find out how the browser turns a name into an actual computer to talk to.

Buy Me a Coffee

Found this tutorial helpful? Consider buying me a coffee to support more free content!