Loading content...
When you first encounter an IPv6 address like 2001:0db8:85a3:0000:0000:8a2e:0370:7334, it can seem intimidating compared to the familiar 192.168.1.1 of IPv4. The address is longer, uses hexadecimal, and features colons as delimiters.
But this complexity is necessary. IPv4's dotted-decimal notation represents 32 bits using four 8-bit decimal numbers (0-255 each). If we tried to extend this to 128 bits, we'd have sixteen numbers—unwieldy and error-prone.
Instead, IPv6 uses a more compact hexadecimal representation: eight groups of four hex digits, separated by colons. And importantly, IPv6 includes abbreviation rules that dramatically shorten most real-world addresses.
By the end of this page, you will understand the complete IPv6 address notation system—from full form to maximum abbreviation. You'll be able to read, write, and mentally parse any IPv6 address, and you'll understand how prefix notation works for network designations.
In its complete, unabbreviated form, an IPv6 address consists of:
Structure Breakdown
Full IPv6 Address:
2001:0db8:85a3:0000:0000:8a2e:0370:7334
| | | | | | | |
└────┴────┴────┴────┴────┴────┴────┴── 8 groups
Group 1: 2001 = 0010 0000 0000 0001 (16 bits)
Group 2: 0db8 = 0000 1101 1011 1000 (16 bits)
Group 3: 85a3 = 1000 0101 1010 0011 (16 bits)
Group 4: 0000 = 0000 0000 0000 0000 (16 bits)
Group 5: 0000 = 0000 0000 0000 0000 (16 bits)
Group 6: 8a2e = 1000 1010 0010 1110 (16 bits)
Group 7: 0370 = 0000 0011 0111 0000 (16 bits)
Group 8: 7334 = 0111 0011 0011 0100 (16 bits)
└── Total: 128 bits
| Aspect | IPv4 | IPv6 |
|---|---|---|
| Base | Decimal (0-9) | Hexadecimal (0-9, a-f) |
| Delimiter | Period (.) | Colon (:) |
| Groups | 4 octets | 8 hextets |
| Bits per group | 8 bits (0-255) | 16 bits (0000-ffff) |
| Total bits | 32 | 128 |
| Characters (max) | 15 (e.g., 255.255.255.255) | 39 (e.g., full form) |
| Case sensitivity | N/A | Case insensitive (a=A) |
Hexadecimal Review
Since IPv6 uses hexadecimal, let's ensure this is clear:
Hex: 0 1 2 3 4 5 6 7 8 9 a b c d e f
Decimal: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Binary: 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
Each hex digit represents exactly 4 bits. This makes binary-to-hex conversion straightforward—far easier than decimal conversion.
Why Hexadecimal?
2001:DB8 and 2001:db8 are equivalentWhile uppercase and lowercase are interchangeable, RFC 5952 recommends lowercase for consistency. Most modern systems output lowercase by default. When documenting or configuring, choose one case and stick with it to avoid confusion.
Each 16-bit group (hextet) in an IPv6 address can represent values from 0000 to ffff (0 to 65535 in decimal). Understanding how to read these groups is essential.
Value Range Examples
0000 = 0 (minimum value)
0001 = 1
000f = 15
0010 = 16
00ff = 255
0100 = 256
0fff = 4095
1000 = 4096
ffff = 65535 (maximum value)
Common Patterns You'll Encounter
| Pattern | Meaning | Example Address |
|---|---|---|
| 2001 | Global unicast documentation prefix | 2001:db8::1 |
| 2607 | Common North American allocation | 2607:f8b0::1 (Google) |
| 2a00-2a07 | European allocations | 2a00:1450::1 (Google EU) |
| fe80 | Link-local prefix | fe80::1 |
| fd00 | Unique local (private) prefix | fd00::1 |
| ff02 | Link-local multicast | ff02::1 (all-nodes) |
| 0000 | Zero group (often abbreviated) | 2001:db8::1 |
| ffff | All ones (appears in special addresses) | ::ffff:192.0.2.1 |
Converting Between Hex and Decimal
While you rarely need to convert IPv6 groups to decimal, understanding the process is valuable:
Hextet: 8a2e
Position values:
8 a 2 e
× × × ×
4096 256 16 1
Calculation:
(8 × 4096) + (10 × 256) + (2 × 16) + (14 × 1)
= 32768 + 2560 + 32 + 14
= 35374
8a2e in hexadecimal = 35374 in decimal
Practical Tip: For quick mental math, memorize that:
1000 hex = 4096 decimal0100 hex = 256 decimal0010 hex = 16 decimalThese round numbers make estimation easy.
With practice, you'll instantly recognize address types by their first hextet: 2xxx/3xxx = global unicast, fe80 = link-local, fdxx = unique local, ff0x = multicast. This pattern recognition becomes automatic and speeds troubleshooting.
IPv6 introduces a concept not present in IPv4: scope and zone identifiers. These become important when working with link-local addresses.
The Problem
Link-local addresses (fe80::/10) are only valid on a single network segment. A host with multiple interfaces might have the same link-local address (fe80::1) on each interface. When you want to reach fe80::1, which interface should be used?
The Solution: Zone ID (% Syntax)
IPv6 addresses can include a zone identifier suffix:
fe80::1%eth0 (Linux interface name)
fe80::1%12 (Windows interface index)
fe80::1%en0 (macOS interface name)
The zone ID (after %) specifies which interface or link the address refers to.
| Operating System | Zone ID Format | Example | How to Find |
|---|---|---|---|
| Linux | Interface name | fe80::1%eth0 | ip link show |
| Windows | Interface index | fe80::1%12 | netsh interface ipv6 show interfaces |
| macOS | Interface name | fe80::1%en0 | ifconfig |
| BSD | Interface name | fe80::1%em0 | ifconfig |
When Zone IDs Are Required
# Pinging a link-local address WITHOUT zone ID:
$ ping fe80::1
ping: connect: Invalid argument # Error! Which interface?
# Pinging WITH zone ID:
$ ping fe80::1%eth0
PING fe80::1%eth0: 56 data bytes
64 bytes from fe80::1%eth0: icmp_seq=1 ttl=64 time=0.5ms
Address Scopes in IPv6
IPv6 defines several address scopes:
Multicast addresses encode scope in the 4th nibble:
ff01::1 Interface-local all-nodes
ff02::1 Link-local all-nodes
ff05::1 Site-local all-nodes (deprecated)
ff0e::1 Global all-nodes
When using link-local addresses in URLs, the % character must be URL-encoded as %25. For example: http://[fe80::1%25eth0]/page.html. This can cause confusion in scripts and configurations—watch for encoding issues.
Just like IPv4's CIDR notation, IPv6 uses prefix length notation to indicate network boundaries.
Format: address/prefix-length
The prefix length (a number from 0 to 128) indicates how many bits from the left constitute the network portion.
Common Prefix Lengths
| Prefix Length | Usage | Number of Addresses | Example |
|---|---|---|---|
| /128 | Single host | 1 | ::1/128 (loopback) |
| /127 | Point-to-point link (RFC 6164) | 2 | 2001:db8::/127 |
| /126 | Point-to-point (IPv4 style) | 4 | Used on some router links |
| /64 | Standard subnet | 2^64 (~18 quintillion) | 2001:db8:1:1::/64 |
| /56 | Home allocation | 256 /64 subnets | 2001:db8:1::/56 |
| /48 | Site allocation | 65,536 /64 subnets | 2001:db8:1234::/48 |
| /32 | ISP allocation | 65,536 /48s | 2001:db8::/32 |
| /16 | Large registry block | ~4 billion /48s | 2001::/16 |
| /3 | Global unicast range | 1/8 of total space | 2000::/3 |
Visualizing Prefix Boundaries
IPv6 Address: 2001:0db8:85a3:0001:0000:8a2e:0370:7334/64
Binary representation (showing /64 boundary):
Network Prefix (64 bits) Interface ID (64 bits)
┌──────────────────────────────────────┬──────────────────────────────────────┐
│ 0010000000000001 0000110110111000 │ 0000000000000000 1000101000101110 │
│ 1000010110100011 0000000000000001 │ 0000001101110000 0111001100110100 │
└──────────────────────────────────────┴──────────────────────────────────────┘
2001:0db8:85a3:0001 0000:8a2e:0370:7334
▲ ▲
│ │
Network: 2001:db8:85a3:1::/64 Host portion
Calculating the Network Address
To find the network address from a host address:
Example: 2001:db8:85a3:1:1234:5678:9abc:def0/48
Original: 2001:0db8:85a3:0001:1234:5678:9abc:def0
↑
/48 boundary (after 3rd hextet)
Network: 2001:0db8:85a3:0000:0000:0000:0000:0000
= 2001:db8:85a3::/48
Unlike IPv4, IPv6 does not use subnet mask notation (like 255.255.255.0). Prefix length notation (/64) is the only standard method. If someone asks for an IPv6 'subnet mask,' they mean the prefix length.
Certain IPv6 addresses have special meanings and standardized representations. Understanding these is essential for network operations.
The Loopback Address
Full form: 0000:0000:0000:0000:0000:0000:0000:0001
Abbreviated: ::1
Equivalent to IPv4's 127.0.0.1
Used for: Testing local TCP/IP stack
The Unspecified Address
Full form: 0000:0000:0000:0000:0000:0000:0000:0000
Abbreviated: ::
Equivalent to IPv4's 0.0.0.0
Used for: Source address before configuration
Listening on all addresses
Default route destination
IPv4-Mapped IPv6 Addresses
These represent IPv4 addresses within the IPv6 format:
Format: ::ffff:IPv4-address
Examples:
::ffff:192.0.2.1 (using dotted-decimal)
::ffff:c000:0201 (pure hex form)
Used by: Dual-stack applications
IPv6 sockets accepting IPv4 connections
| Address | Full Form | Abbreviated | Purpose |
|---|---|---|---|
| Loopback | 0:0:0:0:0:0:0:1 | ::1 | Local host testing |
| Unspecified | 0:0:0:0:0:0:0:0 | :: | No address / any address |
| IPv4-mapped | 0:0:0:0:0:ffff:IPv4 | ::ffff:a.b.c.d | IPv4 in IPv6 format |
| IPv4-compatible | 0:0:0:0:0:0:a.b.c.d | ::a.b.c.d | Deprecated (don't use) |
| Link-local all-nodes | ff02:0:0:0:0:0:0:1 | ff02::1 | Multicast to all hosts on link |
| Link-local all-routers | ff02:0:0:0:0:0:0:2 | ff02::2 | Multicast to all routers on link |
| Documentation | 2001:db8::/32 | 2001:db8::x | Examples in documentation |
Documentation Addresses (2001:db8::/32)
RFC 3849 reserves 2001:db8::/32 for documentation purposes:
2001:db8::1
2001:db8:1234:5678:9abc:def0:1234:5678
2001:db8:cafe::/48
These addresses will never be allocated for real use. Always use them in:
Using real addresses in documentation can cause accidental traffic to those addresses—use 2001:db8:: instead.
Link-Local Address Format
Prefix: fe80::/10
Bits 11-64: Must be zero
Bits 65-128: Interface identifier
Result: fe80:0000:0000:0000:xxxx:xxxx:xxxx:xxxx
fe80::xxxx:xxxx:xxxx:xxxx
Example: fe80::1a2b:3cff:fe4d:5e6f
If you publish documentation using a real IPv6 address (like 2607:f8b0::1 - Google), readers might accidentally send traffic to that address. Always use 2001:db8::/32 for examples. This is the networking equivalent of using 'example.com' instead of real domain names.
IPv6 supports a special notation that embeds IPv4 addresses in dotted-decimal format within the IPv6 address.
Format: The last 32 bits can be written in IPv4 dotted-decimal:
General: prefix:IPv4-address
Example: ::ffff:192.0.2.1
Equivalent pure hex: ::ffff:c000:0201
c000 = 192 × 256 + 0 = 49152 (c0.00 hex)
0201 = 2 × 256 + 1 = 513 (02.01 hex)
Where Mixed Notation Appears
| Address Type | Format | Example | Usage |
|---|---|---|---|
| IPv4-mapped | ::ffff:a.b.c.d | ::ffff:192.168.1.1 | Dual-stack socket representation |
| IPv4-compatible | ::a.b.c.d | ::192.168.1.1 | Deprecated, historical only |
| NAT64/DNS64 | 64:ff9b::a.b.c.d | 64:ff9b::8.8.8.8 | IPv4/IPv6 translation |
| ISATAP | prefix::0:5efe:a.b.c.d | 2001:db8::5efe:10.0.0.1 | Transition tunneling |
| 6to4 | 2002:IPv4::/48 | 2002:c000:0201::/48 | Automatic tunneling |
Understanding IPv4-Mapped Addresses
When an IPv6-enabled application receives a connection from an IPv4 address, the operating system presents it as:
IPv4 source: 192.0.2.100:5000
Appears as: ::ffff:192.0.2.100 port 5000
This allows IPv6-native applications to accept IPv4 connections transparently on dual-stack systems.
Example: Server Socket
# Python server listening on IPv6 socket
import socket
server = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
server.bind(('::', 8080)) # Bind to all IPv6 addresses
server.listen(5)
conn, addr = server.accept()
print(f"Connection from: {addr}")
# If IPv4 client connects from 192.168.1.100:
# Output: Connection from: ('::ffff:192.168.1.100', 54321, 0, 0)
NAT64 Translation Prefix
Well-known prefix: 64:ff9b::/96
IPv4 address: 8.8.8.8 (Google DNS)
NAT64 form: 64:ff9b::8.8.8.8
or 64:ff9b::0808:0808
IPv6-only clients can reach 8.8.8.8 through NAT64 gateway
using this translated address.
Use mixed notation when the IPv4 component is meaningful—like in transition mechanisms or when logging dual-stack connections. For pure IPv6 addresses, always use the standard colon-hex format. Avoid mixed notation for addresses that have no IPv4 relationship.
Using IPv6 addresses in URLs and configuration files requires special handling because colons already have meaning in these contexts.
The Problem
In a URL like http://host:port/path, the colon separates host from port. But IPv6 addresses contain colons:
Ambiguous: http://2001:db8::1:8080/ # Is 8080 the port or part of IP?
The Solution: Square Brackets
Wrap IPv6 addresses in square brackets:
Correct: http://[2001:db8::1]:8080/
Format: protocol://[IPv6-address]:port/path
| Context | Syntax | Example |
|---|---|---|
| HTTP URL | http://[address]:port/ | http://[2001:db8::1]:80/ |
| HTTPS URL | https://[address]:port/ | https://[2001:db8::1]:443/ |
| SSH | user@[address] | ssh user@[2001:db8::1] |
| FTP URL | ftp://[address]/ | ftp://[2001:db8::1]/ |
| SFTP | sftp://[address]/ | sftp://[2001:db8::1]/ |
| SCP | scp file [2001:db8::1]:/tmp/ | |
| rsync | rsync -av [2001:db8::1]::module/ | |
| PostgreSQL | host=[address] | postgresql://[::1]:5432/db |
| DNS zone | AAAA record | host IN AAAA 2001:db8::1 |
Link-Local Addresses with Zone IDs in URLs
Link-local addresses require zone IDs, which contain % characters that must be URL-encoded:
Address: fe80::1%eth0
URL-encoded fe80::1%25eth0
Full URL: http://[fe80::1%25eth0]:8080/
└──────────────────────────────
%25 = URL-encoded %
Configuration File Examples
# Nginx configuration
server {
listen [::]:80; # Listen on all IPv6 addresses
listen [2001:db8::1]:80; # Listen on specific IPv6
server_name example.com;
}
# Apache configuration
Listen [::]:80
Listen [2001:db8::1]:443
<VirtualHost [2001:db8::1]:443>
ServerName secure.example.com
</VirtualHost>
# SSH config (~/.ssh/config)
Host myserver
HostName 2001:db8::1
# Note: No brackets in ssh_config HostName
Command Line Tools
# ping (varies by OS)
ping6 2001:db8::1 # Linux (some systems)
ping -6 2001:db8::1 # Linux (systemd)
ping 2001:db8::1 # Modern Linux (auto-detect)
ping -6 2001:db8::1 # macOS, Windows
# curl
curl http://[2001:db8::1]:8080/
curl -g "http://[2001:db8::1]:8080/" # -g disables glob parsing
# wget
wget http://[2001:db8::1]/file.txt
# netcat
nc -6 2001:db8::1 80
Some shells interpret square brackets as glob patterns. Use quotes or the -g flag (curl) to prevent expansion. If you see 'no matches found' errors, quoting is likely the solution: curl "http://[2001:db8::1]/"
IPv6 address notation uses hexadecimal and colons to represent 128-bit addresses in a relatively compact form. Let's consolidate the key concepts:
What's Next
Now that we can read and write IPv6 addresses, we'll learn the abbreviation rules that dramatically shorten most addresses. These rules make IPv6 much more practical for daily use—transforming 2001:0db8:0000:0000:0000:0000:0000:0001 into the much friendlier 2001:db8::1.
You can now read and write IPv6 addresses in their full form, understand special address representations, use zone IDs for link-local communication, and properly format addresses in URLs and configuration files. Next, we'll master the abbreviation rules that make IPv6 manageable in practice.