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.
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.comis your domain.app— a subdomain, which you create for free.wwwis 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
What Is a Domain Name? (And How to Buy One Without Getting Caught Out)
A domain name is your app's address on the internet — and the one part of it you should truly own. What domains are, how to pick one, where to buy it, and the renewal-price and ownership traps that catch first-time buyers.
How to Get a Custom Email Address for Your Domain
[email protected] looks far more trustworthy than [email protected]. The options — Google Workspace, Microsoft 365, Zoho, Proton, Fastmail, and forwarding — how MX, SPF, DKIM, and DMARC records set it up, and how mailboxes differ from sending email from your app.