URL Structure
A URL consists of several components, each serving a specific purpose:
https
Scheme
://
www.example.com
Host
:
8080
Port
/docs/guide
Path
?
page=1&sort=name
Query
#
section-2
Fragment
Component Details
| Component | Description | Required | Example |
|---|---|---|---|
| Scheme | Protocol or access method. Followed by : or :// |
Yes | https, mailto, tel |
| Authority | Combines userinfo, host, and port. Preceded by // |
Depends | user@host:port |
| Userinfo | Username and optional password (deprecated for passwords) | No | user:pass@ |
| Host | Domain name or IP address | Yes* | example.com, 192.168.1.1 |
| Port | Network port number. Preceded by : |
No | :8080, :443 |
| Path | Hierarchical path to resource. Starts with / |
No | /docs/guide/intro |
| Query | Key-value parameters. Preceded by ? |
No | ?id=123&sort=asc |
| Fragment | In-page anchor. Preceded by #. Not sent to server. |
No | #section-name |
* Host is required when authority is present
Scheme Patterns
Different schemes use different URL structures:
| Pattern | Structure | Examples |
|---|---|---|
| Hierarchical | scheme://authority/path?query#fragment |
https://example.com/page |
| Opaque | scheme:opaque-data |
mailto:user@example.com |
| Data | data:mediatype;base64,data |
data:text/plain;base64,SGVsbG8= |
| File | file:///path/to/file |
file:///home/user/doc.pdf |
Default Ports
When no port is specified, these defaults are used:
| Scheme | Default Port | Scheme | Default Port | Scheme | Default Port |
|---|---|---|---|---|---|
http |
80 | https |
443 | ftp |
21 |
ssh |
22 | ws |
80 | wss |
443 |
Reserved Characters
These characters have special meaning in URLs:
| Character | Purpose | Encoded Form |
|---|---|---|
| : | Scheme/port delimiter | %3A |
| / | Path segment delimiter | %2F |
| ? | Query string start | %3F |
| # | Fragment start | %23 |
| & | Query parameter separator | %26 |
| = | Key-value separator | %3D |
| @ | Userinfo delimiter | %40 |
| [ ] | IPv6 address brackets | %5B %5D |
Relative URL Resolution
How relative URLs resolve against base https://example.com/a/b/page.html:
| Relative URL | Type | Resolves To |
|---|---|---|
other.html |
Document-relative | https://example.com/a/b/other.html |
./other.html |
Same directory | https://example.com/a/b/other.html |
../other.html |
Parent directory | https://example.com/a/other.html |
../../other.html |
Two levels up | https://example.com/other.html |
/other.html |
Root-relative | https://example.com/other.html |
//other.com/page |
Protocol-relative | https://other.com/page |
?query=new |
Query replacement | https://example.com/a/b/page.html?query=new |
#section |
Fragment only | https://example.com/a/b/page.html#section |
Formal Grammar (RFC 3986)
URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
hier-part = "//" authority path-abempty
/ path-absolute
/ path-rootless
/ path-empty
authority = [ userinfo "@" ] host [ ":" port ]
userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
host = IP-literal / IPv4address / reg-name
port = *DIGIT
path-abempty = *( "/" segment )
path-absolute = "/" [ segment-nz *( "/" segment ) ]
segment = *pchar
segment-nz = 1*pchar
query = *( pchar / "/" / "?" )
fragment = *( pchar / "/" / "?" )
pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
pct-encoded = "%" HEXDIG HEXDIG
sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
/ "*" / "+" / "," / ";" / "="