Accuracy & Relevance Scoring
CSV2GEO returns an accuracy_score (0 – 1) and an accuracy label on every geocode and reverse-geocode result. This page explains exactly how those values are computed, what each label means, and how to use them in your application.
We split scoring into two halves because they answer different questions:
- Forward geocoding (address → coordinates): the score reflects which search phase produced the hit and whether the returned address matches the input components you gave us.
- Reverse geocoding (coordinates → address): the score reflects how far the returned address point is from your pin. Closer = higher.
Quick reference
accuracy label | Meaning | Typical accuracy_score |
|---|---|---|
rooftop | Exact match on a known address point | 0.95 – 1.00 |
building | Reverse hit on the nearest building, 30 – 200 m off the pin | 0.90 |
street | Forward: street-level match (no exact house number) · Reverse: 200 – 500 m off | 0.70 – 0.90 |
interpolated | Position interpolated along a road segment | 0.75 – 0.90 |
postcode | Forward: postcode anchor match · Reverse: 500 – 1500 m off (rural) · UK Code-Point | 0.50 – 0.80 |
centroid | Returned the centroid of a postcode, city, or division | 0.50 – 0.65 |
building (reverse) | 30 – 200 m off pin | 0.90 |
city | Reverse: > 1500 m off (very rural) — town-level only | 0.30 |
approximate | State-anchored fallback when no city match existed | 0.30 – 0.55 |
Forward Geocoding (address → coordinates)
Forward geocoding runs through a series of search phases, anchored by the strongest geographic signal in your query. The score is calibrated to the phase that produced the result.
Phase-based base score
| Search phase | What we matched | Base accuracy_score | accuracy label |
|---|---|---|---|
| 1a | country + postcode + street + house number | 1.00 | rooftop |
| 1b | country + postcode + street | 0.90 | interpolated |
| 1c | country + postcode + house number | 0.75 | centroid |
| 1d | country + postcode only | 0.65 | centroid |
| 2a | country + city + street + house number | 0.95 | rooftop |
| 2b | country + city + street | 0.85 | interpolated |
| 2c | country + split city + street + house number | 0.75 | interpolated |
| 2.5 | country + state + house number + street | 0.55 | approximate |
| 2.5 | country + state + street | 0.40 | approximate |
| 3a | country + street + house number (no geographic anchor) | 0.45 | approximate |
| 3b | country + street only | 0.30 | approximate |
| divisions fallback | city centroid (when no street match found) | 0.50 | centroid |
| UK Code-Point | postcode centroid (UK only, free Ordnance Survey data) | 0.80 | postcode |
Cross-validation penalty
The base score is multiplied by penalty factors when the returned address disagrees with the input components you supplied:
| Field that disagrees | Multiplier applied |
|---|---|
| Postcode (strongest disagreement signal) | × 0.5 |
| State / region | × 0.4 |
| City | × 0.7 |
Empty input fields are skipped — if you didn't supply a postcode, we can't say the result's postcode is wrong.
If cross-validation pulls the score below 0.85, the accuracy label is downgraded to approximate so downstream consumers don't mistake a flagged result for a clean match.
Why this exists: before cross-validation was added, every result was hard-coded to 1.0 / rooftop regardless of agreement. The motivating bug was a query for Tuttle, OK 73089 silently resolving to Wilson, OK 73463 (~100 mi away) while the API still reported a full match.
Reverse Geocoding (coordinates → address)
Reverse geocoding has a single search phase (a geo-spatial nearest-neighbor query). The score reflects how far the returned address point is from your query pin.
Distance bands
| Distance from pin | accuracy label | accuracy_score |
|---|---|---|
| ≤ 30 m | rooftop | 1.00 |
| 30 – 200 m | building | 0.90 |
| 200 – 500 m | street | 0.70 |
| 500 – 1500 m | postcode | 0.50 |
| > 1500 m | city | 0.30 |
Boundaries are inclusive on the lower edge — a hit at exactly 30.0 m is building (0.90), and exactly 200.0 m is street (0.70).
Why distance bands, not a continuous formula
The thresholds anchor to the canonical lat/long decimal-precision ladder:
| Decimals | Approximate accuracy | Maps to band |
|---|---|---|
| 4 – 5 | ~10 m | rooftop |
| 3 | ~110 m | building (the nearest known address is within a street-width of your pin) |
| 2 | ~1.1 km | postcode (same neighbourhood) |
| 1 | ~11 km | city (town-level only) |
This is the same ladder every major geocoder uses internally; we surface it as a public, predictable enum so you can compare values across calls without re-deriving them from raw distance.
The radius query parameter
By default, reverse geocoding only returns results within 100 m of your pin. This preserves the legacy behavior of the endpoint — callers who don't pass radius see no change in coverage.
You can opt into a wider search via the ?radius= query parameter (in metres):
GET /v1/reverse?lat=46.49125&lng=-120.395&radius=1000&api_key=geo_live_...| Parameter value | Behavior |
|---|---|
| Omitted | Default 100 m cap (legacy behavior) |
| 1 – 1500 | Used as the max search radius |
| > 1500 | Clamped to 1500 m |
| 0 or negative | Falls back to default (100 m) |
| Malformed (non-numeric) | Falls back to default (100 m) |
Why 1500 m as the max: at greater distances the result has degraded to "town centroid only," which is what the Administrative Divisions and Places APIs are designed for.
Source Attribution
Every result includes a source field telling you where the underlying data came from. Our scoring methodology only applies to data we control. For supplier-sourced rows, we preserve the supplier's own confidence value as-is.
source value | Origin | Scoring on this source |
|---|---|---|
overture | Overture Maps Foundation — our primary address dataset | Forward: phase-based + cross-validation · Reverse: distance bands (see above) |
here | HERE Geocoder, called as a forward-geocoding fallback when Overture misses. Results are imported into our address store with their confidence preserved. | Supplier confidence preserved as-is. We do not re-score HERE results. |
google | Google Geocoding, called as a final forward fallback. Results imported with their confidence preserved. | Supplier confidence preserved as-is. We do not re-score Google results. |
divisions | Our own divisions collection (Overture-derived city / region polygons) — used as a city-centroid fallback when no street match is found | Fixed 0.50 (centroid) |
maxmind-geolite2 | MaxMind's free IP-geolocation database, used only on /v1/ip | Not applicable — the /v1/ip endpoint has its own confidence model |
No HERE or Google fallback exists on reverse geocoding. Reverse hits are always source: overture (or empty).
Worked Examples
Forward — clean rooftop match
GET /v1/geocode?q=1600+Pennsylvania+Ave+NW,+Washington,+DC+20500&country=US{
"results": [{
"formatted_address": "1600 PENNSYLVANIA Avenue Northwest, Washington, DC 20500, US",
"accuracy": "rooftop",
"accuracy_score": 1.0,
"source": "overture",
"rank": { "confidence": 1.0, "match_type": "full_match" }
}]
}Phase 1a match (postcode + street + house number all anchored). No cross-validation penalty.
Forward — postcode supplied, city wrong
GET /v1/geocode?q=123+Main+St,+Wilson,+OK,+73089&country=USIf 73089 is actually Tuttle and Main St in Tuttle resolves cleanly, the returned address will show city=Tuttle (not Wilson). Cross-validation detects the city disagreement:
base score: 1.00 (Phase 1a)
city penalty: × 0.7 (returned "TUTTLE" ≠ input "Wilson")
final: 0.70 → label downgrades to "approximate"The result is still returned (in case the customer mis-typed the city), but the score makes the disagreement explicit.
Reverse — urban rooftop
GET /v1/reverse?lat=38.8977&lng=-77.0365{
"results": [{
"formatted_address": "1600 PENNSYLVANIA Avenue Northwest, Mall/East Potomac Park, ...",
"accuracy": "rooftop",
"accuracy_score": 1.0,
"source": "overture"
}]
}Pin lands on an indexed address point. Distance ≤ 30 m → rooftop.
Reverse — rural pin, default radius
GET /v1/reverse?lat=46.49125&lng=-120.395{ "results": [] }The nearest known address is 577 m away. The default 100 m cap returns nothing.
Reverse — rural pin, widened radius
GET /v1/reverse?lat=46.49125&lng=-120.395&radius=1000{
"results": [{
"formatted_address": "165 East PARKER HEIGHTS Road, WAPATO, WA 98951, US",
"accuracy": "postcode",
"accuracy_score": 0.5,
"source": "overture"
}]
}577 m distance lands in the postcode band → 0.50. You're getting the nearest known address in the same neighbourhood, not the exact parcel at the pin.
How to use accuracy_score in your application
| Threshold | Behavior |
|---|---|
≥ 0.85 | Safe to use as a confirmed match. Show on maps without disclaimer. |
0.60 – 0.84 | Useful, but flag it — show "approximate" indicator in UI, ask user to confirm. |
0.40 – 0.59 | Best-effort. Use for analytics / aggregation, not for "this is your delivery address." |
< 0.40 | Treat as a hint, not an answer. Often city-level only. |
Combine the score with the accuracy label for richer logic:
if result["accuracy"] == "rooftop" and result["accuracy_score"] >= 0.95:
# Pin on map, no disclaimer
...
elif result["accuracy"] in ("building", "street", "interpolated"):
# Show with "approximate" badge
...
elif result["accuracy"] in ("postcode", "centroid", "city", "approximate"):
# Aggregate-only, don't pin
...What we explicitly don't claim
- Per-component confidence. Geoapify and HERE expose separate
confidence_street_level,confidence_city_level, etc. We currently emit a single overallaccuracy_scoreonly. - A first-class
match_levelfield. Ouraccuracylabel combines precision (rooftop vs approximate) with granularity (building vs postcode vs city). Major providers separate these into two fields. We may split them in a future API version. - Rooftop precision for hits beyond 30 m on reverse. Before May 2026 the API returned
accuracy_score: 1.0for any reverse hit within 100 m. That was overstated. The new distance bands correct it — a hit at 50 m now scoresbuilding / 0.90, notrooftop / 1.00. - Re-scored supplier results. HERE and Google returns carry their original confidence values, computed by their own matching logic. We expose them as-is and do not re-derive them. Compare scores across
sourcevalues with that in mind.
Changes
- 2026-05-23 — Reverse geocoding gained distance-aware scoring (
rooftop/building/street/postcode/citybands). Added?radius=parameter (default 100, max 1500). Default search-cap behavior unchanged; the per-hit score now reflects actual distance rather than hard-coded 1.0. - Earlier 2026 — Forward
MatchStrength+crossValidateintroduced after the Tuttle / Wilson OK misroute. Replaced uniform1.0 / rooftopwith phase-aware scoring.