Methodology

How We Test VPNs

Every test runs in your browser. Where a test needs to know which network an address belongs to, our server looks it up with ip-api.com and keeps the answer - never the address - for up to 30 minutes.

🔍

IP Leak Test

Your IPv4 address comes from api.ipify.org, which has no IPv6 address and so can only see IPv4. Our server looks it up with ip-api.com: if ip-api.com lists it as hosting or a proxy, or its network is named as a VPN or hosting operator, your IPv4 is considered protected.

Your IPv6 address, if you have one, comes from api64.ipify.org and is looked up the same way, on its own. It is a leak when IPv4 goes through a VPN and IPv6 leaves through a consumer network - your ISP’s. Comparing the two addresses directly tells nothing: they always differ, being different families.

Pass condition: the IPv4 address belongs to VPN or hosting infrastructure, and there is either no IPv6 address or one that does too. A lookup that does not answer scores neither way.

🌐

DNS Leak Test

Your browser looks up hostnames that exist only for this test, under a zone our own nameserver answers, so the resolvers that ask for them are the ones your system really uses. Each is placed in its network (ASN) and compared with the network of your IPv4 exit.

Pass condition: every resolver sits in the same network as your IPv4 exit. One outside it fails, even a VPN’s or a public resolver. A resolver we cannot place, or an exit whose network is unknown, gives no verdict; with no tunnel, the resolvers are shown and not scored.

📡

WebRTC Leak Test

Using the browser's native RTCPeerConnection API and two STUN servers (Google's and Cloudflare's), we collect the addresses your browser hands out, and read the addresses sites see separately for each family - IPv4 from api.ipify.org, IPv6 from api64.ipify.org.

Private, carrier-grade NAT, link-local and loopback addresses are normal and expected. A leak is a public address that sites do not otherwise see: an IPv4 address other than your visible IPv4, or an IPv6 address on a consumer network while your IPv4 goes through a VPN. Each address is compared only with one of its own family - an IPv4 address and an IPv6 one always differ, which says nothing.

Pass condition: every public address WebRTC showed was compared, and none of them was one sites do not otherwise see. An address that could not be compared makes the run “not fully compared”, never a pass.

⚡

Speed Test

Ping & Jitter: We send 5 HEAD requests to cloudflare.com/cdn-cgi/trace and measure round-trip time. Jitter = max minus min of trimmed samples.

Download: We fetch a 10 MB file from speed.cloudflare.com/__down and calculate throughput. Falls back to httpbin.org if Cloudflare is blocked.

Upload: We POST a 2 MB buffer to speed.cloudflare.com/__up and measure throughput.

Ratings: ≥100 Mbps = Excellent · ≥25 = Good · ≥5 = Fair · <5 = Poor

🔐

Encryption Check

A web page cannot read its own TLS session, but Cloudflare, which serves this site, reports the session it negotiated at /cdn-cgi/trace on the same address. We read that report: the TLS and HTTP version, the key exchange (whether it gives forward secrecy, and whether it is a post-quantum hybrid) and whether the site’s name went out encrypted. We also check whether this page loaded anything over plain HTTP.

Grading: A for TLS 1.3, B for TLS 1.2 with forward secrecy, C for anything older or without it, F for a page not served over HTTPS or with mixed content. No report, no grade: the page says “not measured” instead.

What it never sees is your VPN tunnel’s own cipher (WireGuard, OpenVPN, IKEv2): that is set by the VPN app and no web page can read it.

🔪

Kill Switch Test

We read your IPv4 address every 2 seconds from api.ipify.org, which has no IPv6 address. A service that answers over IPv6 when it can sees your IPv6 address on a dual-stack connection, and for a VPN that carries only IPv4 that address is the ISP’s before the drop and after it - the drop would go unseen. The address read when you start is the baseline.

A different IPv4 address at any check is a failure: traffic went out through another network instead of being blocked. A check that gets no answer counts as blocked only if our own server, api.vpnmeter.com, which also has only an IPv4 address, does not answer either and the browser reports itself online. Otherwise api.ipify.org may just be down, or the device offline, and the check is logged but not counted. A pass needs at least one blocked check, then the connection back on the starting address, and no change in between: a block that never ends looks the same as a network outage. A run with no block, or a block never followed by a reconnect, is not offered for sharing.

Your IPv6 address is read alongside from api64.ipify.org and reported - whether it changed, kept answering or went quiet while IPv4 was down. It cannot fail a run, since which network an IPv6 address belongs to takes a lookup this test does not make, but it can keep one from passing: if IPv6 answers while IPv4 is blocked, or the IPv6 address changes during the run, the run is not offered for sharing as a pass.

How to test: Start the test → force-quit your VPN app (a normal Disconnect can turn a kill switch off on purpose) → start it again → watch whether a different IPv4 address appears in the log, or the connection is blocked until the VPN is back.

⚠ Known Limitations

  • · Classifying an address depends on the databases behind it - ip-api.com for the VPN, DNS and WebRTC leak tests and the provider pages, ipapi.co for some other tools - and some VPN IPs may be misclassified.
  • · Speed test results reflect your VPN connection to Cloudflare's nearest PoP, not absolute bandwidth.
  • · The Encryption Check sees only what Cloudflare reports for this session between your browser and this site, never the VPN tunnel.
  • · WebRTC can be turned off by the browser or an extension. The test then says “WebRTC off” rather than listing addresses - with WebRTC off, no page can use it to read your address either.