Skip to content
IP Intelligence

Identify the VPN Provider Behind an IP From Its Own Server List

19 min readGeoIPHub Team

We fetched Mullvad's relay list at 05:22 UTC on 13 October 2026. It held 566 relays, 553 WireGuard servers and 13 bridges, and Mullvad marks only 124 of them as hardware it owns. One of the owned ones, 185.213.155.73 in Frankfurt, is registered in WHOIS to "31173 Services Germany", has no reverse DNS, and is announced by AS39351. Nothing in its network record says "Mullvad". Only the list does.

That is the whole trick behind every "which VPN is this IP" tool, and almost none of them say so. Below we list the endpoints where providers publish their servers, give a tested Python matcher, and show what our API returned for the provider-listed servers we looked up, plus controls, misses included. It ends with a policy table. For the detection side, meaning how a VPN is caught at all, read how VPN detection works, signal by signal.

Four converging light paths of different brightness meeting at one node, representing the four ways a VPN provider gets named
Four paths can name a provider; the confidence value tells you which one fired.

Can you tell which VPN an IP address belongs to?

Yes, when the IP is on a list the provider publishes. A VPN app has to know where its servers are before it can connect, so providers serve that list to their apps, and most of those lists are public. If the address is on no list, you can usually still tell it is a VPN from probes and hosting signals, but not whose.

Here is 185.213.155.73 traced end to end. Mullvad's list, at api.mullvad.net/www/relays/all/, has a row for it with hostname "de-fra-wg-001", type "wireguard", city_name "Frankfurt", owned true and provider "31173". That last field is the hosting company, and here it is Mullvad's own.

The registry tells a different story. RIPE's RDAP record, which we opened at 05:28 UTC, names the range NET-31173-185-213-155-0-24 and the registrant "31173 Services Germany". The RIPE whois route object gives origin AS39351. We ran dig -x 185.213.155.73 and got no answer at all.

Then we looked it up in our API at 05:27 UTC. This is a trimmed copy, values unedited:

GeoIPHub API
{ "ip": "185.213.155.73", "asn": { "asn": 39351, "org": "ESAB-AS - 31173 Services AB" }, "whois": { "org": "31173 Services AB infrastructure in Frankfurt, DE.", "netname": "NET-31173-185-213-155-0-24", "has_vpn_keywords": false }, "detection": { "is_vpn": true, "vpn_provider": "Mullvad", "vpn_confidence": 95 }, "scoring": { "fraud_score": 100, "recommended_action": "block", "detection_methods": ["known_vpn_server", "wireguard_open", "datacenter_with_vpn_proxy", "no_ptr_datacenter"] } }

Look at whois.has_vpn_keywords. It is false, on a Mullvad server, and it was false on every address we looked up. The WHOIS text never mentions a VPN. The name "Mullvad" came from the list match, and vpn_confidence 95 is the value our API gives for that path. The block came from the evidence: an open WireGuard port on a hosting address.

Why WHOIS, reverse DNS and the ASN name the host, not the VPN

Most VPN servers run on rented machines, so the network record describes the landlord. In our sample, M247 (AS9009) hosts listed servers of NordVPN, PIA, AirVPN, IVPN and FastestVPN. Datacamp (AS212238) hosts a Mullvad New York server and an IVPN Buenos Aires server. A rule that says "M247 means VPN" is a guess about a hosting company. The provider's list is evidence about a server.

Mullvad makes the point for us. Its list marks every relay owned true or false and names the host in provider. On 13 October, 124 of its 566 relays were owned: true, and the most common hosts were DataPacket (128 relays), Tzulo (127) and M247 (98). We looked up two rented Mullvad relays at 05:33 UTC:

Mullvad relay, per its listHost in the listOur asn.orgvpn_provider, vpn_confidenceScore, action
149.22.83.2, ar-bue-wg-001, owned falseDataPacketCDNEXT - Datacamp LimitedMullvad, 9599, block
91.90.123.2, be-bru-wg-101, owned falseM247M247 - M247 Europe SRLMullvad, 95100, block

An ASN check on either says "hosting company". The list says Mullvad. The New York relay us-nyc-wg-301, 143.244.47.65, tells the same story on Datacamp.

Reverse DNS is weaker still. We ran dig -x on 20 of the provider-listed addresses at 05:28 UTC. Eleven returned nothing, and none of the other nine named a VPN brand:

IPListed byWhat dig -x returned
143.244.47.65Mullvadunn-143-244-47-65.datapacket.com
149.22.83.100IVPNunn-149-22-83-100.datapacket.com
198.44.137.44Windscribestatic-198-44-137-44.cust.tzulo.com
204.13.164.252Riseupleapgwv6.bitmask.net
185.244.212.69IVPN185.244.212.69.adsl.inet-telecom.org
185.213.155.73Mullvadno PTR

The Riseup name hints at the VPN software, LEAP and Bitmask, not at a brand. The IVPN Vienna name says "adsl", which reads like a home connection, on a server IVPN lists. That is the danger of reading too much into a PTR.

The ASN names the VPN only when the provider runs its own network, as Mullvad does with AS39351 and Riseup with AS16652. If you want the background, here is what an ASN is and who it names. Our API keeps a short table of networks run by VPN providers, with Mullvad's AS39351 on it, and that table is one of the four naming paths below.

Where VPN providers publish their server IPs

These are the lists the providers' own apps read. "Fetched today" means our network got a 200 response on 13 October 2026; "not reachable today" means the request failed from our network after two tries.

ProviderList the app readsWhere the IP isStatus on 13 October 2026
Mullvadapi.mullvad.net/www/relays/all/ipv4_addr_in, ipv6_addr_inFetched today, 05:22 UTC: 566 relays, 124 owned
AirVPNairvpn.org/api/status/ip_v4_in1 to ip_v4_in4Fetched today, 05:22 UTC: 250 servers
IVPNapi.ivpn.net/v5/servers.jsonWireGuard and OpenVPN host entriesFetched today, 05:22 UTC: 89 WireGuard hosts in 59 locations
PrivadoVPNprivadovpn.com/apps/servers_export.jsonipFetched today, 05:22 UTC: 167 servers
Riseupapi.black.riseup.net/3/config/eip-service.json, found via riseup.net/provider.jsonip_addressFetched today, 05:23 UTC: 21 gateways
NordVPNapi.nordvpn.com/v2/servers, per gluetun's NordVPN updaterstationNot reachable today (timed out)
Surfsharkapi.surfshark.com/v4/server/clusters, per gluetun's Surfshark updaterHostnames onlyNot reachable today (TLS error, then timeout)
Private Internet Accessserverlist.piaservers.net/vpninfo/servers/v6, per PIA's own get_region.shServer IPs per regionNot reachable today (TLS error)
Windscribeassets.windscribe.com/serverlist/mob-v2/1/, per gluetun's Windscribe updaterip, ip2, ip3Not reachable today (timed out)

The four we could not reach are real endpoints. We know them from the providers' official or open-source clients, and gluetun's NordVPN code even comments that the station field "is, it seems, the entry IP address." Their APIs block requests from data centers, which is where our scanner runs, and on 13 October they did not answer the network we used for this post either.

So our API names VPNs from the providers' own server lists plus a public third-party list. For NordVPN, PIA and Windscribe, our scanner falls back to saved copies of their API responses, dated 4 October 2026. We hold no Surfshark copy. The third-party list is gluetun-servers, the community-maintained server data behind gluetun, an open-source VPN client container. We load its files for more than 20 providers, and it is our only source for FastestVPN. The four of its files we fetched today, for ExpressVPN, FastestVPN, NordVPN and PIA, all carry a timestamp of 6 August 2026.

Identify a VPN provider by IP yourself: Mullvad and NordVPN

Download the provider's list and look for an exact match on the address. Mullvad is the easy case because its list answered every time we asked. This is the script we ran at 05:29 UTC on 13 October 2026, on Python 3.9.6, standard library only:

GeoIPHub API
"""Check IPs against Mullvad's public relay list. Standard library only.""" import ipaddress, json, sys, urllib.request URL = "https://api.mullvad.net/www/relays/all/" def load_relays(url=URL): with urllib.request.urlopen(url, timeout=30) as resp: relays = json.load(resp) index = {} for r in relays: for key in ("ipv4_addr_in", "ipv6_addr_in"): if r.get(key): index[ipaddress.ip_address(r[key])] = r return relays, index def match(index, ip): try: addr = ipaddress.ip_address(ip.strip()) except ValueError: return None if addr.version == 6 and addr.ipv4_mapped: addr = addr.ipv4_mapped # ::ffff:141.98.252.67 becomes 141.98.252.67 return index.get(addr) if __name__ == "__main__": try: relays, index = load_relays() except Exception as e: sys.exit(f"could not load Mullvad's list: {e}") print(f"{len(relays)} relays, {len(index)} addresses") ips = sys.argv[1:] or [line for line in sys.stdin if line.strip()] for ip in ips: r = match(index, ip) if r: result = f"{r['hostname']} {r['type']} {r['city_name']} owned={r['owned']} host={r['provider']}" else: result = "not on Mullvad's list" print(f"{ip.strip():22} {result}")

We passed seven inputs on the command line, and it printed:

GeoIPHub API
566 relays, 1122 addresses 185.213.155.73 de-fra-wg-001 wireguard Frankfurt owned=True host=31173 143.244.47.65 us-nyc-wg-301 wireguard New York, NY owned=False host=DataPacket 45.83.220.68 se-mma-wg-101 wireguard Malmö owned=True host=31173 45.83.220.7 not on Mullvad's list ::ffff:141.98.252.67 gb-lon-wg-001 wireguard London owned=True host=31173 102.129.235.17 not on Mullvad's list not-an-ip not on Mullvad's list

We also piped three lines with blanks and padding through stdin, the way you would feed it a log column, and it matched 45.83.220.70 to se-mma-wg-103. Pointed at a URL that returns 404, it printed "could not load Mullvad's list: HTTP Error 404: Not Found" and exited with status 1. Two caveats: an invalid input is reported as not on the list rather than as an error, and the 13 bridges are matched too, so read the type column.

How to detect NordVPN the same way. NordVPN's list puts each server's IP in a station field, and our saved copy from 4 October has one per server. The live endpoint timed out from our network on 13 October, twice, so we are not publishing NordVPN code we could not run. Run the same exact-match logic from a network NordVPN answers.

For one address at a time, you can check any IP for a VPN and its provider; the tool returns the name in detection.vpn_provider. In code, it is one request with the IP in the path:

GeoIPHub API
curl https://api.geoiphub.com/v1/lookup/185.213.155.73 \ -H "x-api-key: YOUR_API_KEY"

vpn_provider is on the free tier, which includes every data field at 1,500 lookups a day. If you key anything on the name, match its start, not the whole string: our API returned "Mullvad" for listed servers and "Mullvad (31173 Services)" for the ASN path. This is the snippet we ran at 05:34 UTC, without a key:

GeoIPHub API
import json, sys, urllib.request def lookup(ip, key=None): # A custom User-Agent: our API answered Python's default one with a 403. headers = {"User-Agent": "vpn-provider-check/1.0"} if key: headers["x-api-key"] = key req = urllib.request.Request(f"https://api.geoiphub.com/v1/lookup/{ip}", headers=headers) with urllib.request.urlopen(req, timeout=10) as resp: return json.load(resp) for ip in sys.argv[1:]: data = lookup(ip) provider = data["detection"]["vpn_provider"] named = provider != "none" is_mullvad = provider.startswith("Mullvad") # "Mullvad" or "Mullvad (31173 Services)" print(ip, repr(provider), "named" if named else "unnamed", "mullvad" if is_mullvad else "-", "is_vpn" if data["detection"]["is_vpn"] else "not_vpn", data["scoring"]["recommended_action"])
GeoIPHub API
185.213.155.73 'Mullvad' named mullvad is_vpn block 45.83.220.7 'Mullvad (31173 Services)' named mullvad is_vpn review 102.129.235.17 'none' unnamed - is_vpn block

The third line is the one to design for: no name, still a VPN, still a block.

If you are asking the other question, whether your own connection shows as NordVPN, open see the IP your connection shows while connected.

What our API returned for provider-listed IPs

Listed servers from every provider we sampled came back named, and vpn_confidence shows which of four paths named them. On a named row, the value maps to the path:

vpn_confidencePath that named the IP
95The provider's own server list
90A server hostname from gluetun's files, resolved by us to this IP
85A short table of networks run by a VPN provider
80The public gluetun server list

We ran these lookups between 05:27 and 05:28 UTC on 13 October 2026. The last column shows only VPN handshake probes that answered; we left the rest of detection_methods out of the table.

IPProvider and server, per its listWhere we found the IPvpn_providervpn_confidenceScore, actionProbe that answered
185.213.155.73Mullvad, de-fra-wg-001Mullvad, fetched todayMullvad95100, blockwireguard_open
143.244.47.65Mullvad, us-nyc-wg-301, owned falseMullvad, fetched todayMullvad9599, blockwireguard_open
82.102.19.137NordVPN, be148NordVPN copy of 4 Oct; also in gluetunNordVPN8099, blockwireguard_open
173.239.247.129PIA, VietnamPIA copy of 4 Oct; also in gluetunPIA8051, step_upnone
198.44.137.44Windscribe, Dallas, us-central-117Windscribe copy of 4 OctWindscribe95100, blockipsec_open, wireguard_open
185.156.175.170AirVPN, Achernar, ZurichAirVPN, fetched todayAirVPN9599, blockwireguard_open
149.22.83.100IVPN, ar1.wg, Buenos AiresIVPN, fetched todayIVPN9599, blockwireguard_open
85.12.5.56PrivadoVPN, hkg-006PrivadoVPN, fetched todayPrivadoVPN9036, reviewnone
204.13.164.252Riseup, vpn01-seaRiseup, fetched todayRiseup9548, reviewnone
31.171.152.205ExpressVPN, Albaniagluetun file of 6 AugExpressVPN8051, step_upnone
46.102.153.134FastestVPN, au-stream, Sydneygluetun file of 6 AugFastestVPN9099, blockwireguard_open
45.83.220.7Not on Mullvad's listNoneMullvad (31173 Services)8546, reviewnone

Three rows need a word. The NordVPN and PIA servers are on our saved copies, but they came back at 80, the gluetun value, and both are in gluetun's files. The PrivadoVPN server is on PrivadoVPN's own export today, yet it came back at 90, not 95: its name came from resolving its hostname, hkg-006.vpn.privado.io, which gluetun's PrivadoVPN file also carries. Read the path from vpn_confidence, not from the list where you found the IP. ExpressVPN is not one of the nine providers whose own lists we pull. One gluetun-listed ExpressVPN address came back named, which shows the path works, not that we cover ExpressVPN.

The last row is the ASN path. 45.83.220.7 is not on Mullvad's list; today's list has .68, .69 and .70 in that /24, not .7. It is named because its network, AS39351, belongs to Mullvad's operator:

GeoIPHub API
{ "ip": "45.83.220.7", "asn": { "asn": 39351, "org": "ESAB-AS - 31173 Services AB" }, "whois": { "org": "31173 Services AB infrastructure in Malmo, SE.", "netname": "NET-31173-45-83-220-0-24", "has_vpn_keywords": false }, "detection": { "is_vpn": true, "vpn_provider": "Mullvad (31173 Services)", "vpn_confidence": 85 }, "scoring": { "fraud_score": 46, "recommended_action": "review", "detection_methods": ["known_vpn_server", "datacenter_ip"] } }

Note that known_vpn_server fires here too. That method name does not mean "on a provider's list"; on this row it comes from the network table. Read vpn_confidence for the path, and only on rows where vpn_provider is not "none".

Why some VPN IPs come back "none"

"none" means the IP is on none of the lists we hold right now. It does not mean the IP is not a VPN, and it does not mean a provider's neighbouring address is clean.

NordVPN's server pl128, 194.99.105.99, is in the NordVPN response we saved on 4 October, listed as online. Today it returned vpn_provider "none", yet is_vpn true, score 98 and block, with ipsec_open among its methods. Its IPsec handshake caught it; nothing named it. PIA's Liechtenstein server, 91.90.122.25, is in PIA's list from the same day. Today it returned is_vpn false and a score of 64, step_up, from blocklist and hosting signals alone.

Neither of those two addresses is in gluetun's files, while the named NordVPN and PIA rows above both are. We could not re-fetch NordVPN's or PIA's API today, so either server may have been retired or re-addressed since 4 October. What we can say is narrower and certain: a server is named only when it is on a list we currently hold.

We also have a miss on a provider whose list we did fetch today. 91.90.123.29 sits in the same /24 as the listed Mullvad relay 91.90.123.2, but it is not on Mullvad's list. IPinfo's provider page showed it as its Mullvad example IP on 13 October. Our API returned is_vpn false, vpn_provider "none", score 12, allow. It may be an exit or an unlisted address next to a listed one; that is suggestive, not proof. Either way, a list match covers the listed address and nothing beside it.

The documented control shows the unnamed but detected case. 102.129.235.17, on AS834 IPXO, returned is_vpn true, vpn_provider "none", score 92, block, with known_vpn_server, openvpn_open and ipsec_open. An unnamed server is still caught when it completes an OpenVPN, WireGuard or IPsec handshake with our scanner; the hub post linked above covers the probes.

Common reasons a VPN IP stays unnamed:

  • No public list. Some providers publish none, and a self-hosted VPN never appears on one.
  • List unreachable. Four of the nine lists we pull block data centers, so we work from saved copies where we have them, and from gluetun.
  • Rotation. A server can leave the list or change address after our last copy.
  • It is a proxy, not a VPN. Proxies have no provider list to match; see datacenter, residential and mobile proxies.

iCloud Private Relay and Cloudflare WARP are not VPN providers in this sense. They get their own field, relay_provider, and their own policy, covered in iCloud Private Relay and Cloudflare WARP.

A named VPN is not a riskier VPN

The name says who runs the server; the score comes from the evidence, such as open handshake ports, hosting and abuse history. Some of the lowest scores in our sample went to named servers, and one of the highest went to an unnamed one.

IPvpn_providerScore, action
85.12.5.56PrivadoVPN36, review
45.83.220.7Mullvad (31173 Services)46, review
204.13.164.252Riseup48, review
102.129.235.17none92, block

Our bands are allow up to 25, review up to 50, step_up up to 75 and block above 75. PrivadoVPN's server answered no handshake probe in our data, so only known_vpn_server fired and it stayed in review. The unnamed server answered two. That is the right way round: a rule should weigh what we observed, not whose logo is on the server. The signal weights are on the how the score is built page.

Entry IPs, rotated servers and stale names

A provider list tells you the address the app connects to. For most servers in our sample, that same address answered our probes, but we verified only that listed addresses are named, not that every exit address a provider uses is on a list.

The field names say "in". Mullvad uses ipv4_addr_in, and AirVPN publishes four addresses per server as ip_v4_in1 to ip_v4_in4. Surfshark's list gives hostnames only, so someone has to resolve names to IPs before anything can match. Our 90 path does that for the server hostnames in gluetun's files. It is how FastestVPN's au-stream.jumptoserver.com, 46.102.153.134, got its name.

Lists also carry state you should read. Mullvad's list today marks 24 relays active: false, including se-mma-wg-101, 45.83.220.68, which our API still names "Mullvad" at 95. A listed server is a fact about the provider's fleet, not proof that the server carried traffic today. This is also why vendors' VPN IP counts disagree so widely. They count different things, such as servers, listed entry addresses, observed exit addresses or whole ranges, on different dates. Mullvad's own list is the only count we quote. We do not publish a refresh schedule for provider lists here; if you run the matcher yourself, fetch the list before each batch.

What to do with a provider name

Use the name for policy and investigation, not as a block switch. Key decisions on recommended_action and the evidence behind it, and key exceptions and reporting on the name.

What you seeActionWhy
Named VPN (vpn_provider set)Follow recommended_action; use the name for allow-lists you choose, licensing logs and grouping abuse by operatorThe name is attribution, not risk: PrivadoVPN scored 36, review, and Mullvad's Frankfurt server 100, block
Unnamed VPN (is_vpn true, vpn_provider "none")Treat it exactly like a named VPN at the same score102.129.235.17 scored 92 without a name
Relay (is_relay true)Allow and score the sessionRelays are not VPN providers; they use relay_provider
Clean (is_vpn false, no relay)Allow unless other signals fireNo anonymizer evidence, though a listed server can drop out, as PIA's 91.90.122.25 did

The usual mistake is the first row turned into a block rule, which turns a provider's customers into VPN detection false positives. Two checks to run on your own logs this week:

  • Find rules keyed on the name. Search your rules for vpn_provider. A rule like "block if a provider is named" lets the unnamed 92 through and blocks the named 36. Key on the action and the evidence instead, and match names by prefix.
  • Match your logs against one list. Feed the last 30 days of signup or login IPs to the Mullvad matcher and count the matches. Compare that with how many of those requests your rules declined, then spot-check a few in the IP lookup tool.

Frequently Asked Questions

Can you tell which VPN an IP address belongs to?

Yes, when the IP is on a server list the VPN provider publishes for its own apps. If it is on no list, you can usually still tell it is a VPN, but not whose.

Is there a list of NordVPN IP addresses?

NordVPN's apps read one from api.nordvpn.com, which gives each server's IP in a station field. On 13 October 2026 it did not answer requests from our network, so we used a saved copy.

Does WHOIS or reverse DNS show the VPN provider?

Rarely. Most VPN servers sit on rented hosting networks such as M247, so WHOIS and reverse DNS name the host. Even Mullvad's own Frankfurt range is registered to 31173 Services.

What does vpn_provider none mean?

The IP is on none of the server lists we hold. It does not mean the IP is not a VPN: check is_vpn and scoring.detection_methods.

Does a named VPN get a higher fraud score?

No. A listed PrivadoVPN server scored 36, review, while an unnamed VPN scored 92, block. The name says who runs the server; the score comes from the evidence.

Which VPN providers publish their server lists?

Mullvad, AirVPN, IVPN, PrivadoVPN and Riseup answered public requests from us on 13 October 2026. NordVPN, Surfshark, PIA and Windscribe publish lists for their apps but did not answer from our network.