For developers

How the IPv6 test works

The test fetches the same payload from two hostnames: one published with an A record only, one with an AAAA record only. A hostname that offers a single record type cannot fall back to the other family, so a success proves that family works end to end. A third signal, the address the page request itself arrived on, shows which family your browser chose when both were available.

Run it on /ipv6-test. This guide is the mechanism behind that page.

One hostname cannot answer the question

A dual-stack hostname publishes both an A and an AAAA record, and the client picks. If you fetch it and see an IPv4 address in the response, you have learned nothing: the client may have had no IPv6, or may have had working IPv6 and preferred v4 anyway. Both produce the same output.

Record-type isolation removes the choice. v4.whatsmyip.fyi publishes A records only and v6.whatsmyip.fyi publishes AAAA records only. There is no fallback available, so each fetch is a clean test of one family:

dig +short A  v4.whatsmyip.fyi
dig +short AAAA v4.whatsmyip.fyi   # empty by design
dig +short AAAA v6.whatsmyip.fyi
dig +short A  v6.whatsmyip.fyi     # empty by design

The page fetches /json from each with a short timeout and fills two slots. A timeout is reported as a failed probe, never as an absent family, which is why “could not test” is one of the verdicts rather than being folded into “no IPv6”.

Keeping the AAAA record off a proxied hostname takes some care, because CDNs add IPv6 to proxied names by default. That is a deployment detail rather than a protocol one, and it is documented in the repository.

Happy Eyeballs decides which family your browser used

The third signal is the connection you are already on. Your browser resolved the main hostname, got both record types, and picked one. That choice is made by Happy Eyeballs version 2, RFC 8305, which replaced RFC 6555.

The algorithm, compressed:

  1. Send the AAAA and A queries at the same time.
  2. If the A answer arrives first, wait a short Resolution Delay, recommended at 50 ms, to give AAAA a chance rather than committing to v4 immediately.
  3. Sort the destination addresses using the policy table in RFC 6724, which prefers IPv6 in the default configuration.
  4. Start a connection to the first address. If it has not completed after the Connection Attempt Delay, recommended at 250 ms, start the next one in parallel rather than waiting for a timeout.
  5. Keep the first connection that completes its handshake, and cancel the rest.

Two consequences matter for reading a test result. First, broken IPv6 almost never produces a visible error; it produces a delay of a few hundred milliseconds and a silent fall back to IPv4. Second, a working but slower IPv6 path loses the race consistently, which is the correct outcome and not a fault.

The four verdicts

Verdict v6 probe v4 probe Page request arrived over What it means
IPv6 working and preferred Success Success IPv6 Full dual stack, and your stack chose v6. Nothing to change.
IPv6 available, browser preferred IPv4 Success Success IPv4 The v6 path exists but lost the Happy Eyeballs race, or a local policy table demotes it.
No IPv6 Failure Success IPv4 No IPv6 reaches your device. ISP, router prefix delegation, or a per-interface setting.
Could not test Failure Failure or timeout either Something blocked the probes: a captive portal, a corporate proxy, or an extension stopping cross-origin requests.

The second verdict is the one that generates support questions. It is common on Windows where a group policy adjusts the prefix policy table, on networks with a high-latency tunnel supplying IPv6, and on connections whose v6 path drops packets intermittently.

Reading the ASN mismatch

Alongside both addresses, the page reports the autonomous system announcing each one. See what an ASN is for what that number represents.

Matching ASNs are the expected result: one network carries both families. A mismatch means the two families leave your network by different routes, and there are only a few causes:

  • A VPN tunnelling IPv4 only. The IPv4 address belongs to the provider, the IPv6 address belongs to your ISP. Every IPv6-capable site you visit records your real address while the client shows connected. This is the single most common VPN failure.
  • A tunnel broker. IPv6 supplied over an IPv4-only ISP by a service such as Hurricane Electric. The mismatch is expected and harmless.
  • A corporate split tunnel where policy sends one family through the corporate network.
  • Two upstreams on a multihomed network, which is normal in an office and unusual at home.

With a VPN connected, treat any mismatch as a leak and check it alongside DNS and WebRTC on /vpn-check.

Reproducing it from a terminal

-4 and -6 force curl to use one family and to fail rather than fall back, which gives you the same isolation the two hostnames give the browser.

curl -4 https://v4.whatsmyip.fyi/ip
curl -6 https://v6.whatsmyip.fyi/ip

Failure messages are worth distinguishing. Could not resolve host means your resolver returned no usable record, which on the v6 hostname usually means the stub resolver has no IPv6 source address to query from. Network is unreachable means the record resolved but there is no route, which points at the router or the ISP rather than at DNS.

For both addresses with their ASNs in one call:

curl -4 -s https://v4.whatsmyip.fyi/json | jq '{ip, asn, asOrganization}'
curl -6 -s https://v6.whatsmyip.fyi/json | jq '{ip, asn, asOrganization}'

To see the race itself rather than the outcome, force the family on a dual-stack hostname and compare connect times:

curl -4 -s -o /dev/null -w 'v4 connect %{time_connect}s\n' https://whatsmyip.fyi/ip
curl -6 -s -o /dev/null -w 'v6 connect %{time_connect}s\n' https://whatsmyip.fyi/ip

A v6 connect time more than 250 ms behind the v4 one explains a browser that keeps choosing IPv4, because that is the Connection Attempt Delay the algorithm uses.

What the test does not prove

It measures your browser’s path to one edge network. It does not prove that arbitrary IPv6 destinations are reachable, since a partial IPv6 deployment can reach a large CDN and fail elsewhere. It says nothing about IPv6 inside your LAN, where router advertisements may be missing while the WAN side works. And address selection is per device, so another machine on the same network can legitimately produce a different verdict.

For the raw fields behind both addresses, use /report, or the curl cookbook for the scriptable versions.

Questions people ask

Why not just check for an IPv6 address on my device?
Every interface has a link-local fe80:: address whether or not IPv6 reaches the internet, and a global address can exist on a network whose upstream path is broken. Only an end-to-end fetch over IPv6 proves the path.
Why does the test say IPv6 works but my browser used IPv4?
Happy Eyeballs races both families and keeps whichever completes its handshake first. A v6 path that is present but a few tens of milliseconds slower loses the race every time, which is a working connection making a reasonable choice.
What does an ASN mismatch between my IPv4 and IPv6 addresses mean?
The two families are taking different paths. Usually a VPN tunnelling IPv4 only while IPv6 goes direct to your ISP, or a tunnel broker supplying IPv6 over an IPv4-only ISP. With a VPN connected, treat it as a leak.
Can I run this test from a script?
Yes. curl -4 and curl -6 force the address family, and the v4 and v6 hostnames make the result unambiguous. Both commands are at the end of this guide.

Last reviewed 2026-09-04. Reviewed quarterly, or sooner when a vendor changes something.