Skip to content

URL vs URI vs URN — Modern Web Anatomy (with SPA Context)

TL;DR: URI is the superset concept. URL (locator) and URN (name) are both kinds of URIs. A URL says where/how to fetch. A URN says what it is named inside a formal namespace (location-agnostic). Most day‑to‑day dev work is with URLs; URNs appear in niche namespaces (ISBN, RFC, UUID, package metadata, some XML/semantic vocabularies). Understanding the generic URI grammar unlocks consistent parsing, state encoding in SPAs, and cleaner routing.

Diagram illustrating comparison of URL, URI and URN components

1. The Core Hierarchy

text
URI
├── URL (Uniform Resource Locator)
└── URN (Uniform Resource Name)

Think: All squares are rectangles. A URL is a URI that contains (or implies) a network access mechanism (scheme + authority + optional path etc.). A URN is a URI that names a resource in a persistent, location‑independent namespace: urn:isbn:9780141036144.

TermStands forCore PurposeExample
URIUniform Resource IdentifierGeneric identifier string formhttps://example.com/docs?page=2#intro
URLLocator (a URI subtype)Locate & access resource (typically via protocol)https://api.example.dev/v1/users?id=42
URNName (a URI subtype)Persistent, location‑agnostic nameurn:ietf:rfc:7230

2. Generic URI Syntax (RFC 3986 Pattern)

text
<scheme>://<authority><path>?<query>#<fragment>

Only scheme is mandatory in a minimal absolute form; other pieces appear when meaningful. Authority may embed userinfo and port.

ComponentSubpartsSeparator(s)PurposeExample Values
scheme: (then often //)Defines interpretation & initial protocol ruleshttp, https, mailto, urn, blob, data, ws, wss
authorityuserinfo@ host : port// prefix; @, :Names network location & optional credentialsapi.example.com:8443, user:pass@host
userinfousername[:password]@ after credentialsLegacy/basic access (rare in public web)admin:secret@
hostdomain / IPv4 / [IPv6]Network address labelexample.com, 127.0.0.1, [2001:db8::1]
portdigits: after hostOverrides default port for scheme443, 3000
pathsegments separated by //Hierarchical resource location/v1/users/42
querykey=value pairs (URL-encoded)? then &Non-hierarchical parameters / filters / statepage=2&sort=desc
fragmentopaque interpreter-specific token#Client-side intra-resource reference or state anchor#section-3, #/?modal=login

Note: Some schemes omit certain pieces (e.g., mailto:, urn: have no authority; data: encodes media inline).

3. URL: Practical Anatomy

Using the Web API URL interface (MDN reference), once parsed you get ergonomic properties:

js
const u = new URL("https://user:pw@sub.example.dev:8443/reports/q1/summary?region=emea&sort=asc#section-2");
{
  protocol: 'https:', // includes ':'
  username: 'user',
  password: 'pw',
  host: 'sub.example.dev:8443',
  hostname: 'sub.example.dev',
  port: '8443',
  origin: 'https://sub.example.dev:8443',
  pathname: '/reports/q1/summary',
  search: '?region=emea&sort=asc',
  hash: '#section-2'
}

searchParams lets us treat the query as a map:

js
u.searchParams.get('region'); // 'emea'
u.searchParams.set('page', '2');

Frequent URL Misunderstandings

MythReality
"URL and URI are different things"A URL is one kind of URI.
"Fragment is sent to server"It is not (unless turned into part of path/query by client routing).
"Everything after ? is query param pairs"Some apps embed JSON or base64 — allowed, but readability trade-off.
"Ports must always be specified"Default ports (80, 443, etc.) are implied.
"Username/password are common"Largely discouraged; use headers/OAuth not user:pass@ in production.

4. URN: Pure Naming

A URN identifies by name only. Pattern is:

urn:<NID>:<NSS>

Where NID is namespace identifier (case-insensitive) and NSS is namespace-specific string, guaranteed unique within that namespace.

Examples:

NamespaceURN ExampleMeaning
ISBNurn:isbn:9780141036144Book by ISBN code
IETF RFCurn:ietf:rfc:7230HTTP/1.1 RFC 7230 specification
UUIDurn:uuid:123e4567-e89b-12d3-a456-426614174000Specific universally unique identifier
OASISurn:oasis:names:specification:docbook:dtd:xml:4.5DocBook DTD name

No authority, no path/query/fragment in the typical web sense. Resolution (turning the name into a retrievable representation) is external and namespace-dependent.

5. Relative References & Base URLs

Not every identifier you write is absolute. In HTML & modules:

html
<a href="../images/logo.svg">Logo</a>
<script type="module" src="./main.js"></script>

The browser synthesises the absolute URL using the document base (<base href> or the document location). The URL() constructor mirrors this when you pass a second argument.

6. How SPAs Use The Pieces

Modern Single Page Applications repurpose normal URL parts for client state:

PartSPA Usage PatternProsCautions
PathLogical route hierarchy (/dashboard/accounts/42)Bookmarkable, SEO, shareableDeep nesting can bloat bundle splits
QueryFilters, pagination, sort, feature flags (?page=2&sort=price)Reflects user intent; easily diffableOverloading can create opaque long strings
Fragment (hash)Legacy routers (#/inbox/5), scroll targets, ephemeral UI (#modal=signup)Doesn't hit server; fast local transitionsNot indexed the same way; can complicate analytics
SubdomainMulti-tenant or environment scoping (eu.app.example.com)CDN separation; tenancy isolationTLS & wildcard cert complexity
PortLocal dev (:5173, :3000)Parallel micro-frontend devAvoid leaking non-standard ports in prod links
SchemeSecurity + protocol upgrade (httphttps, wswss)Integrity & modern APIs require httpsMixed content/CDN edge cases
Query (encoded state)Persisting UI layout (layout=grid&cols=4)Restores state on refreshKeep size < ~2KB for shareability
Fragment (in-app router)Offline-first static hosting hacksWorks with simple static hostsPrefer History API now

Query vs Fragment for State

Use CasePrefer QueryPrefer Fragment
Affects server-side caching / SSR result
Purely client visual mode toggle
Should be shareable & crawlable(Maybe)
Sensitive to ordering & diffing for analytics
Must not trigger server 404 on static host

History API Harmony

Modern routers use pushState to keep semantic paths without reloading. Under the hood they still form proper URLs so deep links function with server rewrites (e.g., catch-all to index.html).

7. Designing Clean API & App URLs

Principles:

  1. Stability over cleverness — Changing /v1/users to /u saves 3 chars and burns muscle memory.
  2. Hierarchy mirrors resource nesting/accounts/42/transactions/2024 reads like a breadcrumb.
  3. Short plural nouns for collections; singular for specific resource (/users vs /users/42).
  4. Consistent separators — prefer hyphens over underscores in path segments.
  5. Avoid encoding entire state blobs — Resist base64 mega-query strings; consider server sessions or localStorage for large, non-shareable view state.
  6. Version in path or subdomain, not query/v2/ or v2.api.example.com.
  7. Lowercase paths — Case-insensitive mental model; avoid 404 surprises on case-sensitive servers.
  8. Human-first, machine-also — Slugs: /posts/how-url-parsing-works > /posts/9f2a01 (maybe both: ID + slug).

8. Validation & Parsing Strategies

Native URL

new URL() throws on invalid absolute URLs. For relative parsing supply base. Use URL.canParse() (newer) for preflight.

Defensive Steps

  • Normalise trailing slashes.
  • Percent-encode unsafe characters (path vs query rules differ).
  • Whitelist acceptable schemes (https, wss, maybe blob, data if controlled).
  • Reject embedded credentials in publicly shared URLs.
  • Limit query key count to prevent abuse.

Example Utility (Lightweight)

js
export function parseAppUrl(str, base = window.location.origin) {
  if (!URL.canParse(str, base)) throw new Error('Invalid URL');
  const u = new URL(str, base);
  return {
    origin: u.origin,
    path: u.pathname.replace(/\/+$/, ''),
    params: Object.fromEntries(u.searchParams.entries()),
    fragment: u.hash.startsWith('#') ? u.hash.slice(1) : u.hash
  };
}

9. Encoding Nuggets

LayerExampleNotes
Percent-encoding (path)space → %20Avoid + (query forms may treat differently)
Query param encodingname=Jalal%20al-DinUse URLSearchParams to avoid manual mistakes
Reserved chars:/?#[]@!$&'()*+,;=Roles vary by component — escape when literal
International domainsmünich.examplexn--mnich-kva.examplePunycode via toASCII (WHATWG URL)
Fragment encoding#section 2#section%202Browser may auto-encode when setting hash

10. URNs in Practice Today

While rarer in frontend application code, URNs surface in:

  • Metadata (e.g., EPUB manifest using urn:isbn:)
  • Standards referencing other specs (RFC refs)
  • Namespace declarations (XML Schema, DocBook, OASIS)
  • UUID-based names where persistence matters independent of host servers

If you expose URNs in an API, treat them as opaque strings; clients shouldn’t parse semantic structure beyond pattern validation.

11. Putting It Together — Example Dissection

text
https://media.example.com:8443/assets/img/banner.png?theme=dark&v=5#hero
└─ scheme: https
   └─ authority: media.example.com:8443
      ├─ host: media.example.com
      └─ port: 8443
└─ path: /assets/img/banner.png
└─ query: theme=dark&v=5
   ├─ theme = dark
   └─ v = 5
└─ fragment: hero (client scroll target or state)

URN counterpart (naming same conceptual image in a registry):

text
urn:example:asset:img:banner:5

12. Quick Decision Cheatsheet

NeedUseWhy
Load a web resourceURLMust locate & fetch
Provide persistent name across hostsURNLocation can change
Link within your SPA & preserve filtersURL (query)Share/reload state
Link to in-page sectionURL (fragment)Scroll / highlight
Name a spec / book / RFCURNStandards ecosystems

13. Common Pitfalls & Anti-Patterns

PitfallBetter Approach
Packing entire view model JSON into queryStore large ephemeral state locally; keep shareable keys only
Using fragment for SEO-relevant content (#!)Use real paths + SSR / prerender
Mixed-case path segmentsNormalise to lowercase slugs
Credentials in URLUse headers / OAuth flows
Unbounded query parameters from UI filtersCap keys & paginate
Relying on implicit base without specifying <base> in complex docsAdd <base> or use absolute paths

14. References & Attribution

  1. MDN Web Docs — URL interface (parsed property behaviors, constructor & searchParams) (paraphrased under CC BY-SA 2.5/3.0 +).
  2. MDN Web Docs — URIs overview (generic structure & components) (paraphrased).
  3. MDN Web Docs — URN scheme (syntax & examples) (paraphrased).
  4. RFC 3986 (generic URI syntax) — authoritative grammar.
  5. Personal implementation & SPA routing experience.

All MDN-derived material paraphrased; consult original pages for verbatim definitions.

Random thoughts on Tech