Skip to content
VPNDetection

Mobile proxy detection: how wide can a block safely be?

87% of mobile proxy IPv4 addresses sit on mobile operators' networks. What a block on each hit's address, /24 or network takes out, and a rule to use instead.

Published 4 min read

On this page
  1. Where proxy addresses sit
  2. How much a wider block takes out
  3. A rule by flag

On Hacker News in September, a site owner whose pages were being scraped through residential proxies was told to set "strict rate limits per IP / per /24 / per ASN" (Hacker News). Hours later, a Show HN for a tool that checks whether an address has been in a residential proxy network drew the reply "This would probably false positive every CGNAT IP" (Hacker News).

On mobile networks, both run into address sharing. A mobile proxy sends its customers' traffic out through a phone or a modem with a SIM card, so a site sees the carrier's address. Most carriers put many subscribers behind each public IPv4 address: a 2016 study found carrier-grade NAT in more than 90% of the cellular networks it measured (Richter et al.). The phone can also be a subscriber's own. On October 8, Bitdefender reported Midnight Mimosa, malware in the firmware of cheap Android phones that, among other things, makes each one a residential proxy exit. Its researchers saw the campaign on thousands of devices in more than 150 countries over about two years (Bitdefender).

So we measured where the addresses in our proxy data sit on mobile operators' networks, and how much of those networks a block takes out at each width.

Where proxy addresses sit

We took every IPv4 address seen in a mobile, residential or datacenter proxy pool in the 90 days to October 16, 2026, and matched it to the networks of operators that run a mobile network, their home broadband included. Those networks held 1,194,571,085 IPv4 addresses that day, and 87.0% of the mobile proxy addresses were on them:

Stacked bar chart of where IPv4 addresses seen in proxy pools in the 90 days to October 16, 2026 sit: 87.0% of mobile proxy addresses and 55.7% of residential ones on mobile operators' networks, while 89.8% of datacenter proxy addresses are on hosting networks.

The mobile and residential flags overlap. 93.7% of the mobile proxy addresses were in a residential proxy pool in the same 90 days, so they answer is_resproxy as well as is_mobproxy. And is_mobproxy marks few of the proxy addresses on mobile operators' networks: of the 38,376,364 there, 94.4% answer is_resproxy without it. A rule that goes easy on is_mobproxy alone still applies its residential rule to most proxy hits on those networks.

How much a wider block takes out

This is what a rule takes out of mobile operators' 1.19 billion addresses when it blocks each hit's address, its /24 or its whole network (AS), for hits seen in the last day and in the last 90 days, the window over which our API counts a proxy address's hits:

Block each hit'sMobile proxy, last dayMobile proxy, 90 daysResidential proxy, last dayResidential proxy, 90 days
Address0.004%0.18%0.18%3.2%
/240.47%4.0%14.3%36.9%
Network (AS)78.7%96.1%97.9%99.3%

The address is the only width that stays small, and it still isn't one person: the table counts addresses, and an address behind carrier-grade NAT carries many subscribers at once. Blocking a mobile proxy address refuses everyone else on it too, for as long as the block stands. On these networks a hit is a reason to ask for more, not to refuse.

Rate limits work the same way. A limit keyed on the /24 or the network puts the proxy in one bucket with every subscriber behind it, so key it on the account or session instead.

A rule by flag

The flags still separate a cheap block from a costly one. A datacenter proxy address on a hosting network, as 89.8% of them are, is a server, which nobody's phone or home line shares, and so is a public proxy on one, an open proxy anyone can use. Any other proxy hit may be someone's connection. Here's that rule with our Python library:

python
import os
import sys

from vpndetection import Result, VPNDetection

FLAGS = ("is_dcproxy", "is_hosting", "is_mobproxy", "is_pubproxy", "is_resproxy")


def decide(r: Result) -> str:
    """block, challenge or allow, from the proxy flags alone."""
    if (r.is_dcproxy or r.is_pubproxy) and r.is_hosting:
        return "block"
    if r.is_dcproxy or r.is_mobproxy or r.is_pubproxy or r.is_resproxy:
        return "challenge"
    return "allow"


with VPNDetection(os.environ["VPNDETECTION_API_KEY"]) as client:
    for arg in sys.argv[1:]:
        name, ip = arg.split("=")
        r = client.lookup(ip)
        flags = " ".join(f for f in FLAGS if r.flagged(f))
        print(f"{name:<18} {decide(r):<10} {flags}".rstrip())

We ran it on November 5, 2026, with Python 3.15.2 and vpndetection 5.12.3 on a Max plan key, over seven addresses from our data that we don't print: a mobile proxy exit on a mobile operator's network, a residential proxy exit on a fixed-line network, a datacenter proxy exit on a hosting network, another on a mobile operator's network, a public proxy on a hosting network, another on a cable ISP's network, and a Comcast home line.

mobile-proxy       challenge  is_mobproxy is_resproxy
residential-proxy  challenge  is_resproxy
dc-proxy           block      is_dcproxy is_hosting
dc-proxy-operator  challenge  is_dcproxy
public-proxy-host  block      is_hosting is_pubproxy
public-proxy-isp   challenge  is_pubproxy
home-line          allow

Block the address only, even for datacenter proxies: one day's datacenter proxy hits came from networks holding 38.8% of mobile operators' addresses.

What a challenge asks for depends on the action: an emailed code at signup, say, or 3-D Secure at payment. decide takes a lookup's result rather than an address, so it sits beside the lookup your handler already makes. lookup raises VPNDetectionError when the API can't answer, so settle what an outage means for each action before you ship.

The proxy flags come with every paid plan (pricing). decide and flagged() both read a flag your plan doesn't include as false, so on a free key or none every line reads allow: with no key, all seven did.

Each proxy flag comes with its detail, last_seen included, and the residential, datacenter and mobile ones with hits too, so a rule can weigh a hit by how recently and how often the address was seen (How long do residential proxy IPs last?). An address that leaves the 90 days keeps its flag, so last_seen is what says how recent a hit is. The Mobile Proxy IP and Residential Proxy IP databases carry the same fields, for lookups on your own servers.

Written by

  • Uman Shahzad

    Founder & CEO

    IP intelligence data expert for over 8 years, former lead engineer at IPinfo, Uman has pioneered many systems and practices used by IP data companies to operate at scale, provide high-quality data and offer the best developer experiences.

Get new posts by email

Or follow along in a feed reader.

RSS feed

Try it on your own traffic.

The detection these posts describe is one API call away, with SDKs for every major language.

00 · No key

Start without signing up.

Paste it into a terminal. No account needed. 1,000 lookups a day per address, answering ip and is_vpn.

curl "https://api.vpndetection.io/146.70.116.130"
{
"ip": "146.70.116.130",
"is_vpn": true
}
01 · Free key

Sign up and get 50,000 requests a month.

No card and no sales call: the key is issued on signup.
Every request flags VPN IPs.
Upgrade only when you outgrow the allowance.