Geocoding Scraper — Address ↔ Coordinates (OpenStreetMap)
Pricing
from $0.70 / 1,000 result items
Geocoding Scraper — Address ↔ Coordinates (OpenStreetMap)
Free geocoding for agents and CRMs via OpenStreetMap: address or place → lat/lon with full address breakdown, structured queries (street/city/postcode), reverse geocoding with zoom levels, OSM id lookup, bounded POI search, boundary polygons, multilingual names. Nominatim or Photon (fuzzy).
Pricing
from $0.70 / 1,000 result items
Rating
0.0
(0)
Developer
Samat Makatov
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
15 hours ago
Last modified
Categories
Share
Geocoding Scraper — address ↔ coordinates, POI search, boundaries (OpenStreetMap)
Free, key-less geocoding on OpenStreetMap data for agents, CRMs and data pipelines. Forward (address or place → lat/lon + full address breakdown), structured queries (street/city/postcode fields for messy CRM data), reverse (lat,lon → address at the zoom level you need), OSM id lookup, bounded POI search inside a box, boundary polygons as GeoJSON and names in any language. Two engines: Nominatim (exact, rich) and Photon (typo-tolerant). Worldwide, no API key, no proxy.
Use cases
- CRM address cleaning — geocode 500 customer addresses with
structuredQueries, keepfound,lat/lon, normalizedpostcode/city; withemitNotFound: truerows stay 1:1 with input. - Store / branch enrichment —
reverseZoom: 10turns delivery GPS points into city names for territory reports. - Local lead lists —
queries: ["pharmacy"]+viewbox+bounded: truelists every mapped pharmacy in a district with street and house number;extraTagsadds opening hours and websites where mapped. - Service-area maps —
polygon: truegives district/city boundaries as GeoJSON for coverage checks. - Multilingual labels —
lang: "ru"ornameDetails: truefor Cyrillic / Kazakh / local names on the same object. - Dedupe & entity resolution — stable
osmType+osmId,placeRank,importanceandbestMatchto pick the right candidate among ambiguous names.
Input
| Field | Type | Default | Notes |
|---|---|---|---|
queries | string[] | — | Text address/place → forward; lat,lon → reverse; R62422 / N1,W2 → lookup. |
structuredQueries | object[] | — | { amenity, street, city, county, state, country, postalcode, label } (Nominatim). |
mode | select | auto | auto, forward, reverse, lookup. |
engine | select | nominatim | nominatim or photon (structured & lookup always use Nominatim). |
lang | string | en | Accept-Language, e.g. ru, kk, de, ru,en. Photon: en/de/fr only. |
countryCodes | string | — | kz,ru — ISO-3166 alpha-2, comma-separated. |
viewbox | string | — | minLon,minLat,maxLon,maxLat, e.g. Almaty 76.75,43.15,77.10,43.40. |
bounded | bool | false | Only results inside viewbox (enables area POI search). |
featureType | select | — | country, state, city, settlement. |
layers | multi | — | address, poi, railway, natural, manmade. |
limit | int | 1 | Results per query; Nominatim max 40, Photon max 50. |
reverseZoom | int | 18 | 18 building · 17 street · 16 major street · 14 suburb · 12 town · 10 city · 8 county · 5 state · 3 country. |
addressDetails | bool | true | address object + derived columns. |
extraTags | bool | false | extraTags: website, opening_hours, wikidata, population… |
nameDetails | bool | false | nameDetails: name:ru, name:kk, official_name… |
polygon | bool | false | geojson outline. |
polygonThreshold | number | 0 | Simplification tolerance in degrees (0.005 ≈ city level). |
dedupe | bool | true | Nominatim result dedupe. |
emitNotFound | bool | false | Emit found: false rows to keep 1:1 alignment. Such rows are charged like hits, so this is opt-in; not-found queries are always listed free in SUMMARY.notFoundInputs. |
outputFields | string[] | — | Projection, e.g. ["query","lat","lon","countryCode"]. |
maxItems | int | 10000 | Hard cap. |
osmTag | string | — | Photon: amenity:cafe, shop, !amenity:parking. |
photonLayers | multi | — | Photon: house, street, locality, district, city, county, state, country, other. |
biasLat, biasLon | number | — | Photon: prefer results near this point. |
Reference
Nominatim vs Photon
| Nominatim | Photon | |
|---|---|---|
| Matching | exact tokens, structured fields | fuzzy / prefix (typos OK) |
| Address breakdown | full (address object, 20+ keys) | street, housenumber, district, city, state, postcode, country |
| Reverse | yes, zoom-controlled | yes (nearest object) |
| OSM id lookup, polygons, extra tags, name details | yes | no |
| Language | any (accept-language) | en / de / fr |
| POI filter | layers, featureType, bounded box | osm_tag, layer, bbox, location bias |
| Policy | 1 request/s, identify app (the actor does both) | fair use |
reverseZoom levels
| zoom | returns |
|---|---|
| 3 | country |
| 5 | state |
| 8 | county |
| 10 | city |
| 12 | town / borough |
| 13 | village / suburb |
| 14 | neighbourhood |
| 16 | major streets |
| 17 | major and minor streets |
| 18 | building |
Common type / category values
boundary/administrative (countries, regions, cities, districts) · place/city|town|village|suburb|neighbourhood · highway/residential|primary|… (streets) · building/yes|office|apartments|… · amenity/pharmacy|cafe|bank|school|… · shop/* · tourism/* · office/*. Full tag catalogue: https://wiki.openstreetmap.org/wiki/Map_features
Examples
Batch-geocode CRM addresses (1:1 rows)
{"structuredQueries": [{ "street": "Nauryzbai Batyr 154A", "city": "Almaty", "country": "Kazakhstan", "label": "Kaspi HQ" },{ "street": "Mangilik El 55", "city": "Astana", "country": "Kazakhstan", "label": "Client 2" }],"lang": "ru","emitNotFound": true,"outputFields": ["query", "found", "lat", "lon", "displayName", "postcode", "city", "osmUrl"]}
All pharmacies in a district (POI lead list)
{ "queries": ["pharmacy"], "viewbox": "76.85,43.20,77.00,43.30", "bounded": true, "limit": 40, "extraTags": true, "lang": "ru" }
GPS points → city names for reporting
{ "queries": ["43.2363,76.9457", "51.1282,71.4307", "42.3417,69.5901"], "reverseZoom": 10, "outputFields": ["query", "city", "state", "countryCode"] }
City boundaries as GeoJSON
{ "queries": ["Almaty", "Astana"], "featureType": "city", "countryCodes": "kz", "polygon": true, "polygonThreshold": 0.005 }
Fuzzy search of user-typed input (Photon)
{ "queries": ["Almty Nauryzbai Batyr 154"], "engine": "photon", "limit": 3, "biasLat": 43.24, "biasLon": 76.95 }
Output
{"query": "Nauryzbai Batyr 154A, Almaty","mode": "forward","engine": "nominatim","rank": 1,"bestMatch": true,"found": true,"placeId": 213728564,"osmType": "way","osmId": 51267846,"osmUrl": "https://www.openstreetmap.org/way/51267846","displayName": "Kaspi.kz, 154А, Nauryzbai Batyr Street, Керемет, Көктем, Bostandıq District, Almaty, 050013, Kazakhstan","name": "Kaspi.kz","lat": 43.2399856,"lon": 76.9388247,"category": "building","type": "office","addressType": "building","placeRank": 30,"importance": 0.0000743,"boundingBox": [43.2398836, 43.2400877, 76.9383802, 76.9392699],"country": "Kazakhstan","countryCode": "KZ","state": null,"county": null,"city": "Almaty","district": "Bostandıq District","suburb": "Көктем","postcode": "050013","road": "Nauryzbai Batyr Street","houseNumber": "154А","address": { "building": "Kaspi.kz", "house_number": "154А", "road": "Nauryzbai Batyr Street", "city": "Almaty", "ISO3166-2-lvl4": "KZ-75", "postcode": "050013", "country": "Kazakhstan", "country_code": "kz" },"extraTags": { "building:levels": "7" },"nameDetails": null,"geojson": null,"licence": "Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright","sourceUrl": "https://nominatim.openstreetmap.org/search?q=…","fetchedAt": "2026-09-12T23:50:01.000Z"}
| Field | Description |
|---|---|
query, mode, engine | Input label (or structured label), detected mode, engine used. |
rank, bestMatch, found | 1-based rank; rank 1 is bestMatch; found: false rows carry nulls. |
placeId, osmType, osmId, osmUrl | Stable OSM identity (use osmType+osmId as key; placeId changes between Nominatim imports). |
displayName, name | Full label and object name. |
lat, lon, boundingBox | WGS84; bbox as [minLat, maxLat, minLon, maxLon] (Nominatim order). |
category, type, addressType, placeRank, importance | OSM class/type, address level, 0–1 relevance. |
country…houseNumber | Normalized address columns; raw parts in address. |
extraTags, nameDetails, geojson | Only when requested. |
structured | Echo of the structured query object (structured rows only). |
SUMMARY key-value record: { queries, found, notFound, rows, errors[{query, error}], engine, errorCount, notFoundCount, notFoundInputs[], notFoundRowsEmitted }.
Use it from code / agents
curl -X POST "https://api.apify.com/v2/acts/yadroo~osm-geocode/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-H 'Content-Type: application/json' -d '{"queries":["Almaty, Kazakhstan","43.2363,76.9457"],"lang":"ru"}'
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('yadroo/osm-geocode').call({ structuredQueries: [{ street: 'Nauryzbai Batyr 154A', city: 'Almaty', country: 'Kazakhstan' }] });const { items } = await client.dataset(run.defaultDatasetId).listItems();
from apify_client import ApifyClientclient = ApifyClient(os.environ["APIFY_TOKEN"])run = client.actor("yadroo/osm-geocode").call(run_input={"queries": ["pharmacy"], "viewbox": "76.85,43.20,77.00,43.30", "bounded": True, "limit": 40})items = client.dataset(run["defaultDatasetId"]).list_items().items
MCP: connect https://mcp.apify.com and call the yadroo/osm-geocode tool with the same JSON.
Pricing
Pay per event: $0.001 per run start + $0.001 per result row (not-found rows are included only when you turn emitNotFound on; failed queries are never charged). 100 addresses at limit: 1 ≈ $0.10; a bounded POI search returning 40 rows ≈ $0.041.
Limits & FAQ
- Speed. Nominatim's usage policy allows 1 request per second; the actor enforces a 1.1 s gap, so 300 queries ≈ 5.5 minutes. Split big batches into parallel runs of ≤ 500 queries.
- Accuracy. OSM coverage varies: exact house numbers exist for most cities in Europe/CIS/US; rural addresses may resolve to the street or village (check
addressType/placeRank). - Ambiguity. Use
countryCodes,viewbox,featureTypeorstructuredQueries; inspectimportanceandrankwhenlimit > 1. - Errors. HTTP 429/5xx → 3 retries with backoff; a failing query is listed in
SUMMARY.errors(no row, not charged) and the run continues. Nothing fetched at all → run fails with the reason. - Licence. Data © OpenStreetMap contributors, ODbL — attribution required when you display it; Nominatim results may not be used for autocomplete-as-you-type (use Photon for that).
- Roadmap. Batch mode with your own Nominatim/Photon endpoint, distance/nearest computation between rows.
Made by Yadroo · Sibling actors: open-meteo-weather · ip-intel · public-holidays · krisha-kz