★ Web · regex
Regex for IPv6 Address
Covers the eight-group form and every legal placement of the :: shorthand. It does not cover zone IDs (%eth0) or IPv4-embedded forms like ::ffff:192.0.2.1.
- Runs in your browser
- No signup
Try the ipv6 address pattern
Read it in plain English (best-effort)
- ^start of a line
- (?:start a group (not captured)
- (?:start a group (not captured)
- [0-9A-Fa-f]one character from: 0–9, A–F, a–f
- {1,4}between 1 and 4 of the previous
- :the character ':'
- )end of group
- {7}exactly 7 of the previous
- [0-9A-Fa-f]one character from: 0–9, A–F, a–f
- {1,4}between 1 and 4 of the previous
- |or
- (?:start a group (not captured)
- [0-9A-Fa-f]one character from: 0–9, A–F, a–f
- {1,4}between 1 and 4 of the previous
- :the character ':'
- )end of group
- {1,7}between 1 and 7 of the previous
- :the character ':'
- |or
- (?:start a group (not captured)
- [0-9A-Fa-f]one character from: 0–9, A–F, a–f
- {1,4}between 1 and 4 of the previous
- :the character ':'
- )end of group
- {1,6}between 1 and 6 of the previous
- :the character ':'
- [0-9A-Fa-f]one character from: 0–9, A–F, a–f
- {1,4}between 1 and 4 of the previous
- |or
- (?:start a group (not captured)
- [0-9A-Fa-f]one character from: 0–9, A–F, a–f
- {1,4}between 1 and 4 of the previous
- :the character ':'
- )end of group
- {1,5}between 1 and 5 of the previous
- (?:start a group (not captured)
- :the character ':'
- [0-9A-Fa-f]one character from: 0–9, A–F, a–f
- {1,4}between 1 and 4 of the previous
- )end of group
- {1,2}between 1 and 2 of the previous
- |or
- (?:start a group (not captured)
- [0-9A-Fa-f]one character from: 0–9, A–F, a–f
- {1,4}between 1 and 4 of the previous
- :the character ':'
- )end of group
- {1,4}between 1 and 4 of the previous
- (?:start a group (not captured)
- :the character ':'
- [0-9A-Fa-f]one character from: 0–9, A–F, a–f
- {1,4}between 1 and 4 of the previous
- )end of group
- {1,3}between 1 and 3 of the previous
- |or
- (?:start a group (not captured)
- [0-9A-Fa-f]one character from: 0–9, A–F, a–f
- {1,4}between 1 and 4 of the previous
- :the character ':'
- )end of group
- +44 more
One sample per line works well with the m flag on anchored patterns.
The pattern, piece by piece
/^(?:(?:[0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4}|(?:[0-9A-Fa-f]{1,4}:){1,7}:|(?:[0-9A-Fa-f]{1,4}:){1,6}:[0-9A-Fa-f]{1,4}|(?:[0-9A-Fa-f]{1,4}:){1,5}(?::[0-9A-Fa-f]{1,4}){1,2}|(?:[0-9A-Fa-f]{1,4}:){1,4}(?::[0-9A-Fa-f]{1,4}){1,3}|(?:[0-9A-Fa-f]{1,4}:){1,3}(?::[0-9A-Fa-f]{1,4}){1,4}|(?:[0-9A-Fa-f]{1,4}:){1,2}(?::[0-9A-Fa-f]{1,4}){1,5}|[0-9A-Fa-f]{1,4}:(?::[0-9A-Fa-f]{1,4}){1,6}|:(?:(?::[0-9A-Fa-f]{1,4}){1,7}|:))$/| Part | What it does |
|---|---|
[0-9A-Fa-f]{1,4} | one group of 1–4 hex digits |
(?:group:){7}group | the full eight-group form |
…:(?::group){n} | each alternative places the :: gap in a different position |
:(?:(?::group){1,7}|:) | addresses starting with ::, including :: on its own |
What it accepts and rejects
Every sample below is checked automatically in JavaScript and Python. The tester above is preloaded with all of them, one per line.
| Should match | |
|---|---|
2001:0db8:85a3:0000:0000:8a2e:0370:7334 | ✓ |
2001:db8::8a2e:370:7334 | ✓ |
::1 | ✓ |
:: | ✓ |
fe80::1 | ✓ |
2001:db8:: | ✓ |
| Should not match | |
|---|---|
2001:db8::85a3::7334 | ✗ |
1:2:3:4:5:6:7:8:9 | ✗ |
12345::1 | ✗ |
gggg::1 | ✗ |
192.168.1.1 | ✗ |
:1:2:3:4:5:6:7 | ✗ |
Copy it into your code
RE2-safeNo lookarounds or backreferences, so the same pattern works in Go's RE2 engine and in Rust's regex crate.
const ipv6Re = /^(?:(?:[0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4}|(?:[0-9A-Fa-f]{1,4}:){1,7}:|(?:[0-9A-Fa-f]{1,4}:){1,6}:[0-9A-Fa-f]{1,4}|(?:[0-9A-Fa-f]{1,4}:){1,5}(?::[0-9A-Fa-f]{1,4}){1,2}|(?:[0-9A-Fa-f]{1,4}:){1,4}(?::[0-9A-Fa-f]{1,4}){1,3}|(?:[0-9A-Fa-f]{1,4}:){1,3}(?::[0-9A-Fa-f]{1,4}){1,4}|(?:[0-9A-Fa-f]{1,4}:){1,2}(?::[0-9A-Fa-f]{1,4}){1,5}|[0-9A-Fa-f]{1,4}:(?::[0-9A-Fa-f]{1,4}){1,6}|:(?:(?::[0-9A-Fa-f]{1,4}){1,7}|:))$/;
export function isValidIpv6(value) {
return ipv6Re.test(value.trim());
}When not to use regex for this
Parse IPv6 with your language's IP library (net/netip in Go, ipaddress in Python, a library in JavaScript). It handles zone IDs, embedded IPv4 and canonical formatting, and the code reads better than this pattern.
Questions engineers actually ask
Why is the IPv6 regex so long?
Does it accept ::ffff:192.168.1.1?
What is catastrophic backtracking?
More web patterns
- Email AddressPragmatic email check: catches typos without rejecting real addresses.^[A-Za-z0-9_%+-]+(?:\.[A-Za-z0-9_%+-]+)*@[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?(?:\.[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*\.[A-Za-z]{2,}$
- URLhttp(s) URLs with a real domain, optional port, path, query and fragment.^https?:\/\/(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?\.)+[A-Za-z]{2,63}(?::\d{1,5})?(?:[\/?#]\S*)?$
- Domain NameHostnames like example.com or sub.example.co.uk, including punycode.^(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?\.)+[A-Za-z]{2,63}$
- URL SlugLowercase kebab-case slugs like my-first-post.^[a-z0-9]+(?:-[a-z0-9]+)*$
- IPv4 AddressDotted-quad IPv4 with each octet 0–255 and no leading zeros.^(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$
- Hex ColorCSS hex colours: #rgb, #rgba, #rrggbb and #rrggbbaa.^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$
- HTML TagFinds opening, closing and self-closing tags in a string. Not a parser.<\/?([A-Za-z][A-Za-z0-9-]*)\b[^<>]*>
Or browse the full regex library.
More from the workbench
Fine print
Tools: on the house.
Engineer: by the hour.
The regex was free. Code that doesn't need one is the upgrade: typed schemas, validated once at the edge, trusted everywhere after.
I'm Himanshu, an AI and full-stack engineer. I build MVPs, AI agents and the growth plumbing around them for early-stage startups.
