# 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.

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](https://news.ycombinator.com/item?id=49706947)). 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](https://news.ycombinator.com/item?id=49716749)).

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.](https://arxiv.org/abs/1605.05606)). 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](https://www.bitdefender.com/en-us/blog/labs/midnight-mimosa-malware)).

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.](/blog/media/mobile-proxy-detection-where.2x.png)

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](https://vpndetection.io/api) counts a proxy address's hits:

| Block each hit's | Mobile proxy, last day | Mobile proxy, 90 days | Residential proxy, last day | Residential proxy, 90 days |
|---|---:|---:|---:|---:|
| Address | 0.004% | 0.18% | 0.18% | 3.2% |
| /24 | 0.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](https://vpndetection.io/blog/public-proxy-detection-api) 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](https://docs.vpndetection.io/integrations/python):

```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](https://vpndetection.io/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?](https://vpndetection.io/blog/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](https://vpndetection.io/databases/mobile-proxy-ip) and [Residential Proxy IP](https://vpndetection.io/databases/residential-proxy-ip) databases carry the same fields, for lookups on your own servers.

