| Both sides previous revisionPrevious revisionNext revision | Previous revision |
| design:ip_classification [2026/08/06 21:47] – DB-IP Lite row: quote DB-IP's own description of the Lite tiers as reduced-coverage subsets. Authored by Claude. karel.kubicek.claude | design:ip_classification [2026/08/21 14:50] (current) – Boxes: <wrap> renders a span, use uppercase <WRAP>; one box per list, not per bullet karel.kubicek.claude |
|---|
| | Is it the //same host// as last week? | Nothing reliable | Bad. Assume no unless you can show otherwise | — | | | Is it the //same host// as last week? | Nothing reliable | Bad. Assume no unless you can show otherwise | — | |
| |
| The rows are in descending order of defensibility, and papers reach for the bottom rows far more often than the top ones. Of the 234 papers in our corpus that classify an IP address, 92 name a geolocation source and only 53 name a routing or ASN source (see [[#Use in Publications]]) — even though the routing answer is the one that is nearly always correct. | The rows are in descending order of defensibility, and papers reach for the bottom rows far more often than the top ones. Of the 295 papers in our corpus that classify an IP address, 114 name a geolocation source and only 68 name a routing or ASN source (see [[#Use in Publications]]) — even though the routing answer is the one that is nearly always correct. |
| |
| <WRAP important> | <WRAP important> |
| * **Playwright**: ''await response.serverAddr()'' → ''{ipAddress, port}''. | * **Playwright**: ''await response.serverAddr()'' → ''{ipAddress, port}''. |
| * **Chrome DevTools Protocol** (so also Puppeteer, and OpenWPM through its instrumentation): ''Network.responseReceived'' → ''e.response.remoteIPAddress'' and ''remotePort''. | * **Chrome DevTools Protocol** (so also Puppeteer, and OpenWPM through its instrumentation): ''Network.responseReceived'' → ''e.response.remoteIPAddress'' and ''remotePort''. |
| * **A HAR file**: the per-entry ''serverIPAddress'' field. See [[Programming:Traffic files]]. | * **A HAR file**: the per-entry ''serverIPAddress'' field, which HAR 1.2 defines and Chrome, Firefox and Playwright all populate. (More on working with HAR: [[Programming:Traffic files]].) |
| |
| Measured on one page load of ''https://www.bbc.com/'' on 6 August 2026: all 130 responses carried an address via Playwright and via CDP; the HAR was missing one, a beacon still in flight when the context closed. So take it from the live event stream if you can, and treat a HAR as very slightly lossy. | Measured on one page load of ''https://www.bbc.com/'' on 6 August 2026: all 130 responses carried an address via Playwright and via CDP; the HAR was missing one, a beacon still in flight when the context closed. So take it from the live event stream if you can, and treat a HAR as very slightly lossy. |
| Every routable address is inside a prefix that some autonomous system announces into BGP. That mapping is public, is not a vendor's opinion, and is free: | Every routable address is inside a prefix that some autonomous system announces into BGP. That mapping is public, is not a vendor's opinion, and is free: |
| |
| * **[[https://team-cymru.com/community-services/ip-asn-mapping/|Team Cymru IP-to-ASN mapping]]** — the practical default. A ''whois'' bulk interface on port 43 takes thousands of addresses per connection and returns ASN, covering prefix, allocating RIR, allocation date and AS name; there is also a DNS interface. Free for research use, no key. The script in [[#A Script]] uses it. | * **[[https://team-cymru.com/community-services/ip-asn-mapping/|Team Cymru IP-to-ASN mapping]]** — the practical default. A ''whois'' bulk interface on port 43 takes thousands of addresses per connection and returns ASN, covering prefix, the country and RIR on the allocation record, the allocation date and the AS name; there is also a DNS interface. Free for research use, no key. The script in [[#A Script]] uses it. |
| * **[[https://www.routeviews.org/|RouteViews]]** and **[[https://ris.ripe.net/docs/|RIPE RIS]]** — the raw BGP collector archives everything else is derived from. Use these if you need a mapping //as of a historical date//, which no live API gives you. | * **[[https://www.routeviews.org/|RouteViews]]** and **[[https://ris.ripe.net/docs/|RIPE RIS]]** — the raw BGP collector archives everything else is derived from. Use these if you need a mapping //as of a historical date//, which no live API gives you. |
| * **[[https://stat.ripe.net/docs/02.data-api/|RIPEstat Data API]]** — HTTP, no key, one address at a time; convenient for a handful of lookups. No hard rate limit for casual use; registration is asked for above 1,000 requests a day. | * **[[https://stat.ripe.net/docs/02.data-api/|RIPEstat Data API]]** — HTTP, no key, one address at a time; convenient for a handful of lookups. No hard rate limit for casual use; registration is asked for above 1,000 requests a day. |
| * **[[https://asdb.stanford.edu/|ASdb]]** {[ziv2021_asdb]} classifies ASNs into 17 industry categories and 95 sub-categories (hosting, ISP, education, government…), reporting 96% coverage of ASes at 93% accuracy on the top level and 75% on sub-categories. Snapshots run through March 2026. Used, for example, by {[darwich2023_replication]} to describe what kind of networks their geolocation targets sat in. | * **[[https://asdb.stanford.edu/|ASdb]]** {[ziv2021_asdb]} classifies ASNs into 17 industry categories and 95 sub-categories (hosting, ISP, education, government…), reporting 96% coverage of ASes at 93% accuracy on the top level and 75% on sub-categories. Snapshots run through March 2026. Used, for example, by {[darwich2023_replication]} to describe what kind of networks their geolocation targets sat in. |
| |
| <wrap todo>**CAIDA's separate //AS Classification// dataset is discontinued** — CAIDA's own page states it is no longer supported and download access has been removed. Papers from 2015–2022 cite it routinely; ASdb is the live replacement. Check before you cite a dataset you found in a related-work section.</wrap> | <WRAP todo>**CAIDA's separate //AS Classification// dataset is discontinued** — CAIDA's own page states it is no longer supported and download access has been removed. Papers from 2015–2022 cite it routinely; ASdb is the live replacement. Check before you cite a dataset you found in a related-work section.</WRAP> |
| |
| The current state of the art on the sibling problem is {[selmo2025_borges]} (IMC 2025), which few-shot prompts an LLM over PeeringDB free-text fields plus website and domain evidence, and reports a 7% improvement in sibling-ASN identification over AS2Org-style methods. That is, as of 2026, **the one place in IP classification where an LLM method has cleared peer review** — see [[#Open Questions]]. | The current state of the art on the sibling problem is {[selmo2025_borges]} (IMC 2025), which few-shot prompts an LLM over PeeringDB free-text fields plus website and domain evidence, and reports a 7% improvement in sibling-ASN identification over AS2Org-style methods. That is, as of 2026, **the one place in IP classification where an LLM method has cleared peer review** — see [[#Open Questions]]. |
| </WRAP> | </WRAP> |
| |
| One more corpus data point, because it shows the databases disagreeing on a population you might actually study rather than on a ground-truth set. {[khan2018_commercial]} compared the //claimed// locations of 626 commercial-VPN vantage points against three databases and reported agreement of **70% (Google), 90% (IP2Location Lite) and 95% (MaxMind GeoLite2)** — a 25-point spread on the same addresses. Their observation about the residue matters more than the ranking: | One more corpus data point, because it shows the databases disagreeing on a population you might actually study rather than on a ground-truth set. {[khan2018_commercial]} took 626 commercial-VPN vantage points and asked three databases whether each one was where the provider //claimed// it was. Note the denominators, which differ because the services answered for different subsets: Google agreed for **377 of 541 (70%)**, IP2Location Lite for **552 of 612 (90%)**, MaxMind GeoLite2 for **583 of 612 (95%)**. This measures agreement with a marketing claim rather than accuracy against ground truth — but a 25-point spread between three databases on one address set is the point. Their observation about the residue matters more than the ranking: |
| |
| > For all databases, about one third of the inconsistencies were the database claiming a vantage point was hosted in the US when the claimed location was elsewhere. | > For all databases, about one third of the inconsistencies were the database claiming a vantage point was hosted in the US when the claimed location was elsewhere. |
| Worth knowing, because it tells you where they will be wrong. When {[darwich2023_replication]} asked IPinfo why they were doing so well, the answer was that they use "hints extracted from DNS, WHOIS, geofeeds [...] or other proprietary data" on top of latency measurements. So: | Worth knowing, because it tells you where they will be wrong. When {[darwich2023_replication]} asked IPinfo why they were doing so well, the answer was that they use "hints extracted from DNS, WHOIS, geofeeds [...] or other proprietary data" on top of latency measurements. So: |
| |
| * **Self-published geofeeds.** [[https://www.rfc-editor.org/rfc/rfc8805.html|RFC 8805]] (2020) defines a CSV format in which a network operator publishes the location of its own prefixes; [[https://www.rfc-editor.org/rfc/rfc9092.html|RFC 9092]] (2021) defines how to find that file from RPSL ''remarks:'' in the RIR databases and authenticate it with RPKI. Where an operator publishes one, it is as close to ground truth as this field gets. **Adoption is small and you should check rather than assume**: two years after standardisation, {[livadariu2024_geofeeds]} measured geofeed coverage at **1.50% of allocated IPv4 prefixes and 0.70% of IPv6**, with erroneous entries for 0.9% of client, 4.0% of router and 8.5% of server addresses. Their own conclusion is that geofeeds are "at least a geolocation hint", not a ground-truth dataset. | * **Self-published geofeeds.** [[https://www.rfc-editor.org/rfc/rfc8805.html|RFC 8805]] (2020) defines a CSV format in which a network operator publishes the location of its own prefixes; [[https://www.rfc-editor.org/rfc/rfc9632.html|RFC 9632]] (August 2024) defines how to find that file from RPSL ''remarks:'' in the RIR databases and authenticate it with RPKI — **it obsoletes RFC 9092**, which is what most papers and blog posts still cite. Where an operator publishes one, it is as close to ground truth as this field gets. **Adoption is small and you should check rather than assume**: two years after standardisation, {[livadariu2024_geofeeds]} measured geofeed coverage at **1.50% of allocated IPv4 prefixes and 0.70% of IPv6**, with erroneous entries for 0.9% of client, 4.0% of router and 8.5% of server addresses. Their own conclusion is that geofeeds are "at least a geolocation hint", not a ground-truth dataset. |
| * **Reverse DNS naming** — router and server hostnames often encode a city or airport code (''ae-1.fra3.example.net''). This is the ''undns''/DDec line of work, systematised in **Hoiho** {[luckie2021_hoiho]}, which learns per-operator regexes and validates them against RTT constraints; CAIDA's topology data kit tags each router location with which method produced it. It is why {[gamerogarrido2022_using]} could identify institutional networks by resolving 616,705 addresses to 440,233 hostnames. | * **Reverse DNS naming** — router and server hostnames often encode a city or airport code (''ae-1.fra3.example.net''). This is the ''undns''/DDec line of work, systematised in **Hoiho** {[luckie2021_hoiho]}, which learns per-operator regexes and validates them against RTT constraints; CAIDA's topology data kit tags each router location with which method produced it. It is why {[gamerogarrido2022_using]} could identify institutional networks by resolving 616,705 addresses to 440,233 hostnames. |
| * **WHOIS and RIR allocation records** give the //registrant's// country, which is often not the host's. The script below shows the canonical example: 1.1.1.1 is allocated under APNIC with country ''AU'', is operated by a US company, and is anycast on every continent. | * **WHOIS and RIR allocation records** give the //registrant's// country, which is often not the host's. The script below shows the canonical example: 1.1.1.1 is allocated under APNIC with country ''AU'', is operated by a US company, and is anycast on every continent. |
| * **Latency** — constraint-based geolocation {[gueye2004_cbg]} from a probe network. Accurate when a probe is close, useless when there is not one. {[darwich2023_replication]} quantified both the ceiling and the cost: removing vantage points closer than 40 km moved the median error from 8 km to 120 km, and the median time to geolocate a single IP was **1,238 seconds (about 20 minutes)** on a 32-core machine. If you want this without building it, [[https://ipmap.ripe.net/|RIPE IPmap]] {[du2020_ipmap]} runs a latency engine and a reverse-DNS engine over RIPE Atlas and exposes the result through a public API — for infrastructure addresses, not arbitrary hosts. | * **Latency** — constraint-based geolocation {[gueye2004_cbg]} from a probe network. Accurate when a probe is close, useless when there is not one. {[darwich2023_replication]} quantified the ceiling: removing vantage points closer than 40 km moved the median error from 8 km to 120 km. Accuracy is not the binding constraint, though — throughput is. Replicating the finer-grained //street-level// technique, they measured a median of **1,238 seconds (about 20 minutes) to geolocate one address** on a 32-core machine with 62 GB of RAM, against the 1–2 seconds its authors had projected. Budget for that before you plan to geolocate a crawl's worth of servers actively. If you want this without building it, [[https://ipmap.ripe.net/|RIPE IPmap]] {[du2020_ipmap]} runs a latency engine and a reverse-DNS engine over RIPE Atlas and exposes the result through a public API — for infrastructure addresses, not arbitrary hosts. |
| |
| ==== Anycast: addresses with no location ==== | ==== Anycast: addresses with no location ==== |
| ^ Source ^ What you get free ^ Status ^ Notes ^ | ^ Source ^ What you get free ^ Status ^ Notes ^ |
| | **MaxMind GeoLite2** | Country, City (incl. ''accuracy_radius'') and ASN databases, under the GeoLite2 EULA plus CC BY-SA 4.0 for redistribution | Current, but **since 30 December 2019 you need an account and a licence key** to download | The field's default by inertia. MaxMind's own stated reason for the 2019 change was that GDPR and CCPA restricted their "ability to continue distributing our GeoLite databases on a public page". Measured at 55% within 40 km in 2023 {[darwich2023_replication]}. No committed release cadence — their docs say to check for a new release periodically through the day — so "we used MaxMind" without a date is not reproducible. | | | **MaxMind GeoLite2** | Country, City (incl. ''accuracy_radius'') and ASN databases, under the GeoLite2 EULA plus CC BY-SA 4.0 for redistribution | Current, but **since 30 December 2019 you need an account and a licence key** to download | The field's default by inertia. MaxMind's own stated reason for the 2019 change was that GDPR and CCPA restricted their "ability to continue distributing our GeoLite databases on a public page". Measured at 55% within 40 km in 2023 {[darwich2023_replication]}. No committed release cadence — their docs say to check for a new release periodically through the day — so "we used MaxMind" without a date is not reproducible. | |
| | **MaxMind GeoIP2 / Insights** | — (paid; City from ~$148/month at list) | Current | Same ''accuracy_radius'' field. **Use it**: it is the vendor telling you not to trust the point. | | | **MaxMind GeoIP2 / Insights** | — (paid: GeoIP City listed at $148/month or $1,628/year on 2026-08-06, Country at $38/month) | Current | Same ''accuracy_radius'' field. **Use it**: it is the vendor telling you not to trust the point. Note the listed price covers internal use only; a commercial licence is separate. | |
| | **IPinfo** | The free "Lite" database is **country and ASN only**, unlimited, CC BY-SA with attribution. City-level and privacy detection start at the paid tier. | Current | Best performer in the only recent head-to-head in the corpus {[darwich2023_replication]} — but note that measurement used IPinfo's //free API// as it stood in 2023, and the free tier has been restructured since. Check what you are actually getting. | | | **IPinfo** | The free "Lite" database is **country and ASN only**, unlimited, CC BY-SA with attribution. City-level and privacy detection start at the paid tier. | Current | Best performer in the only recent head-to-head in the corpus {[darwich2023_replication]} — but note that measurement used IPinfo's //free API// as it stood in 2023, and the free tier has been restructured since. Check what you are actually getting. | |
| | **IP2Location LITE** | Country/city/ASN under CC BY-SA 4.0 with mandatory attribution | Current | Its Lite tier tied with NetAcuity for //coverage// in {[gharaibeh2017_look]} — "near perfect", against MaxMind's 43% and 61.6% at city level. Coverage is not accuracy; on accuracy it sat with MaxMind at 77.5–78.6%. | | | **IP2Location LITE** | Country/city/ASN under CC BY-SA 4.0 with mandatory attribution | Current | Its Lite tier tied with NetAcuity for //coverage// in {[gharaibeh2017_look]} — "near perfect", against MaxMind's 43% and 61.6% at city level. Coverage is not accuracy; on accuracy it sat with MaxMind at 77.5–78.6%. | |
| | **NetAcuity (Digital Element)** | — (paid, enterprise, sales-gated) | Current | Best accuracy in {[gharaibeh2017_look]} (2017). We found no academic-access programme; 5 papers in the corpus. | | | **NetAcuity (Digital Element)** | — (paid, enterprise, sales-gated) | Current | Best accuracy in {[gharaibeh2017_look]} (2017). We found no academic-access programme; 5 papers in the corpus. | |
| | **RIPE IPmap** | Latency and reverse-DNS engines over RIPE Atlas, open API {[du2020_ipmap]} | Current | Infrastructure addresses (routers, IXPs) rather than arbitrary hosts. | | | **RIPE IPmap** | Latency and reverse-DNS engines over RIPE Atlas, open API {[du2020_ipmap]} | Current | Infrastructure addresses (routers, IXPs) rather than arbitrary hosts. | |
| | **Geofeeds (RFC 8805/9092)** | The operator's own published claim | Current but **thinly adopted** — 1.50% of IPv4 prefixes {[livadariu2024_geofeeds]} | Check for one; do not build a pipeline that assumes one exists. | | | **Geofeeds (RFC 8805, RFC 9632)** | The operator's own published claim | Current but **thinly adopted** — 1.50% of IPv4 prefixes {[livadariu2024_geofeeds]} | Check for one; do not build a pipeline that assumes one exists. | |
| | **Quova, Neustar IP Intelligence, HostIP.info, freegeoip.net, IPInfoDB** | — | **Historical.** Present in the corpus; superseded or gone | If a paper's method rests on one of these, that paper is telling you about 2012. | | | **Quova, Neustar IP Intelligence, HostIP.info, freegeoip.net, IPInfoDB** | — | **Historical.** Present in the corpus; superseded or gone | If a paper's method rests on one of these, that paper is telling you about 2012. | |
| |
| ==== Ask the operator first ==== | ==== Ask the operator first ==== |
| |
| The most accurate datacenter detection is free, authoritative and almost unused in this literature: **the cloud and CDN operators publish their own prefix lists.** Grepping the full text of all 4,322 papers in the corpus for the URLs below finds them in **six**.((Full-text grep of `paper.cols.txt` for `ip-ranges.amazonaws`, `gstatic.com/ipranges`, `cloudflare.com/ips`, `public_ip_ranges.json` or `ServiceTags_Public`, run 2026-08-06. Six papers, all network-measurement rather than web-privacy. This undercounts papers that used a list without citing its URL, so read it as a floor.)) | The most accurate datacenter detection is free, authoritative and almost unused in this literature: **the cloud and CDN operators publish their own prefix lists.** Grepping the full text of all 5,859 papers in the corpus for the URLs below finds them in **seven**.((Full-text grep of `paper.cols.txt` for `ip-ranges.amazonaws`, `gstatic.com/ipranges`, `cloudflare.com/ips`, `public_ip_ranges.json` or `ServiceTags_Public`, re-run 2026-08-12 against the extended corpus. Seven papers, all network-measurement rather than web-privacy; the seventh, added with the 2025 venue-year, is //Secure IP Address Allocation at Cloud Scale// (NDSS 2025). This undercounts papers that used a list without citing its URL, so read it as a floor.)) |
| |
| All of the following were fetched and confirmed serving on 6 August 2026: | All of the following were fetched and confirmed serving on 6 August 2026: |
| If an address is in AWS's own file, it is AWS. No vendor score improves on that. Note the limit, which the script output below demonstrates: these files cover what the operator wants you to route to. Google's ''cloud.json'' is GCP customer space and does **not** contain 8.8.8.8; Cloudflare's ''ips-v4'' is their proxy range and does **not** contain 1.1.1.1. | If an address is in AWS's own file, it is AWS. No vendor score improves on that. Note the limit, which the script output below demonstrates: these files cover what the operator wants you to route to. Google's ''cloud.json'' is GCP customer space and does **not** contain 8.8.8.8; Cloudflare's ''ips-v4'' is their proxy range and does **not** contain 1.1.1.1. |
| |
| There is a real gap here: we found **no peer-reviewed method for systematically identifying hosting and datacenter address space** beyond these published lists and the commercial products below. The academic work closest to it is AS-level classification ({[ziv2021_asdb]}, {[selmo2025_borges]}), which labels a whole AS rather than a prefix. | There is a gap here worth stating carefully. We found **no peer-reviewed general classifier for hosting and datacenter address space at prefix granularity** beyond these published lists and the commercial products below. Adjacent work exists and is worth reading before you conclude nobody has tried: AS-level classification ({[ziv2021_asdb]}, {[selmo2025_borges]}) labels a whole AS rather than a prefix, and the //off-net// literature — Gigis et al., "Seven Years in the Life of Hypergiants' Off-Nets" (SIGCOMM 2021), and He et al., "Next Stop, the Cloud" (IMC 2013) — identifies specific serving infrastructure by other means. None of them is the thing you want, which is a maintained prefix-to-network-type map for the whole address space. |
| |
| ==== Commercial VPN, proxy and abuse feeds ==== | ==== Commercial VPN, proxy and abuse feeds ==== |
| * **GreyNoise** covers Internet-wide scanners specifically, and — unusually — runs a free [[https://docs.greynoise.io/docs/vip-program|Research Community programme]] giving students and independent researchers non-commercial access to the full enterprise API. If you need this class of data for a paper, ask them before you pay anyone. | * **GreyNoise** covers Internet-wide scanners specifically, and — unusually — runs a free [[https://docs.greynoise.io/docs/vip-program|Research Community programme]] giving students and independent researchers non-commercial access to the full enterprise API. If you need this class of data for a paper, ask them before you pay anyone. |
| |
| Only 13 of the 234 IP-classifying papers in the corpus name a feed of this kind, and **all but one are from 2019 or later** (the exception is 2018) — this is the newest of the five questions and the least settled. | Only 17 of the 295 IP-classifying papers in the corpus name a feed of this kind, and **all but one are from 2019 or later** (the exception is 2018) — this is the newest of the five questions and the least settled. |
| |
| <WRAP important> | <WRAP important> |
| |
| * {[mi2019_resident]} captured 6,183,876 distinct residential proxy IPs and classified 5.9M (95.22%) as genuinely residential; of the hosts they could fingerprint, 237,029 (43%) were IoT devices — cameras, DVRs, printers — and 67 potentially unwanted programs were found enrolling hosts. | * {[mi2019_resident]} captured 6,183,876 distinct residential proxy IPs and classified 5.9M (95.22%) as genuinely residential; of the hosts they could fingerprint, 237,029 (43%) were IoT devices — cameras, DVRs, printers — and 67 potentially unwanted programs were found enrolling hosts. |
| * {[mi2021_your]} found 963 Android apps embedding proxy SDKs, and 624,989 cellular IPv4 addresses used as exits. | * {[mi2021_your]} found 963 Android apps embedding proxy SDKs, and 624,989 proxy exit addresses that IPinfo classified as cellular — a number that is itself the output of the kind of commercial classification this page is about, which is worth noticing. |
| * {[yang2022_extensive]} captured 8,176,522 backconnect residential proxy IPs in China, and measured their lifetime: around 91% of the directly-exposed ones lasted **less than 10 days**. | * {[yang2022_extensive]} infiltrated Chinese residential-proxy services and captured 8,176,522 backconnect proxy IPs — which, despite the services targeting the China market, were spread across 227 countries. They also measured lifetime: around 91% of the directly-exposed ones lasted **less than 10 days**. |
| |
| For the ethics of //using// one, see [[Design:Crawling location]] and [[Practices:Ethics]]. For //detecting// them in data you already have, the current technique is a **cross-layer latency discrepancy**: an application-layer RTT that is much larger than the network-layer RTT to the same address means something is terminating the connection in front of the real host. {[ramesh2024_calculatency]} (USENIX Security 2024) is the reference implementation — at a 50 ms threshold it reports 2.9% false negatives and 0.95% false positives, and 94.2% of the VPN addresses it tested answered ICMP at all, which is what makes the measurement possible. Two caveats before you adopt it: | For the ethics of //using// one, see [[Design:Crawling location]] and [[Practices:Ethics]]. For //detecting// them in data you already have, the current technique is a **cross-layer latency discrepancy**: an application-layer RTT that is much larger than the network-layer RTT to the same address means something is terminating the connection in front of the real host. {[ramesh2024_calculatency]} (USENIX Security 2024) is the reference implementation — at a 50 ms threshold it reports 2.9% false negatives and 0.95% false positives, and 94.2% of the VPN addresses it tested answered ICMP at all, which is what makes the measurement possible. Two caveats before you adopt it: |
| |
| * It is an **active** technique. You are probing third-party hosts; that belongs in your ethics section. | * It is an **active** technique. You are probing third-party hosts; that belongs in your ethics section. |
| * The threshold is fragile in exactly the conditions a real client has. A 2023 IMC poster measured the RTT delta under ordinary client environments and found a mobile device on 4G sitting at 51.5 ± 14.5 ms — over a 50 ms threshold with no proxy present at all, while a browser rather than a script, or a Wi-Fi hotspot, each added delay without individually crossing it. | * The threshold may be fragile in exactly the conditions a real client has. {[chiapponi2023_poster]} probed the RTT delta from one laptop and one handset in France, 20 connections per configuration, and found the handset on 4G at **51.5 ± 14.5 ms** — over a 50 ms threshold with no proxy present — while a browser rather than a script, or a Wi-Fi hotspot, each added delay without individually crossing it. It is a two-page poster on a single carrier (SFR), and the authors themselves attribute the 4G result to that carrier running a transparent proxy, so read it as a warning to calibrate on your own population rather than as a general false-positive rate. |
| |
| Earlier and complementary: {[weinberg2018_catch]} used active geolocation to show that 638 of 2,269 advertised proxy locations were false, 401 of them not even on the right continent. Work published after our corpus closes continues this line — Ali et al., [[https://www.ndss-symposium.org/ndss-paper/beyond-rtt-an-adversarially-robust-two-tiered-approach-for-residential-proxy-detection/|"Beyond RTT: An Adversarially Robust Two-Tiered Approach for Residential Proxy Detection"]] (NDSS 2026), is explicitly a response to the fragility above — so check for something newer than 2024 before you build your own. | Earlier and complementary: {[weinberg2018_catch]} used active geolocation to show that 638 of 2,269 advertised proxy locations were false, 401 of them not even on the right continent. The line continues into the corpus's newest venue-year — Ali et al., [[https://www.ndss-symposium.org/ndss-paper/beyond-rtt-an-adversarially-robust-two-tiered-approach-for-residential-proxy-detection/|"Beyond RTT: An Adversarially Robust Two-Tiered Approach for Residential Proxy Detection"]] (NDSS 2026), is explicitly a response to the fragility above — so check for something newer still before you build your own. |
| |
| ===== IP as an Identifier: Four Ways It Breaks ===== | ===== IP as an Identifier: Four Ways It Breaks ===== |
| **Anycast and load balancing.** One address, many hosts, many countries — see above. In the reverse direction, one host answers on many addresses, so counting distinct server addresses over-counts servers. | **Anycast and load balancing.** One address, many hosts, many countries — see above. In the reverse direction, one host answers on many addresses, so counting distinct server addresses over-counts servers. |
| |
| **IPv6 is different, and in the direction people do not expect.** The intuition is that IPv6 clients rotate temporary addresses ([[https://www.rfc-editor.org/rfc/rfc8981.html|RFC 8981]]) and are therefore harder to track. That is true of the interface identifier and false of the assignment: {[padmanabhan2020_dynamips]} found that **IPv6 assignments last //longer// than IPv4 ones — often stable for months — "thereby allowing the possibility of long-term fingerprinting of IPv6 subscribers"**. Aggregate on the /64 or the delegated prefix, not the full address, and do not assume dual-stack clients are equally identifiable on both stacks. Where hardware still derives the interface identifier from a MAC address, the address is //more// identifying than IPv4 ever was: {[rye2023_ipvseeyou]} extracted EUI-64-derived MACs from over 12M routers in 146 countries and geolocated them by correlating with wardriving data, reporting a **median error of 39 metres** — against a median disagreement with MaxMind of 26 km for the same addresses. | **IPv6 is different, and in the direction people do not expect.** The intuition is that IPv6 clients rotate temporary addresses ([[https://www.rfc-editor.org/rfc/rfc8981.html|RFC 8981]]) and are therefore harder to track. That is true of the interface identifier and false of the assignment: {[padmanabhan2020_dynamips]} found that **IPv6 assignments last //longer// than IPv4 ones, often remaining stable for months** — which makes long-term tracking of an IPv6 subscriber //easier//, not harder.((Paraphrased rather than quoted: we verified the paper, venue and topic against Crossref and the authors' own listing, but could not reach a copy to quote the sentence verbatim. Check it before citing the wording.)) Aggregate on the /64 or the delegated prefix, not the full address, and do not assume dual-stack clients are equally identifiable on both stacks. Where hardware still derives the interface identifier from a MAC address, the address is //more// identifying than IPv4 ever was: {[rye2023_ipvseeyou]} extracted EUI-64-derived MACs from over 12M routers in 146 countries and geolocated them by correlating with wardriving data, reporting a **median error of 39 metres**. For the same devices, MaxMind's locations sat a median **26 km** from those wardriving positions — three orders of magnitude apart, from the same input address. |
| |
| <wrap todo>Before you use an IP as a user identifier, write down which of these four you have ruled out and how. If the answer is "none", use it as a network identifier (prefix or ASN) instead, where all four are far weaker.</wrap> | <WRAP todo>Before you use an IP as a user identifier, write down which of these four you have ruled out and how. If the answer is "none", use it as a network identifier (prefix or ASN) instead, where all four are far weaker.</WRAP> |
| |
| ===== A Script ===== | ===== A Script ===== |
| |
| Returns {ip: {asn, prefix, cc, registry, allocated, as_name}}. | Returns {ip: {asn, prefix, cc, registry, allocated, as_name}}. |
| The 'cc' here is the REGISTRY's country for the allocation, which is where | Two separate fields that are easy to conflate, so both are printed: |
| the resource holder is registered -- not where the host is. 1.1.1.1 is | cc -- the country on the ALLOCATION record. Where the resource |
| allocated under APNIC to an Australian registration and is announced by a US | holder is registered, NOT where the host is. 1.1.1.1 is |
| company from every continent. | registered AU, run by a US company, and answered from every |
| | continent. |
| | registry -- which RIR made the allocation (arin/ripencc/apnic/...). |
| """ | """ |
| query = "begin\nverbose\n" + "\n".join(ips) + "\nend\n" | query = "begin\nverbose\n" + "\n".join(ips) + "\nend\n" |
| def main(): | def main(): |
| ap = argparse.ArgumentParser() | ap = argparse.ArgumentParser() |
| ap.add_argument("ips", nargs="+", help="IPv4 addresses, or - to read from stdin") | ap.add_argument("ips", nargs="+", |
| | help="IP addresses, or - to read from stdin. IPv6 works for " |
| | "layers 1 and 3; layer 2 loads IPv4 prefix lists only.") |
| ap.add_argument("--no-geo", action="store_true", | ap.add_argument("--no-geo", action="store_true", |
| help="routing and operator prefixes only; no per-IP API calls") | help="routing and operator prefixes only; no per-IP API calls") |
| routing = cymru_bulk(ips) | routing = cymru_bulk(ips) |
| print(f"layer 1 routing (Team Cymru bulk whois, {len(routing)}/{len(ips)} answered)\n") | print(f"layer 1 routing (Team Cymru bulk whois, {len(routing)}/{len(ips)} answered)\n") |
| print(f" {'IP':<16} {'ASN':<8} {'BGP prefix':<20} {'RIR':<4} {'allocated':<11} AS name") | print(f" {'IP':<16} {'ASN':<8} {'BGP prefix':<20} {'reg-CC':<7} {'RIR':<9} " |
| | f"{'allocated':<11} AS name") |
| for ip in ips: | for ip in ips: |
| r = routing.get(ip) | r = routing.get(ip) |
| print(f" {ip:<16} -- not announced in the global routing table --") | print(f" {ip:<16} -- not announced in the global routing table --") |
| continue | continue |
| print(f" {ip:<16} {r['asn']:<8} {r['prefix']:<20} {r['cc']:<4} {r['allocated']:<11} {r['as_name']}") | print(f" {ip:<16} {r['asn']:<8} {r['prefix']:<20} {r['cc']:<7} {r['registry']:<9} " |
| | f"{r['allocated']:<11} {r['as_name']}") |
| |
| print("\nlayer 2 operator-published prefixes (AWS, Google Cloud, Cloudflare)\n") | print("\nlayer 2 operator-published prefixes (AWS, Google Cloud, Cloudflare)\n") |
| print(f" {len(table)} prefixes loaded") | print(f" {len(table)} prefixes loaded") |
| for ip in ips: | for ip in ips: |
| hit = owner_of(ipaddress.ip_address(ip), table) | addr = ipaddress.ip_address(ip) |
| | if addr.version == 6: |
| | # PREFIX_SOURCES and CLOUDFLARE_V4 are the v4 files. An IPv6 address |
| | # is never "in" an IPv4 network, so without this the answer would |
| | # read as "not a cloud address" when it means "not checked". |
| | print(f" {ip:<16} NOT CHECKED -- only IPv4 prefix lists are loaded") |
| | continue |
| | hit = owner_of(addr, table) |
| if hit: | if hit: |
| net, owner, detail = hit | net, owner, detail = hit |
| layer 1 routing (Team Cymru bulk whois, 5/5 answered) | layer 1 routing (Team Cymru bulk whois, 5/5 answered) |
| |
| IP ASN BGP prefix RIR allocated AS name | IP ASN BGP prefix reg-CC RIR allocated AS name |
| 8.8.8.8 15169 8.8.8.0/24 US 2023-12-28 GOOGLE - Google LLC, US | 8.8.8.8 15169 8.8.8.0/24 US arin 2023-12-28 GOOGLE - Google LLC, US |
| 1.1.1.1 13335 1.1.1.0/24 AU 2011-08-11 CLOUDFLARENET - Cloudflare, Inc., US | 1.1.1.1 13335 1.1.1.0/24 AU apnic 2011-08-11 CLOUDFLARENET - Cloudflare, Inc., US |
| 104.16.132.229 13335 104.16.128.0/20 US 2014-03-28 CLOUDFLARENET - Cloudflare, Inc., US | 104.16.132.229 13335 104.16.128.0/20 US arin 2014-03-28 CLOUDFLARENET - Cloudflare, Inc., US |
| 13.32.99.63 16509 13.32.98.0/23 US 2020-08-05 AMAZON-02 - Amazon.com, Inc., US | 13.32.99.63 16509 13.32.98.0/23 US arin 2020-08-05 AMAZON-02 - Amazon.com, Inc., US |
| 82.220.84.43 9044 82.220.0.0/16 CH 2003-12-02 SOLNET - BSE Software GmbH, CH | 82.220.84.43 9044 82.220.0.0/16 CH ripencc 2003-12-02 SOLNET - BSE Software GmbH, CH |
| |
| layer 2 operator-published prefixes (AWS, Google Cloud, Cloudflare) | layer 2 operator-published prefixes (AWS, Google Cloud, Cloudflare) |
| 8.8.8.8 not in any loaded operator list | 8.8.8.8 not in any loaded operator list |
| 1.1.1.1 not in any loaded operator list | 1.1.1.1 not in any loaded operator list |
| 104.16.132.229 Cloudflare 104.16.0.0/13 | 104.16.132.229 Cloudflare 104.16.0.0/13 |
| 13.32.99.63 AWS 13.32.0.0/15 AMAZON/GLOBAL | 13.32.99.63 AWS 13.32.0.0/15 AMAZON/GLOBAL |
| 82.220.84.43 not in any loaded operator list | 82.220.84.43 not in any loaded operator list |
| Everything this page argues is visible in that one run: | Everything this page argues is visible in that one run: |
| |
| - **Layer 1 never disagrees with itself.** ASN and covering prefix are the same from every source because they are read out of BGP. | - **Layer 1 answered for all five, with no ambiguity to reconcile.** An ASN, a covering prefix, the allocation record and its date, read out of the routing system. There is no confidence interval because nothing is being estimated — which is why nothing below layer 1 gets the same treatment on this page. Note that ''reg-CC'' and ''RIR'' are two different things and neither is a location: ''1.1.1.1'' is ''AU'' under ''apnic'' and is served from everywhere. |
| - **The RIR country is not the host's country.** ''1.1.1.1'' is registered ''AU'' and all four geolocation services dutifully say Australia — for an anycast resolver that answers you from the nearest of hundreds of sites. | - **The RIR country is not the host's country.** ''1.1.1.1'' is registered ''AU'' and all four geolocation services dutifully say Australia — for an anycast resolver that answers you from the nearest of hundreds of sites. |
| - **Country disagreement is not rare.** Two of five addresses, and one of them (the AWS CloudFront edge, DE vs US) is exactly the kind of address a web crawl records by the thousand. If your paper says "//n// % of third-party requests left the EEA", that number moves depending on which vendor you asked. | - **Country disagreement is not rare.** Two of five addresses, and one of them (the AWS CloudFront edge, DE vs US) is exactly the kind of address a web crawl records by the thousand. If your paper says "//n// % of third-party requests left the EEA", that number moves depending on which vendor you asked. |
| ===== Use in Publications ===== | ===== Use in Publications ===== |
| |
| The figures below come from a structured extraction over **4,322 full-text papers** from CCS, IMC, NDSS, PETS, USENIX Security, TheWebConf and IEEE S&P, 2010–2024. Populations are named per table; sentinel values (''not-stated'') are reported as themselves and never counted as answers; and papers, not tuples, are counted. Free-text resource names are folded through an explicit family map with the unmatched residue printed. Method and limitations are at the end of the section. The audit script is ''scripts/report_ip_classification.mjs''. | The figures below come from a structured extraction over **5,859 full-text papers** from CCS, IMC, NDSS, PETS, USENIX Security, TheWebConf and IEEE S&P, 2010–2026 — of which the 2025 and 2026 venue-years are provisional, since CCS and IMC 2026 have not been held and IEEE S&P and WWW 2026 abstracts are not yet in the selection source. Populations are named per table; sentinel values (''not-stated'') are reported as themselves and never counted as answers; and papers, not tuples, are counted. Free-text resource names are folded through an explicit family map with the unmatched residue printed. Method and limitations are at the end of the section. The audit script is ''scripts/report_ip_classification.mjs''. |
| |
| ==== This is an IMC topic ==== | ==== This is an IMC topic ==== |
| |
| **234 papers (5.4% of 4,322) classify an IP address** — that is, carry at least one classification record whose target is an IP address. | **295 papers (5.0% of 5,859) classify an IP address** — that is, carry at least one classification record whose target is an IP address. |
| |
| ^ Venue ^ Papers classifying an IP ^ Papers in corpus ^ Share of venue ^ | ^ Venue ^ Papers classifying an IP ^ Papers in corpus ^ Share of venue ^ |
| | IMC | 109 | 559 | 19.5% | | | IMC | 124 | 638 | 19.4% | |
| | USENIX Security | 46 | 1,117 | 4.1% | | | USENIX Security | 55 | 1,410 | 3.9% | |
| | NDSS | 26 | 419 | 6.2% | | | NDSS | 38 | 701 | 5.4% | |
| | CCS | 20 | 889 | 2.2% | | | CCS | 24 | 990 | 2.4% | |
| | TheWebConf | 18 | 713 | 2.5% | | | TheWebConf | 24 | 843 | 2.8% | |
| | IEEE S&P | 8 | 270 | 3.0% | | | IEEE S&P | 21 | 767 | 2.7% | |
| | PETS | 7 | 355 | 2.0% | | | PETS | 9 | 510 | 1.8% | |
| |
| One paper in five at IMC classifies an IP address; roughly one in forty everywhere else. If you are coming from the web-privacy side, **the methods literature you need is not in the venue you publish in** — that is the practical reason this page exists. | One paper in five at IMC classifies an IP address; about one in thirty across the other six venues (171 of 5,221). If you are coming from the web-privacy side, **the methods literature you need is not in the venue you publish in** — that is the practical reason this page exists. |
| |
| The absolute count grows over time (30 papers in 2010–2013, 59 in 2014–2017, 67 in 2018–2021, 78 in 2022–2024) while the share of the corpus falls from 6.4% to 4.5%, because the corpus itself roughly quadrupled. | The absolute count grows steadily (31 papers in 2010–2013, 61 in 2014–2017, 68 in 2018–2021, 84 in 2022–2024, and 51 in the provisional 2025–2026 window). The //share// of the corpus peaked in the middle and has since flattened: 6.1%, 7.9%, 4.7%, 4.3%, 4.3%. That is the corpus growing around the topic rather than the topic shrinking. |
| |
| ==== How they classify ==== | ==== How they classify ==== |
| |
| ^ Method ^ Papers ^ Share of 234 ^ | ^ Method ^ Papers ^ Share of 295 ^ |
| | Third-party service | 101 | 43.2% | | | Third-party service | 124 | 42.0% | |
| | Curated database | 86 | 36.8% | | | Curated database | 109 | 36.9% | |
| | Heuristic rules | 74 | 31.6% | | | Heuristic rules | 88 | 29.8% | |
| | Blocklist | 11 | 4.7% | | | Blocklist | 16 | 5.4% | |
| | Regex or signature | 10 | 4.3% | | | Regex or signature | 12 | 4.1% | |
| | Supervised ML | 7 | 3.0% | | | Other | 9 | 3.1% | |
| | Manual labelling | 5 | 2.1% | | | Manual labelling | 8 | 2.7% | |
| | | Supervised ML | 7 | 2.4% | |
| | | Graph analysis | 5 | 1.7% | |
| | | Dynamic analysis | 4 | 1.4% | |
| | | Static analysis | 2 | 0.7% | |
| | | LLM | 1 | 0.3% | |
| |
| Shares exceed 100% because a paper can use several. The distribution is the opposite of most classification tasks on this site: IP classification is overwhelmingly a **look-it-up** problem, not a machine-learning one, and supervised ML barely appears. | Shares exceed 100% because a paper can use several. The distribution is the opposite of most classification tasks on this site: IP classification is overwhelmingly a **look-it-up** problem, not a machine-learning one. Supervised ML has not moved at all in absolute terms (7 papers on the old 4,322-paper corpus, 7 on this one), and the ''llm'' method fires exactly **once** — one paper, GPT-4o, in the 2025–2026 window. Whatever LLM classification is doing elsewhere on this site, it has not arrived here. |
| |
| ==== Which resources, folded ==== | ==== Which resources, folded ==== |
| |
| Folded into families, because MaxMind alone appears under **41 distinct spellings** across the two fields we searched ("MaxMind", "Maxmind geoip", "MAXMIND GeoIP2", "Max-Mind GeoIP2 Precision Insights", "GeoIP: MaxMind", …). Folded, **111 papers in the corpus** name it; the commonest single spelling covers 25 of them. **Counting exact strings would understate the field's most-used resource by 77%** — which is why nothing on this page is aggregated by raw string. | Folded into families, because MaxMind alone appears under **50 distinct spellings** across the two fields we searched ("MaxMind", "Maxmind geoip", "MAXMIND GeoIP2", "Max-Mind GeoIP2 Precision Insights", "GeoIP: MaxMind", …). Folded, **134 papers in the corpus** name it; the commonest single spelling covers 28 of them. **Counting exact strings would understate the field's most-used resource by 79%** — which is why nothing on this page is aggregated by raw string. |
| |
| Within the 234 IP-classifying papers specifically, MaxMind is named by 56; the other 55 name it only when describing their own vantage point, which is [[Design:Crawling location]]'s subject rather than this page's. | Within the 295 IP-classifying papers specifically, MaxMind is named by 65; the other 69 name it only when describing their own vantage point, which is [[Design:Crawling location]]'s subject rather than this page's. |
| |
| Grouped by the question the resource answers, families named by two or more papers: | Grouped by the question the resource answers, families named by two or more papers: |
| |
| ^ Question ^ Family ^ Papers ^ Share of 234 ^ | ^ Question ^ Family ^ Papers ^ Share of 295 ^ |
| | Home-grown | Custom heuristic or classifier | 83 | 35.5% | | | Home-grown | Custom heuristic or classifier | 104 | 35.3% | |
| | Where is it? | MaxMind | 56 | 23.9% | | | Where is it? | MaxMind | 65 | 22.0% | |
| | Where is it? | IPinfo | 15 | 6.4% | | | Where is it? | IPinfo | 26 | 8.8% | |
| | Where is it? | IP2Location | 11 | 4.7% | | | Where is it? | IP2Location | 14 | 4.7% | |
| | Where is it? | NetAcuity (Digital Element) | 5 | 2.1% | | | Where is it? | Free geo-lookup APIs (freegeoip, ipstack, HostIP, IPInfoDB…) | 6 | 2.0% | |
| | Where is it? | Free geo-lookup APIs (freegeoip, ipstack, HostIP, IPInfoDB…) | 5 | 2.1% | | | Where is it? | NetAcuity (Digital Element) | 5 | 1.7% | |
| | Where is it? | Unnamed commercial geo database | 4 | 1.7% | | | Where is it? | RIPE IPmap | 5 | 1.7% | |
| | Where is it? | RIPE IPmap | 4 | 1.7% | | | Where is it? | Unnamed commercial geo database | 4 | 1.4% | |
| | Where is it? | Chinese geo databases (Chunzhen/QQWry, AIWEN, QAX…) | 3 | 1.3% | | | Where is it? | Chinese geo databases (Chunzhen/QQWry, AIWEN, QAX…) | 3 | 1.0% | |
| | Where is it? | Quova / Neustar //(historical)// | 2 | 0.9% | | | Where is it? | Quova / Neustar //(historical)// | 2 | 0.7% | |
| | Whose network? | Team Cymru IP-to-ASN | 12 | 5.1% | | | Location reference data //(not IP-based)// | GeoNames, Google Geocoding, Skyhook, WiGLE, Nominatim, Apple WPS | 4 | 1.4% | |
| | Whose network? | RouteViews | 12 | 5.1% | | | Whose network? | Team Cymru IP-to-ASN | 16 | 5.4% | |
| | Whose network? | CAIDA (prefix2as, AS2Org, ITDK) | 10 | 4.3% | | | Whose network? | RouteViews | 14 | 4.7% | |
| | Whose network? | WHOIS / IRR / RIR delegation files | 9 | 3.8% | | | Whose network? | WHOIS / IRR / RIR delegation files (incl. the IANA special-purpose registry) | 13 | 4.4% | |
| | Whose network? | RIPE RIS / RIPEstat / RIPE Atlas | 7 | 3.0% | | | Whose network? | CAIDA (prefix2as, AS2Org, ITDK) | 11 | 3.7% | |
| | Whose network? | Raw BGP feeds and IX data | 6 | 2.6% | | | Whose network? | Raw BGP feeds and IX data | 7 | 2.4% | |
| | Whose network? | PeeringDB | 4 | 1.7% | | | Whose network? | RIPE RIS / RIPEstat / RIPE Atlas | 7 | 2.4% | |
| | Whose network? | ASdb | 3 | 1.3% | | | Whose network? | PeeringDB | 6 | 2.0% | |
| | Known-bad? | Other IP blocklists (DShield, FireHOL, CBL, AbuseIPDB, Honey Pot…) | 25 | 10.7% | | | Whose network? | ASdb | 5 | 1.7% | |
| | Known-bad? | VirusTotal / Google Safe Browsing | 12 | 5.1% | | | Whose network? | pyasn / iptoasn.com | 2 | 0.7% | |
| | Known-bad? | Spamhaus | 10 | 4.3% | | | Known-bad? | Other IP blocklists (DShield, FireHOL, CBL, AbuseIPDB, Honey Pot, SpamCop, SinkDB…) | 33 | 11.2% | |
| | Known-bad? | Chainalysis | 2 | 0.9% | | | Known-bad? | VirusTotal / Google Safe Browsing | 14 | 4.7% | |
| | Router, and which? | bdrmapIT / MAP-IT / MIDAR / Hoiho | 13 | 5.6% | | | Known-bad? | Spamhaus | 12 | 4.1% | |
| | What runs on it? | Censys / Shodan / Nmap / Snort / Suricata | 12 | 5.1% | | | Known-bad? | Chainalysis | 2 | 0.7% | |
| | What kind of host? | Fraud-score APIs (IPQualityScore, IPHub, Scamalytics, VPNAPI, Udger) | 5 | 2.1% | | | Router, and which? | bdrmapIT / MAP-IT / MIDAR / Hoiho | 16 | 5.4% | |
| | What kind of host? | GreyNoise | 3 | 1.3% | | | What runs on it? | Censys / Shodan / Nmap / Snort / Suricata / Criminal IP | 15 | 5.1% | |
| | What kind of host? | IP2Proxy | 2 | 0.9% | | | What kind of host? | Fraud-score APIs (IPQualityScore, IPHub, Scamalytics, VPNAPI, Udger) | 5 | 1.7% | |
| | What kind of host? | Spur | 2 | 0.9% | | | What kind of host? | GreyNoise | 5 | 1.7% | |
| | What kind of host? | MaxMind Anonymous IP / minFraud | 2 | 0.9% | | | What kind of host? | MaxMind Anonymous IP / minFraud | 3 | 1.0% | |
| | | What kind of host? | IP2Proxy | 2 | 0.7% | |
| | | What kind of host? | Spur | 2 | 0.7% | |
| |
| Five more families were named by exactly one paper each (ip-api.com, Akamai EdgeScape, pyasn, a CDN's internal geo, bgp.tools). **The unfolded residue is zero of 363 distinct strings** — every name in the corpus is in one of these families. | Nine more families were named by exactly one paper each (ip-api.com, Akamai EdgeScape, a CDN's internal geo, bgp.tools, DB-IP, a cloud provider's own published address ranges, SPF records, phone-number reference services, and one use of GPT-4o). **The unfolded residue is zero of 443 distinct strings** — every name in the corpus is in one of these families. |
| |
| Read the top row carefully. **The single most common thing a paper does with an IP address is apply a rule it invented itself** (83 of 234), and that family is genuinely heterogeneous: reverse-DNS keyword matching, TTL clustering, hand-built allowlists, custom CGN criteria. That is not a criticism — for many questions no product exists — but it does mean the field has very little shared, comparable IP-classification method, which is the opposite of the situation for, say, [[Design:Website classification]]. | Read the top row carefully. **The single most common thing a paper does with an IP address is apply a rule it invented itself** (104 of 295), and that family is genuinely heterogeneous: reverse-DNS keyword matching, TTL clustering, hand-built allowlists, custom CGN criteria. That is not a criticism — for many questions no product exists — but it does mean the field has very little shared, comparable IP-classification method, which is the opposite of the situation for, say, [[Design:Website classification]]. |
| |
| ==== Almost nobody cross-checks ==== | ==== Almost nobody cross-checks ==== |
| |
| Of the 92 papers that name a geolocation source, **only 12 (13.0%) name more than one.** Given a measured 89.4%-best country accuracy {[gharaibeh2017_look]} and a 34-point spread between two free databases {[darwich2023_replication]}, one source is one opinion. | Of the 114 papers that name a geolocation source, **only 14 (12.3%) name more than one.** Given a measured 89.4%-best country accuracy {[gharaibeh2017_look]} and a 34-point spread between two free databases {[darwich2023_replication]}, one source is one opinion. |
| |
| But cross-checking is a floor, not a ceiling. {[gharaibeh2017_look]}'s own summary of what agreement buys you: | But cross-checking is a floor, not a ceiling. {[gharaibeh2017_look]}'s own summary of what agreement buys you: |
| ==== Almost nobody validates ==== | ==== Almost nobody validates ==== |
| |
| ^ Validation of the IP classification ^ Papers ^ Share of 234 ^ | ^ Validation of the IP classification ^ Papers ^ Share of 295 ^ |
| | Not applicable | 97 | 41.5% | | | Not applicable | 121 | 41.0% | |
| | **None reported** | 80 | 34.2% | | | **None reported** | 99 | 33.6% | |
| | Manual validation | 43 | 18.4% | | | Manual validation | 54 | 18.3% | |
| | Comparison to another method | 39 | 16.7% | | | Comparison to another method | 49 | 16.6% | |
| | Held-out test set | 3 | 1.3% | | | Held-out test set | 3 | 1.0% | |
| | Cross-validation | 1 | 0.4% | | | Cross-validation | 1 | 0.3% | |
| |
| **154 of 234 papers (65.8%) report no validation at all** on any of their IP classifications, and 97 (41.5%) name a ground-truth source. The high //not-applicable// share is partly legitimate — looking up an ASN is not a classifier that needs a test set — but it is also where "we used MaxMind, therefore it is true" hides. | **196 of 295 papers (66.4%) report no validation at all** on any of their IP classification records — that is, every such record is ''none-reported'' or ''not-applicable''. Separately and with a different meaning, 127 papers (43.1%) name a ground-truth source. The high //not-applicable// share is partly legitimate — looking up an ASN is not a classifier that needs a test set — but it is also where "we used MaxMind, therefore it is true" hides. |
| |
| ==== Papers do not say which snapshot they used ==== | ==== Papers do not say which snapshot they used ==== |
| |
| A geolocation database is reissued continuously and MaxMind commits to no fixed cadence — their own documentation tells you to check for a new release periodically through the day. "We used MaxMind" is therefore not a reproducible statement. Of the **111 papers in the whole corpus whose extraction names MaxMind** (in either an IP classification or a vantage-point record), all 111 mention it in their full text, and at most **26 (23.4%)** have any date, month or version token in the same sentence. That is an upper bound twice over: it counts crawl dates and page furniture as if they were database dates, and the unfiltered count of 40 shrinks to 26 only once bibliography entries are dropped. The script is ''scripts/maxmind_version.mjs''. | A geolocation database is reissued continuously and MaxMind commits to no fixed cadence — their own documentation tells you to check for a new release periodically through the day. "We used MaxMind" is therefore not a reproducible statement. Of the **134 papers in the whole corpus whose extraction names MaxMind** (in either an IP classification or a vantage-point record), all 134 mention it in their full text, and at most **36 (26.9%)** have any date, month or version token in the same sentence. That is an upper bound twice over: it counts crawl dates and page furniture as if they were database dates, and the unfiltered count of 52 shrinks to 36 only once bibliography entries are dropped. The script is ''scripts/maxmind_version.mjs''. |
| |
| The standard to copy is the minority that names the file it read. One sentence is enough — this is from Benson et al., //Leveraging Internet Background Radiation for Opportunistic Network Analysis// (IMC 2015): | The standard to copy is the minority that names the file it read. One sentence is enough — this is from Benson et al., //Leveraging Internet Background Radiation for Opportunistic Network Analysis// (IMC 2015): |
| > Since MaxMind updates the database regularly (to reflect changes in the address space), we use the databases produced on August 1, 2012 and August 16, 2013 for the 2012 census and 2013 census periods, respectively. | > Since MaxMind updates the database regularly (to reflect changes in the address space), we use the databases produced on August 1, 2012 and August 16, 2013 for the 2012 census and 2013 census periods, respectively. |
| |
| ==== Crawling papers almost never geolocate anything ==== | ==== Crawling papers rarely name a geolocation service ==== |
| |
| ^ Population ^ N ^ Names a geolocation service ^ Share ^ | This table counts something narrower than its heading might suggest: naming a geolocation service **for the paper's own vantage point**. |
| | Ran an automated web crawl | 859 | 33 | 3.8% | | |
| | Took a measurement from a vantage point | 2,909 | 157 | 5.4% | | |
| |
| Of the 157 papers that name one, MaxMind takes 88 (56.1%), IPinfo 9 (5.7%), IP2Location 6 (3.8%), ip-api.com 6 (3.8%), NetAcuity 5 (3.2%), RIPE IPmap 5 (3.2%). This is a near-monoculture: **one vendor's free tier is the field's de facto ground truth for location**, and it is the one that scored 55% at city level in the only recent head-to-head {[darwich2023_replication]}. | ^ Population ^ N ^ Names a geolocation service for its own vantage point ^ Share ^ |
| | | Ran an automated web crawl | 1,120 | 45 | 4.0% | |
| | | Took a measurement from a vantage point | 3,908 | 194 | 5.0% | |
| | |
| | Crawling papers that classify //observed// addresses are a partly different set: 54 of the 1,120. The union — a crawling paper that geolocates anything at all, its own position or someone else's — is **76 of 1,120 (6.8%)**. |
| | |
| | Of the 194 papers naming a service for their vantage point, MaxMind takes 108 (55.7%), IPinfo 17 (8.8%), IP2Location 8 (4.1%), ip-api.com 7 (3.6%), RIPE IPmap 7 (3.6%), NetAcuity 5 (2.6%). This is a near-monoculture: **one vendor is the field's de facto ground truth for location.** We cannot tell from the extraction how many of those 108 used the free GeoLite2 rather than paid GeoIP2 — the folding does not separate the products, and most papers do not say (see above). Where the free tier //is// what was used, note that it is the one that scored 55% at city level in the only recent head-to-head {[darwich2023_replication]}. |
| |
| ==== Where it is used well in web measurement ==== | ==== Where it is used well in web measurement ==== |
| |
| * {[urban2020beyond]} passively logged DNS responses and used MaxMind to test whether third-party addresses sat in countries without a GDPR adequacy decision, finding "93 % of the analyzed websites embedded third parties that are located in regions that might not be in line with the current legal framework". The claim is a country-level one, which is the level geolocation supports. It also carries a lesson the authors could not have avoided: they define adequate as "part of the Privacy Shield ... and countries part of the European Economic Area", and **Privacy Shield was invalidated by //Schrems II// three months after the paper appeared**. Your geolocation may be right and your classification still expire. Publish the country codes, not only the adequate/non-adequate verdict, so the analysis can be re-run against a later list. | * {[urban2020beyond]} passively logged DNS responses and used MaxMind to test whether third-party addresses sat in countries without a GDPR adequacy decision, finding "93 % of the analyzed websites embedded third parties that are located in regions that might not be in line with the current legal framework". The claim is a country-level one, which is the level geolocation supports. It also carries a lesson the authors could not have avoided: they define adequate as "part of the Privacy Shield ... and countries part of the European Economic Area", and **Privacy Shield was invalidated by //Schrems II// three months after the paper appeared**. Your geolocation may be right and your classification still expire. Publish the country codes, not only the adequate/non-adequate verdict, so the analysis can be re-run against a later list. |
| * {[iordanou2018_tracing]} traced cross-border web tracking and is one of the twelve papers that used more than one geolocation source. | * {[iordanou2018_tracing]} traced cross-border web tracking and is one of the fourteen papers that used more than one geolocation source. |
| * {[kumar2024_choices]} geolocated 4,286 government server addresses with IPinfo, then detected anycast with MAnycast2 and //verified// the country with RIPE Atlas probes, excluding the 72 anycast addresses it could not confirm. 87% of government URLs were served domestically and 98.3% of EU government URLs from inside the EU — figures that only mean something because of the verification step. | * {[kumar2024_choices]} geolocated 4,286 government server addresses with IPinfo, then detected anycast with MAnycast2 and //verified// the country with RIPE Atlas probes, excluding the 72 anycast addresses it could not confirm. 87% of government URLs were served domestically and 98.3% of EU government URLs from inside the EU — figures that only mean something because of the verification step. |
| |
| * **How they were produced.** One structured record per paper, extracted from full text; every tuple carries a verbatim evidence quote and its section, so any figure traces to a sentence. We re-read the quotes behind the accuracy figures against ''paper.cols.txt'' before publishing them. | * **How they were produced.** One structured record per paper, extracted from full text; every tuple carries a verbatim evidence quote and its section, so any figure traces to a sentence. We re-read the quotes behind the accuracy figures against ''paper.cols.txt'' before publishing them. |
| * **What "classifies an IP address" means.** The paper has at least one classification record with target ''ip-address''. A paper that geolocates addresses only to describe its own vantage point is counted in the //vantage// tables instead, not here. | * **What "classifies an IP address" means.** The paper has at least one classification record with target ''ip-address''. A paper that geolocates addresses only to describe its own vantage point is counted in the //vantage// tables instead, not here. |
| * **Folding.** ''scripts/ip_fold.mjs'' maps 363 distinct free-text names onto ordered regex families, specific products before the generic term they contain, and returns anything unmatched. Residue is zero and is printed on every run. The families are ours, not the papers': ''Other IP blocklists'' merges a dozen services that are not interchangeable. | * **Folding.** ''scripts/ip_fold.mjs'' maps 443 distinct free-text names onto ordered regex families, specific products before the generic term they contain, and returns anything unmatched. Residue is zero and is printed on every run — but it was **18 strings** when the corpus grew to 2026 and had to be extended; see [[provenance:design:ip_classification]] for what was added and where each new string went. The families are ours, not the papers': ''Other IP blocklists'' merges a dozen services that are not interchangeable. |
| * **Field stability.** The enums (''method'', ''validation'', ''target'') are reproducible on a repeat extraction to within a few points. Free-text resource names are ~20% stable by exact string, which is why they appear here only as folded rankings. | * **Field stability.** The enums (''method'', ''validation'', ''target'') are reproducible on a repeat extraction to within a few points. Free-text resource names are ~20% stable by exact string, which is why they appear here only as folded rankings. |
| * **Venue coverage.** IEEE S&P is only 43% retrieved (paywall) and is under-represented. EuroS&P, ACSAC, RAID, AsiaCCS, CHI and SOUPS are absent, as are the venues where much of this work actually appears — **PAM, TMA, ANRW, SIGCOMM and ACM CCR are not in the corpus**, and for IP geolocation specifically that is a serious gap. Any claim here is a claim about seven venues. | * **Venue coverage.** Seven venues only — the scope and the selection funnel are on [[literature:corpus]]. For //this// topic the venues where much of the work actually appears are all absent: **PAM, TMA, ANRW, SIGCOMM and ACM CCR are not in the corpus**, and for IP geolocation specifically that is a serious gap. |
| * **The corpus ends in 2024.** The "current in 2026" judgements on this page are ours, checked against vendor and standards documentation, not derived from the corpus. | * **The corpus reaches 2026, but its last two years are provisional** (see [[literature:corpus]]), so a per-period row ending in 2025–2026 rests on fewer papers than a complete window would give. The "current in 2026" judgements on this page are ours, checked against vendor and standards documentation, not derived from the corpus. |
| | * **Every query behind this section, the report script and its unedited output** are on [[provenance:design:ip_classification]]; corpus-level caveats are on [[literature:corpus]]. |
| |
| ===== What to Report ===== | ===== What to Report ===== |
| ===== Open Questions ===== | ===== Open Questions ===== |
| |
| * <wrap todo>**No head-to-head of the geolocation databases on a web-measurement population.** {[gharaibeh2017_look]} used router interfaces (2017), {[darwich2023_replication]} RIPE Atlas anchors (2023), {[nabi2026_lostprefix]} Atlas and Giga (2026). None of them is "the servers a Tranco top-10k crawl connects to" — a population dominated by CDN and cloud edges, which is exactly the population the anycast and datacenter caveats bite hardest on.</wrap> | <WRAP todo> |
| * <wrap todo>**How much does the choice of database move a published cross-border-transfer figure?** Re-running one compliance paper's analysis with four databases would be a small, cheap, useful replication, and the answer is not obviously small: the run above disagreed on country for the AWS edge.</wrap> | * **No head-to-head of the geolocation databases on a web-measurement population.** {[gharaibeh2017_look]} used router interfaces (2017), {[darwich2023_replication]} RIPE Atlas anchors (2023), {[nabi2026_lostprefix]} Atlas and Giga (2026). None of them is "the servers a Tranco top-10k crawl connects to" — a population dominated by CDN and cloud edges, which is exactly the population the anycast and datacenter caveats bite hardest on. |
| * <wrap todo>**Geofeed adoption is not measured for the web.** {[livadariu2024_geofeeds]} gives 1.50% of allocated IPv4 prefixes overall; nobody has asked what share of the //address space a crawl actually touches// has a geofeed, which — given how concentrated that space is on a few large operators — could be much higher or much lower.</wrap> | * **How much does the choice of database move a published cross-border-transfer figure?** Re-running one compliance paper's analysis with four databases would be a small, cheap, useful replication, and the answer is not obviously small: the run above disagreed on country for the AWS edge. |
| * <wrap todo>**No systematic evaluation of the commercial datacenter/VPN/proxy flags against ground truth.** Every paper that uses one takes it on faith, and the run above shows two public DNS resolvers flagged ''is_vpn'' and ''is_abuser''. A labelled benchmark here would be immediately useful and is well within a single student's reach.</wrap> | * **Geofeed adoption is not measured for the web.** {[livadariu2024_geofeeds]} gives 1.50% of allocated IPv4 prefixes overall; nobody has asked what share of the //address space a crawl actually touches// has a geofeed, which — given how concentrated that space is on a few large operators — could be much higher or much lower. |
| * <wrap todo>**No peer-reviewed method for identifying hosting/datacenter address space** beyond the operators' own published lists — which means everything outside the big five clouds is guesswork.</wrap> | * **No systematic evaluation of the commercial datacenter/VPN/proxy flags against ground truth.** Every paper that uses one takes it on faith, and the run above shows two public DNS resolvers flagged ''is_vpn'' and ''is_abuser''. A labelled benchmark here would be immediately useful and is well within a single student's reach. |
| * <wrap todo>**LLMs have reached AS-to-organisation mapping {[selmo2025_borges]} but not IP classification.** We found nothing peer-reviewed applying an LLM to geolocation, host typing or residential/VPN/datacenter labelling as of August 2026 — unlike cookie and policy classification, where LLM methods are now routine. Whether that is because the task has no useful text to read, or because nobody has tried, is an open question.</wrap> | * **No peer-reviewed method for identifying hosting/datacenter address space** beyond the operators' own published lists — which means everything outside the big five clouds is guesswork. |
| * <wrap todo>**No strong successor to {[richter2016_multi]} on CGNAT prevalence.** The best numbers on how much of the client Internet sits behind shared addresses are a decade old, and IPv4 exhaustion has only got worse since.</wrap> | * **LLMs have reached AS-to-organisation mapping {[selmo2025_borges]} but not IP classification.** We found nothing peer-reviewed applying an LLM to geolocation, host typing or residential/VPN/datacenter labelling as of August 2026 — unlike cookie and policy classification, where LLM methods are now routine. Whether that is because the task has no useful text to read, or because nobody has tried, is an open question. |
| | * **No strong successor to {[richter2016_multi]} on CGNAT prevalence.** The best numbers on how much of the client Internet sits behind shared addresses are a decade old, and IPv4 exhaustion has only got worse since. |
| | </WRAP> |
| |
| ===== Related Pages ===== | ===== Related Pages ===== |
| * [[Programming:Traffic files]] — extracting server addresses from a HAR or a packet capture. | * [[Programming:Traffic files]] — extracting server addresses from a HAR or a packet capture. |
| * [[Practices:Ethics]] — client IP addresses are personal data. | * [[Practices:Ethics]] — client IP addresses are personal data. |
| * [[Design:Sampling]] — why an IP is a bad sampling unit. | * [[Design:Sampling]] //(not yet written)// — why an IP is a bad sampling unit. |
| |
| ====== References ====== | ====== References ====== |