By Ether DataRequest data sample
All sections

IP Lookup To H3

An IP geolocation lookup is not a point — it is a disk at a stated confidence, and the honest conversion is a weighted cell crosswalk with a vintage, not latLngToCell on the center.

stable8 min read
Source geometry
ip_block, device_ping
Destination geometry
h3_cell_set
approximate

Purpose

The dominant location signal on the open web is an IP geolocation lookup: a center coordinate plus an accuracy radius at a stated confidence — commonly the radius within which the vendor holds roughly 67% confidence the device sits. At advertising-relevant resolutions that disk spans dozens to hundreds of cells. The near-universal practice of collapsing the lookup to its center and calling latLngToCell is a silent center-mode conversion applied to an input that is not a point, and it discards exactly the information that makes the signal usable: how much of the device's probability mass actually falls inside any geography you care about.

This page defines the honest conversion: the lookup becomes a weighted cell set{cell, p} rows with probability mass in place of area fraction — resolved from a versioned crosswalk (the vendor's database release is the vintage). Both objects already exist elsewhere in this knowledge base; nothing here is new machinery, only the refusal to pretend a disk is a point.

Source geometry and destination geometry

Source geometry is ip_block (a network block resolved through a geolocation database, carrying accuracy_radius, confidence_convention, db_vintage, and source) or a device_ping whose locationSource is IP rather than GPS. Destination geometry is an h3_cell_set whose weights are probability masses summing to at most 1, with the remainder carried explicitly as an unlocated residual.

Exactness class

Approximate, at three layered points: the vendor's center estimate is frequently a registry or population centroid, not an observation — a correctly sized circle around a systematically displaced point; the declared radius is a model claim whose honesty is the vendor's calibration, not a measurement you can audit from the lookup alone; and the kernel spreading mass over the disk is itself a modeling choice. None of this is repaired by higher H3 resolution — see resolution behavior below.

The two required declarations before any mass is computed

Confidence convention. Vendors and SDKs do not agree on what a radius means. A radius at ~67% confidence (the 1σ-equivalent form IP vendors publish), a CEP50 median radius, and a raw Rayleigh σ differ by factors large enough that pooling them unconverted produces containment estimates wrong by a factor of two or more. The convention is mandatory metadata; normalize every radius to one confidence level before anything downstream touches it.

Database vintage. Geolocation databases release weekly. The release you resolved against is a crosswalk vintage exactly like a boundary-file vintage: it carries valid_from/valid_to, joins across a vintage gap are refused, and — the sharpest consequence — the vintage used for experiment match decisions is pinned for the assignment period, because a block whose estimate crosses an arm boundary between releases flips every device behind it between arms mid-flight (see the vintage-arm-flip edge case).

Vendors that publish confidence instead of a radius

Not every geolocation vendor declares uncertainty as a radius. The second form in production is per-field confidence: a per-lookup probability that the device is in a named country, region, city, or postal area, with no radius at all. The same {cell, p} shape carries it — the declared confidence spreads over the named region's cells through the standard weighted crosswalk (area- or population-weighted, declared), and the remainder is the same explicit unlocated residual the disk form carries. Radius vendors and confidence vendors declare differently and interoperate identically; every match rule, disposition, and contamination computation below consumes the two without knowing which vendor shape produced them. The reference implementation exposes this as region_confidence_to_cells beside disk_to_cells.

Match rules: the four containment modes over probability mass

The four containment modes generalize from area measure to probability measure and become the match rules a delivery platform must declare:

Area modeProbabilistic match rule
centerThe point estimate falls in a declared cell. Today's silent default, now nameable and auditable.
fullThe entire declared-confidence disk lies inside the declared set.
intersectAny probability mass touches the declared set.
thresholdP(true location ∈ declared set) ≥ p, with p declared.

threshold is the workhorse. The unlocated residual (the mass outside the declared-confidence disk) is never credited to a declared set under any rule, and every match decision reports expected_overreach = 1 − in_set_mass — matched or not — so probabilistic spill is a declared quantity rather than a discovered one.

Resolution behavior

Resolution does not buy precision here; it only changes how many cells the disk smears across. A 1.2 km radius at res 8 spans a handful of cells; at res 10 it spans hundreds, each carrying a sliver of mass that no downstream consumer can act on. Cap the indexing resolution to the signal's own accuracy — a disk that would touch more cells than a sane enumeration bound is a resolution mismatch, not a bigger computation. The right failure mode is an error advising a coarser resolution, not a silent grind.

Units and CRS

Center in EPSG:4326 decimal degrees; radius in meters, normalized through the declared convention before use; mass dimensionless in [0, 1]. All disk and cell areas geodesic, in square metres — a probability computed as a ratio of planar degree-areas drifts with latitude.

Algorithm

// Uniform kernel: declared mass spread over the confidence disk;
// the tail (1 - confidence) is an explicit unlocated residual.
import { ipDiskToCells } from "@/lib/h3/ip";

const dist = ipDiskToCells(lat, lng, radiusM, {
  resolution: 8,
  confidence: 0.67,
  convention: "confidence", // or "cep50" | "one_sigma" — normalized first
});
// dist.cells: [{ cell, p }], sum(p) ≈ 0.67; dist.residualMass ≈ 0.33

const inSetMass = dist.cells
  .filter(({ cell }) => declaredSet.has(cell))
  .reduce((s, { p }) => s + p, 0);
const matched = inSetMass >= 0.6; // threshold rule, p declared

The same conversion in Python (mirroring the tested reference implementation):

# Reference: src/adcp_mcp/conversion/ip_crosswalk.py (maraketa)
dist = disk_to_cells(lat, lng, radius_m, resolution=8,
                     confidence=0.67, convention="confidence",
                     kernel="uniform")
decision = match(dist, declared_cells, rule="threshold", threshold=0.6)
# decision.in_set_mass, decision.expected_overreach — reported either way

The uniform kernel needs zero vendor cooperation: center + radius + convention is enough, and it is conservative by construction because the tail is never assigned to any cell. A vendor-published empirical distribution per block is strictly better and slots into the same {cell, p} shape — that is a supplied declaration, not a free-rail computation (see the extension points page).

Parameters

Resolution (capped to accuracy), confidence convention (mandatory), kernel (uniform default, gaussian optional), match rule and threshold where applicable, and the database vintage carried on every output row.

Outputs

Weighted {cell, p} rows at the stated resolution, the explicit residual_mass, the center cell (for auditing the center-rule counterfactual), and the crosswalk provenance: source, vintage, valid_from/valid_to, confidence convention.

Quality metrics

The polygon-era coverage_ratio has no meaning here; the native metric is expected overreach1 − mean in-set mass across matched lookups — computable before delivery from the declared distribution and verifiable after against any ground-truth sample. Track alongside it: the fraction of lookups whose accuracy radius exceeds the cell scale (same proxy as for device pings), the modal-cell share (how much mass the top cell carries — a distribution whose top cell carries ~1.0 is a point pretending to be a disk), and the forecast-versus-realized overreach gap, which is a running calibration audit of the supplying vendor.

Edge cases

Centroid pile-up is the signature failure: assigning each lookup to its most-likely cell stacks every ambiguous impression onto vendor fallback centroids — city centers, ZIP centroids — manufacturing density spikes uncorrelated with population or POI mass; apportion fractionally instead, and never report modal-cell rows as measured. Convention mismatch silently halves or doubles containment when ~67% and CEP50 radii are pooled unconverted. Vintage arm-flips are the experimentation-critical case: pin the vintage per assignment period, re-pin only at period boundaries, and count, report, and exclude flipped blocks. And the matching-semantics rule from the advertising page still binds — IP-derived location is never physical_presence, whatever the radius says; a tight radius is a precision claim about a signal that fails on the semantic axis first.

Assumptions and limitations

This conversion assumes the vendor's declared radius is honest at the declared confidence. That assumption is checkable only through a calibration attestation — measured containment of the declared disk against a GPS ground-truth sample, per country or region — and a declared radius without one is a claim, not a bound. The uniform and Gaussian kernels are models; both are isotropic, and real IP error follows ISP infrastructure, which is anisotropic. The framework's protection against both gaps is the same: expected overreach is declared up front and audited against realized delivery, so a miscalibrated vendor is detected after one flight rather than trusted indefinitely.

Illustration — the disk is the datum, not the point

The containing cell (cyan) is exact for the center coordinate, but the accuracy disk touches many plausible cells (amber) — at IP scale (hundreds of meters to kilometers) the amber set is the honest object, weighted by probability mass.
Rendered from the tested conversion code · The containing cell (cyan) is exact for the center coordinate, but the accuracy disk touches many plausible cells (amber) — at IP scale (hundreds of meters to kilometers) the amber set is the honest object, weighted by probability mass.

Edge cases affecting this page

Point To H3SourceH3Point-Radius To H3SourceH3Advertising Geographic Matching SemanticsAdvertising & measurementCommercial Extension PointsConceptual model