All posts
4 min read

Anatomy of a URL: What Every Part of a Web Address Means

https://app.example.com:8080/orders/42?sort=new#details has seven parts, and each one matters when you build an app. The scheme, subdomain, domain, port, path, query string, and fragment, explained — plus URL encoding and why some characters turn into %20.

getting startedno-codedomainsbeginner

You use URLs all day without thinking about them. Once you build an app, you start designing them — routes, links, API endpoints, redirect addresses for login — and every part has a job. Here's a full one, taken apart:

https://app.example.com:8080/orders/42?sort=new&page=2#details
└─┬─┘   └┬┘ └────┬────┘ └┬─┘└───┬───┘ └──────┬──────┘ └──┬──┘
scheme  sub   domain    port   path       query       fragment

Scheme: https://

The scheme (or protocol) says how to talk to the server. On the web it's https (encrypted) or http (not). (What Is HTTPS?.)

Other schemes exist — mailto: opens an email, tel: dials a number, and apps can register their own, like slack://.

Host: app.example.com

The host is the server's name. It has parts, read right to left:

  • .com — the top-level domain (TLD).
  • example — the name you registered. Together, example.com is your domain.
  • app — a subdomain, which you create for free. www is also just a subdomain.

DNS turns the host into an IP address. (DNS Records Explained.)

Port: :8080

The port says which program on that server to talk to. You usually don't see it, because browsers assume 443 for https and 80 for http. You'll see ports constantly during development: localhost:3000, localhost:5173. (What Is an IP Address and a Port?.)

Path: /orders/42

The path says which thing on the server you want. It looks like folders, and on old-fashioned sites it really was folders and files. In modern apps, the path is matched against routes in your code:

/orders        → the list of orders
/orders/42     → order number 42
/orders/42/edit → the edit page for order 42

The 42 here is a path parameter — a variable part of the route. Your code reads it to decide which order to show.

(And — important — your code must check that the logged-in user is allowed to see order 42. Changing the number in the address bar is the first thing a curious user tries. Authentication vs Authorization.)

Query string: ?sort=new&page=2

After the ? come query parameters: key=value pairs separated by &. They're for options that modify what you're looking at — sorting, filters, search terms, page numbers:

/search?q=blue+shoes&size=9&page=2

A useful rule when designing URLs: the path says what the thing is, the query says how to show it. /products/123 identifies a product; ?color=red picks a variant of the view.

Query strings are visible in browser history, server logs, and analytics. Never put passwords, tokens, or personal data in them.

Fragment: #details

The fragment (or hash) points to a spot within the page — usually an element with that id, which the browser scrolls to. Two things make fragments special:

  • They're never sent to the server. The browser keeps them to itself.
  • Some older single-page apps used them for routing (/#/settings), which you'll still occasionally see.

URL encoding: why spaces become %20

URLs can only contain a limited set of characters. Anything else — spaces, accented letters, emoji, and characters with special meaning like &, ?, #, / — gets percent-encoded: replaced with % and a code.

Character Encoded
space %20 (or + in query strings)
& %26
/ %2F
é %C3%A9

This matters when you build URLs in code. If a user searches for salt & pepper and you glue it straight into a URL, the & splits your parameter in two. Use your language's built-in tools instead of string concatenation:

const url = new URL("https://example.com/search")
url.searchParams.set("q", "salt & pepper")
url.toString() // https://example.com/search?q=salt+%26+pepper

Absolute and relative URLs

In links within your own app, you can leave parts out:

  • https://example.com/about — absolute: everything spelled out.
  • /about — root-relative: same scheme and host as the current page.
  • about — relative to the current path. Easy to get wrong; prefer root-relative.

Root-relative links keep working when you move from localhost to your real domain, which is one less thing to break at launch. (Why Does My App Work Locally but Not in Production?.)

The summary

Part Example Job
Scheme https How to connect
Host app.example.com Which server
Port 8080 Which program on it (usually hidden)
Path /orders/42 Which resource
Query ?sort=new Options for that resource
Fragment #details A spot on the page (browser only)

EasySpawn gives every app a real HTTPS address from the first deploy and lets you add subdomains on your own domain, so the URLs you test with are the ones your users will see. See how it works or join the waitlist.

Related: What Is an API? · HTTP Status Codes Explained · Designing a REST API

Keep reading