Purpose
Given a latitude/longitude pair, finding the H3 cell that contains it is a deterministic, exact geometric operation — the H3 grid partitions the sphere, so every point lies in exactly one cell at a given resolution (ignoring the measure-zero case of a point exactly on a cell boundary). What is not exact, and what this page is actually about, is the coordinate itself: POI locations, geocoded addresses, and device pings all carry uncertainty that the point-to-cell step inherits silently unless it is tracked explicitly.
Source geometry and destination geometry
Source geometry is one of poi (a point of interest with a claimed
location), address (a mailing or street address prior to geocoding), or
device_ping (a single observed lat/lng with a timestamp, typically from a
mobile SDK or bid-stream signal). Destination geometry is a single H3 cell,
or an h3_cell_set when a set of points is aggregated.
Exactness class
Point-to-cell containment is exact: latLngToCell returns the one cell
whose boundary contains the given point, with no approximation in the
containment test itself. This page's badge describes the conversion step,
not the input — a device ping accurate to only 500 meters is still mapped
to exactly one cell, but that cell may not be the cell the true device
location would have produced.
Containment rule and boundary behavior
A point belongs to the unique cell whose polygon boundary contains it under
H3's standard point-in-polygon test. Points falling exactly on a shared edge
or vertex between cells are resolved by H3's internal tie-breaking rather
than by any caller-visible rule; do not rely on which side a boundary point
resolves to being stable across H3 library versions. This matters in
practice for device_ping data snapped to a grid (see rounded coordinates,
below) where a large share of points can land precisely on cell boundaries
rather than being uniformly distributed within cells.
Resolution behavior
Resolution does not change whether the operation is exact — it changes how
much a fixed amount of coordinate uncertainty matters. At res 6 (average
cell edge length near 3.2 km), a 50-meter GPS error essentially never moves
a point to a different cell. At res 10 (edge length near 65 m), the same
50-meter error frequently does. The right rule of thumb: choose a resolution
whose cell diameter is large relative to the stated accuracy radius of the
source, or explicitly report the probability the true point falls in a
neighboring cell (via gridDisk around the assigned cell).
Units and CRS
Input must be EPSG:4326 decimal degrees, latitude first. Accuracy radius, where available, is reported in meters and should be treated as a 1-sigma or CEP50 radius depending on the source's own documentation — mobile SDKs and geocoders rarely agree on which, and mixing them without checking produces confidence estimates that are wrong by a factor of two or more.
Algorithm
import { latLngToCell, cellToLatLng, gridDisk } from "h3-js";
const cell = latLngToCell(lat, lng, resolution);
// Report neighbor cells the true point could plausibly occupy,
// given a stated accuracy radius larger than the cell's own scale.
const candidateNeighbors = gridDisk(cell, 1);
The same conversion with the Python bindings (h3-py v4):
import h3
cell = h3.latlng_to_cell(lat, lng, res)
# Report neighbor cells the true point could plausibly occupy,
# given a stated accuracy radius larger than the cell's own scale.
candidate_neighbors = h3.grid_disk(cell, 1)
# Cap the usable resolution to the coordinate's own precision: if lat/lng
# were truncated (see rounded-coordinates below), h3.get_resolution(cell)
# should not be trusted as more precise than the source data actually is.
assigned_resolution = h3.get_resolution(cell)
The tested reference implementation for this conversion is the TypeScript
in lib/ (via h3-js); the Python above calls the equivalent h3-py
functions directly, since point-to-cell containment has no library-specific
logic to reproduce.
Parameters
Resolution, and — where the source provides it — an accuracy radius in meters used only for downstream uncertainty reporting, never to alter the containment result itself.
Outputs
cell_id at the stated resolution, the original coordinate pair for
audit, and, when available, the source's own accuracy radius and
observation timestamp carried through unchanged.
Quality metrics
Point conversions do not have a coverage_ratio in the polygon sense.
Instead track: the fraction of points whose accuracy radius exceeds the
chosen cell's edge length (a proxy for how often the "true" cell may differ
from the assigned one), and the duplicate rate — the fraction of
observations sharing an identical coordinate pair, timestamp, and source id.
Edge cases
Axis-order reversal is the most common silent failure: many formats list
longitude first, and swapping lat/lng produces a coordinate that is often
still a valid point on Earth — frequently landing in the ocean or another
continent — with no error thrown. Always validate that latitude falls in
negative-90 to 90 and longitude in negative-180 to 180, and where both are
in range, cross-check against an expected bounding region rather than
trusting field order. Rounded coordinates — device pings or POI feeds
truncated to 2-3 decimal places for privacy or storage reasons — can
introduce error of 100 meters to over 1 km depending on latitude, which is
routinely larger than a res-9 or res-10 cell; treat any coordinate with
suspiciously round decimal digits as lower-resolution input and cap the H3
resolution used for it accordingly, rather than polyfilling it as if it
were survey-grade. Geocoding uncertainty applies to address inputs before
they become points at all: rooftop, parcel-centroid, street-segment
interpolation, and ZIP-centroid geocodes carry radically different implied
accuracy (meters versus kilometers), and the geocode tier should be
recorded alongside the resulting cell. Duplicate observations — the same
device or POI reported multiple times at the same or near-identical
coordinate within a short window — inflate density counts if not
deduplicated by source id and timestamp window before aggregation into a
cell-level count.
Assumptions and limitations
This conversion assumes the input coordinate is the caller's best available estimate of a real-world location; it does not attempt to detect or correct for measurement error, only to propagate accuracy metadata alongside the assigned cell where it exists. Stale POIs (a business location that closed or moved but remains in a feed) are a data-freshness problem, not a geometric one — no adjustment of resolution or containment rule corrects for a POI at the wrong address; that requires refreshing the source rather than tuning this conversion.
