# Hostname vs. Domain

> This topic assumes the Browser Request Lifecycle and CORS topics from this group — it fills in a precise vocabulary gap those topics lean on but don't formally define: what exactly counts as "the same site" for cookies and origin checks.

## 1. The Two Words People Use Interchangeably (and Shouldn't)

- **Hostname**: the exact name of one specific machine or service, e.g. `api.example.com`, `www.example.com`, `checkout.shop.example.com`. It's the literal string between `https://` and the next `/` or `:` in a URL.
- **Domain**: the *registrable* unit — the name someone actually bought from a registrar, e.g. `example.com`. A domain can host any number of distinct hostnames underneath it (`www.example.com`, `api.example.com`, `mail.example.com` are all different hostnames, all part of the same domain).

```
https://checkout.shop.example.com/cart
         └──────────┬──────────┘
                hostname

                      example.com
                      └────┬────┘
                        domain
```

Every hostname belongs to exactly one domain (by construction — it's built by prepending labels to the domain), but a domain can have unlimited hostnames built on top of it.

## 2. Why "example.com" Alone Isn't Enough — the Public Suffix Problem

Naively, "domain = strip subdomains down to two labels" (`a.b.example.com` -> `example.com`) breaks immediately for domains like `example.co.uk` or `example.github.io`. `.co.uk` and `.github.io` are themselves NOT things anyone can register a full domain under directly in the "example.com" sense — they're **public suffixes**: registries where unrelated third parties independently register names (anyone can get `<anything>.github.io`, just like anyone can get `<anything>.com`).

```
alice.github.io   <- Alice's independent site
bob.github.io     <- Bob's independent site, UNRELATED to Alice's
```

Treating `github.io` as "the domain" here would be wrong — `alice.github.io` and `bob.github.io` are, for security purposes, as unrelated as `alice.com` and `bob.com`. The actual registrable unit is one label deeper: `alice.github.io` and `bob.github.io` respectively.

Browsers resolve this with the **Public Suffix List (PSL)** — a maintained, crowd-sourced list of every known suffix under which the public can register names (`.com`, `.co.uk`, `.github.io`, thousands of entries). The registrable domain is then defined precisely as:

> **eTLD+1** ("effective TLD, plus one label"): take the longest matching public suffix from the PSL for a given hostname, then include exactly one more label to its left.

```
hostname:            checkout.shop.example.com
matching PSL suffix: com                          (eTLD)
eTLD+1 (the domain):          example.com
```

```
hostname:            alice.github.io
matching PSL suffix: github.io                    (eTLD — a multi-label public suffix)
eTLD+1 (the domain): alice.github.io
```

## 3. "Same-Site" Is Defined in Terms of eTLD+1, Not Hostname

This is the concrete payoff for the rest of this group's topics. When the CORS topic and the CSRF topic talk about "same-site" (as distinct from "same-origin"), they mean **same eTLD+1** — not same hostname:

```
https://app.example.com   and   https://api.example.com
  -> DIFFERENT hostnames, DIFFERENT origins, but SAME SITE (both eTLD+1 = example.com)

https://alice.github.io   and   https://bob.github.io
  -> DIFFERENT hostnames, and because github.io is a public suffix, DIFFERENT SITES too
     (eTLD+1 differs: alice.github.io vs bob.github.io)
```

`SameSite=Lax`/`Strict` cookies (CSRF topic, §4) are scoped by this same-site definition, not by hostname or full origin — which is precisely why a cookie set by `app.example.com` can be shared with `api.example.com` (same site) via an explicit `Domain=example.com` attribute, but two unrelated tenants both living under `*.github.io` can never accidentally share a `SameSite` cookie with each other, even if one tenant's page tries to set `Domain=github.io` (browsers reject setting a cookie's `Domain` to a public suffix outright, for exactly this reason).

![For https://app.shop.example.co.uk:443 the origin is scheme, host and port, the site is the registrable domain example.co.uk, and the hostname is the full name](diagrams/01-origin-site-hostname.svg)

## 4. Cookie Scoping: `Domain` Attribute Rides on This Too

When a server sets a cookie, the (optional) `Domain` attribute controls which hostnames receive it:

```http
Set-Cookie: session=abc123; Domain=example.com; Path=/
```

- **No `Domain` attribute at all**: the cookie is scoped to the exact hostname that set it (host-only cookie) — `app.example.com` sets it, only `app.example.com` gets it back, not `api.example.com`.
- **`Domain=example.com`**: the cookie is shared across `example.com` and every subdomain of it (`app.example.com`, `api.example.com`, `anything.example.com`) — because `example.com` is a legitimate registrable domain the site actually controls end-to-end.
- **Attempting `Domain=github.io`** (a public suffix): browsers refuse to set this. If they didn't, `alice.github.io` could set a cookie that `bob.github.io` — a completely unrelated party — would also receive, since both share that suffix. The PSL is exactly what lets the browser recognize and block this.

## 5. Origin Is Stricter Than Site — Don't Conflate the Two

It's worth being precise that "same-site" (this topic) and "same-origin" (the CORS topic's unit) are different, nested concepts:

```
same-origin  =>  same scheme + same hostname + same port   (strictest)
same-site    =>  same eTLD+1                                (looser — ignores
                                                               subdomain, scheme,
                                                               and port entirely)
```

`https://app.example.com` and `https://api.example.com` are same-site but NOT same-origin. `https://example.com` and `http://example.com` are same-site (identical eTLD+1) but NOT same-origin (different scheme). CORS decisions use same-origin; `SameSite` cookie behavior uses same-site — mixing the two up is a common source of confusion when debugging why a cookie is present but a CORS request still fails, or vice versa.

## Common Pitfalls

1. **Assuming "domain = strip to the last two labels."** Breaks for any domain under a multi-label public suffix (`.co.uk`, `.github.io`, `.com.au`, and thousands more) — always resolve against the actual Public Suffix List, never a fixed label count.
2. **Conflating "same-site" with "same-origin."** They answer different questions and are used by different mechanisms (`SameSite` cookies vs. CORS/SOP) — same-site is a strict superset of same-origin.
3. **Trying to set a cookie's `Domain` to a public suffix**, expecting it to "just work" across all hostnames under that suffix — browsers block this specifically because the PSL identifies it as unsafe (it would leak the cookie to unrelated third parties on the same suffix).
4. **Forgetting that a host-only cookie (no `Domain` attribute) does NOT get shared with subdomains** — a very common source of "why isn't my session cookie visible on `api.example.com` when it was set on `app.example.com`" bugs; the fix is an explicit `Domain=example.com`, not assuming it's automatic.
5. **Treating `www.example.com` and `example.com` as automatically interchangeable.** They're different hostnames on the same domain/site — a cookie or CORS rule scoped to one does not automatically apply to the other unless explicitly configured to.

## Quick Reference

```
hostname   = the exact machine/service name, e.g. api.example.com
domain     = the registrable unit, e.g. example.com (unlimited hostnames can sit under it)
eTLD+1     = "public suffix from the PSL, plus one label" — the precise definition of "domain"
same-site  = same eTLD+1 (ignores subdomain, scheme, port)
same-origin = same scheme + hostname + port (strict; used by CORS/SOP)

Cookie Domain attribute:
  (unset)            -> host-only, exact hostname that set it, no subdomain sharing
  Domain=example.com -> shared across example.com and ALL its subdomains
  Domain=<public suffix> -> browsers REFUSE (PSL prevents leaking across unrelated tenants)
```
