# Geocoding Scraper - Address to Coordinates & Reverse (OSM) (`scrapers_lat/geocoding-nominatim-scraper`) Actor

Forward and reverse geocoding via OpenStreetMap Nominatim. Convert addresses to lat/lon and coordinates back to full structured addresses (house number, road, city, state, postcode, country) in batch. JSON, CSV, Excel.

- **URL**: https://apify.com/scrapers\_lat/geocoding-nominatim-scraper.md
- **Developed by:** [Scrapers Lat](https://apify.com/scrapers_lat) (community)
- **Categories:** Developer tools, Automation, Integrations
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $8.00 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

[![Geocoding Scraper - Address to Coordinates & Reverse (OSM)](https://scrapers.lat/banners/geocoding-nominatim-scraper.png)](https://apify.com/scrapers_lat/geocoding-nominatim-scraper)

## Geocoding Scraper - Address to Coordinates & Reverse (OpenStreetMap)

Turn messy addresses into clean coordinates, and coordinates back into full structured addresses, in batch. This actor is a complete **geocoding** and **reverse geocoding** tool powered by OpenStreetMap data. Give it a list of addresses and get latitude and longitude plus a fully parsed address (house number, road, city, state, postcode, country). Give it a list of coordinates and get the nearest address. It beats a bare lat/lon by returning the full structured address and place metadata, in both directions, over your whole list.

Perfect for **address validation**, **CRM and data enrichment**, **lead list cleanup**, **logistics and routing**, and any **mapping** workflow that needs coordinates or a normalized address.

### What you get

- **Forward geocoding** - convert any address or place name to latitude and longitude.
- **Reverse geocoding** - convert coordinates to the nearest full address.
- **Structured geocoding** - geocode from separate street, city, state, country and postcode fields for cleaner matches.
- **Fully parsed address** - house number, road, neighbourhood, suburb, city, county, state, postcode, country and ISO country code, each in its own field.
- **Place metadata** - display name, category, type, place rank, importance score, bounding box and OSM identifiers.
- **Country and language control** - bias results to specific countries and choose the response language.
- **Honest no-match handling** - unresolved inputs are returned with `matched: false` and are never billed.
- **Place details add-on** - optional extra tags (website, phone, opening hours, Wikidata, Wikipedia), admin level and approximate area.
- Export to **JSON, CSV or Excel**.

### Example output

```json
{
  "input": "Empire State Building",
  "mode": "forward",
  "matched": true,
  "lat": 40.7484421,
  "lon": -73.9856589,
  "displayName": "Empire State Building, 350, 5th Avenue, Koreatown, Manhattan Community Board 5, Manhattan, New York County, New York, 10118, United States",
  "name": "Empire State Building",
  "category": "office",
  "type": "yes",
  "addressType": "office",
  "placeRank": 30,
  "importance": 0.58,
  "boundingBox": [40.7479255, 40.7489585, -73.9865012, -73.9848166],
  "osmType": "way",
  "osmId": "34633854",
  "houseNumber": "350",
  "road": "5th Avenue",
  "neighbourhood": "Koreatown",
  "suburb": "Manhattan",
  "city": "New York",
  "county": "New York County",
  "state": "New York",
  "postcode": "10118",
  "country": "United States",
  "countryCode": "US",
  "website": "https://www.esbnyc.com/explore",
  "phone": "+1-212-736-3100",
  "openingHours": "Mo-Su 08:00-02:00",
  "wikidata": "Q9188",
  "observedAt": "2026-08-17T13:50:00.000Z",
  "error": null
}
```

### Input

| Field | Type | Description |
|---|---|---|
| `mode` | string | `forward` (address to coordinates), `reverse` (coordinates to address) or `structured` (address fields to coordinates). Default `forward`. |
| `queries` | array | Address or place strings to geocode. Used in `forward` mode. |
| `coordinates` | array | List of `{ "lat": number, "lon": number }` objects to reverse-geocode. Used in `reverse` mode. Optional per-item `zoom` (3-18) controls detail level. |
| `structured` | array | List of `{ "street", "city", "state", "country", "postalcode" }` objects. Used in `structured` mode. |
| `countryCodes` | string | Optional comma-separated ISO country codes to bias forward and structured results, e.g. `us,mx`. |
| `language` | string | Preferred language for the address and display name, e.g. `en`, `es`, `fr`. Default `en`. |
| `limit` | integer | Maximum matches to return per forward or structured query (1-50). Default 1. |
| `maxResults` | integer | Optional overall cap on result rows across all inputs. Free plans are capped at 10. |
| `includeDetails` | boolean | Off by default. Enrich each resolved place with extra tags, admin level and approximate area (paid add-on). |

### Output fields

| Field | Description |
|---|---|
| `input` | The original query, coordinate or structured object. |
| `mode` | The mode used for this row. |
| `matched` | Whether a location was resolved. `false` rows are never billed. |
| `lat`, `lon` | Latitude and longitude of the match. |
| `displayName` | Full human-readable address line. |
| `name` | Place name when present. |
| `category`, `type`, `addressType` | OpenStreetMap classification of the place. |
| `placeRank`, `importance` | Ranking and importance score of the match. |
| `boundingBox` | `[south, north, west, east]` bounding box. |
| `osmType`, `osmId` | OpenStreetMap element type and id. |
| `houseNumber`, `road`, `neighbourhood`, `suburb`, `city`, `county`, `state`, `postcode`, `country`, `countryCode` | Flattened structured address components. |
| `website`, `phone`, `openingHours`, `wikidata`, `wikipedia`, `extratags`, `computedAreaSqKm`, `adminLevel` | Extra fields from the place details add-on. |
| `observedAt` | When the record was collected. |
| `error` | Populated only on a fetch failure. |

### Use cases

- **Geocoding** - batch convert address lists to coordinates for maps, geofencing and spatial analysis.
- **Reverse geocoding** - turn GPS pings, store coordinates or device locations into readable addresses.
- **Address validation and cleanup** - normalize and standardize free-text addresses into structured fields with postcode and country code.
- **CRM and data enrichment** - add coordinates and clean address components to customer, lead and account records.
- **Lead list cleanup** - deduplicate and standardize prospect addresses before outreach.
- **Logistics and routing** - geocode delivery and pickup addresses for route planning and territory assignment.
- **Real estate and mapping** - place listings and points of interest accurately on a map.

### Billing

This actor is priced pay per event:

| Event | Price | When it is charged |
|---|---|---|
| `result` | $0.008 | Once per resolved location. No-match and error rows are never charged. |
| `place_details` | $0.008 | Once per place, only when the details add-on is enabled and returns data. |

The place details add-on is optional and off by default. Both events are charged only on genuine success, never on a failed lookup.

### Data source, licensing and rate limits

Location data comes from **OpenStreetMap** via the Nominatim service. OpenStreetMap data is licensed under the **Open Database License (ODbL)** and is free to use, including for commercial purposes, provided you credit **OpenStreetMap contributors**. When you display or redistribute results, include an attribution such as "Data (C) OpenStreetMap contributors, ODbL".

To respect the public usage policy, this actor paces requests to roughly one per second, identifies itself with a descriptive User-Agent, and retries politely on rate limits. Very large batches will therefore take proportionally longer to complete.

# Actor input Schema

## `mode` (type: `string`):

forward = address text to coordinates; reverse = coordinates to address; structured = geocode from separate street/city/state/country/postcode fields.

## `queries` (type: `array`):

List of free-form address or place strings to geocode. Used when mode = forward. Example: \["Empire State Building", "Torre Latinoamericana, CDMX"].

## `coordinates` (type: `array`):

List of {"lat": number, "lon": number} objects to reverse-geocode into addresses. Used when mode = reverse. Optional per-item "zoom" (3-18) controls address detail level.

## `structured` (type: `array`):

List of {"street", "city", "state", "country", "postalcode"} objects. Used when mode = structured. Any subset of fields is allowed.

## `countryCodes` (type: `string`):

Optional comma-separated ISO 3166-1 alpha-2 country codes to bias/limit forward and structured results, e.g. "us,mx".

## `language` (type: `string`):

Preferred language for the returned address/display name (Accept-Language), e.g. "en", "es", "fr".

## `limit` (type: `integer`):

Maximum matches to return per forward/structured query (1-50). Default 1 (best match only).

## `maxResults` (type: `integer`):

Optional overall cap on the number of resolved location rows across all inputs. Free Apify plans are capped at 10.

## `includeDetails` (type: `boolean`):

Off by default. When on, each resolved place is enriched from the Nominatim details endpoint with extra tags (website, phone, opening hours, Wikidata/Wikipedia), admin level and an approximate area. Requires a paid Apify plan. Billed only when details are returned.

## Actor input object example

```json
{
  "mode": "forward",
  "queries": [
    "Empire State Building",
    "Torre Latinoamericana, CDMX"
  ],
  "coordinates": [
    {
      "lat": 48.8584,
      "lon": 2.2945
    }
  ],
  "structured": [
    {
      "street": "350 5th Avenue",
      "city": "New York",
      "state": "NY",
      "country": "USA",
      "postalcode": "10118"
    }
  ],
  "language": "en",
  "limit": 1,
  "includeDetails": false
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "queries": [
        "Empire State Building",
        "Torre Latinoamericana, CDMX"
    ],
    "coordinates": [
        {
            "lat": 48.8584,
            "lon": 2.2945
        }
    ],
    "structured": [
        {
            "street": "350 5th Avenue",
            "city": "New York",
            "state": "NY",
            "country": "USA",
            "postalcode": "10118"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapers_lat/geocoding-nominatim-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "queries": [
        "Empire State Building",
        "Torre Latinoamericana, CDMX",
    ],
    "coordinates": [{
            "lat": 48.8584,
            "lon": 2.2945,
        }],
    "structured": [{
            "street": "350 5th Avenue",
            "city": "New York",
            "state": "NY",
            "country": "USA",
            "postalcode": "10118",
        }],
}

# Run the Actor and wait for it to finish
run = client.actor("scrapers_lat/geocoding-nominatim-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "queries": [
    "Empire State Building",
    "Torre Latinoamericana, CDMX"
  ],
  "coordinates": [
    {
      "lat": 48.8584,
      "lon": 2.2945
    }
  ],
  "structured": [
    {
      "street": "350 5th Avenue",
      "city": "New York",
      "state": "NY",
      "country": "USA",
      "postalcode": "10118"
    }
  ]
}' |
apify call scrapers_lat/geocoding-nominatim-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scrapers_lat/geocoding-nominatim-scraper"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/5UkRJDu8ZF8ueEZGd/builds/cwUANV0MMY50mTiKI/openapi.json
