# OpenStreetMap Scraper - Places & Business Data (`dataio/openstreetmap-overpass-poi-scraper`) Actor

Extract local businesses and points of interest from OpenStreetMap (Overpass API) by place name and category: name, phone, email, website, address and coordinates. An open-data alternative to Google Maps for lead lists and location data. No login, no proxies.

- **URL**: https://apify.com/dataio/openstreetmap-overpass-poi-scraper.md
- **Developed by:** [Tom Awake](https://apify.com/dataio) (community)
- **Categories:** Lead generation, MCP servers
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 places

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/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### What does OpenStreetMap Scraper do?

Extract local businesses and places from OpenStreetMap **by place name and
category** — with phone numbers, emails, websites, opening hours, addresses
and coordinates.

**No login. No cookies. No proxies. No API keys. Nothing to break.**

Type `Bordeaux, France` and `restaurants`. That is the whole configuration.

### A legal alternative to scraping Google Maps

Scraping Google Maps breaks Google's terms of service. This Actor reads
**OpenStreetMap**, an open database, through the public Overpass and
Nominatim APIs — access that is offered, documented and free. There is no
anti-bot system to defeat, no account to get suspended, and no proxy bill.

The data is licensed **ODbL 1.0**: you may use it commercially, including in
a lead list or a product, provided you attribute OpenStreetMap. Every row
carries an `attribution` field so the requirement travels with the data. If
you redistribute a *derived database*, ODbL's share-alike terms apply to
that database — worth knowing before you resell the raw export.

### What makes this one different

**It takes a place name, not a bounding box.** Overpass needs
`(44.81,-0.63,44.91,-0.53)` and `amenity=restaurant`. That is why most
OpenStreetMap tools go unused. Here you type a town and pick from 82
categories.

**It queries the real administrative area, not a rectangle.** Asking for
"Gironde" by bounding box means querying the Atlantic Ocean: measured, 64
near-empty requests and over ten minutes. This Actor resolves the
département's actual boundary and returns 488 pharmacies in about four
seconds.

**It returns the most complete records first.** Overpass emits points before
buildings, so a capped run would hand you an arbitrary, biased slice. Rows
are ranked by how contactable they are before the limit applies. Measured on
Bordeaux restaurants, asking for 120 out of 835:

| | Naive order | This Actor |
|---|---|---|
| With a phone number | 47 % | **100 %** |
| With a website | 47 % | **99 %** |
| With a street address | — | **97 %** |

**It includes places mapped as buildings.** Many POIs are areas, not points.
Querying nodes only silently loses them — 37 of 835 Bordeaux restaurants.

### Output

One row per place, deduplicated.

| Field | Example |
|---|---|
| `name` | La Tupiña |
| `category` | restaurants |
| `phone` | +33 5 56915637 |
| `email` | contact@latupina.com |
| `website` | http://www.latupina.com/ |
| `address` | 6 Rue Porte de la Monnaie |
| `street`, `housenumber`, `postcode`, `city`, `country` | split for mail merge |
| `latitude`, `longitude` | 44.8335, -0.5658 |
| `openingHours` | `Mo-Su, PH 11:00-23:00` |
| `cuisine`, `brand`, `operator`, `wheelchair` | when mapped |
| `siret`, `siren` | French business identifiers, when mapped |
| `osmType`, `osmId`, `osmUrl` | provenance, to verify any row |
| `attribution` | © OpenStreetMap contributors, ODbL 1.0 |

French places often carry `ref:FR:SIRET` and `ref:FR:SIREN`, which lets you
join the export straight to the French company register. Measured on
Bordeaux restaurants: 84 of the first 120 rows carried a SIRET.

### Input

```json
{
  "location": "Bordeaux, France",
  "category": "restaurants",
  "maxItems": 500,
  "requirePhone": false
}
```

| Field | Default | Notes |
|---|---|---|
| `location` | `Bordeaux, France` | Town, city, district, département, region or country |
| `category` | `restaurants` | 82 presets — see below |
| `maxItems` | `500` | Up to 50,000 |
| `requirePhone` | `false` | Keep only places with a phone number |
| `requireWebsite` | `false` | Keep only places with a website |
| `boundingBox` | — | `[south, west, north, east]`, overrides `location` |
| `center` + `radiusMeters` | — | Circle around a point |
| `customTags` | — | `["amenity=restaurant"]` for tags with no preset |

#### Categories

**Food and drink** — restaurants, fast-food, cafes, bars, nightclubs,
bakeries, caterers

**Accommodation** — hotels, guest-houses, campsites

**Health** — pharmacies, doctors, dentists, hospitals, clinics,
veterinarians, opticians, physiotherapists

**Retail** — supermarkets, convenience-stores, clothing-stores,
shoe-stores, furniture-stores, hardware-stores, florists, bookshops,
jewellers, electronics-stores, bicycle-shops, pet-shops, butchers,
greengrocers, wine-shops, tobacco-shops

**Personal services** — hairdressers, beauty-salons, tattoo-parlours,
dry-cleaners, gyms, spas

**Automotive** — car-dealers, car-repair, car-rental, petrol-stations,
car-wash, driving-schools

**Professional services** — real-estate-agents, lawyers, accountants,
insurance-offices, banks, architects, travel-agencies,
employment-agencies, advertising-agencies, it-companies, coworking-spaces

**Trades** — plumbers, electricians, carpenters, painters, roofers,
locksmiths, builders

**Education** — schools, kindergartens, universities, language-schools

**Leisure** — museums, attractions, theatres, cinemas, sports-centres,
swimming-pools, golf-courses, playgrounds

**Logistics and infrastructure** — warehouses, post-offices,
parcel-lockers, ev-charging, parking, atms

Anything else: use `customTags` with a tag from
[taginfo.openstreetmap.org](https://taginfo.openstreetmap.org).

### Use cases

- **Local lead lists** — pick a category and a city, tick "only places with
  a phone number", export a call list.
- **Market and site analysis** — count competitors per town, map their
  density, compare coverage between areas.
- **Store locators and directories** — seed a directory with real
  coordinates and opening hours.
- **Enriching a CRM** — match on name and postcode, fill in missing phone
  numbers and websites.
- **Field logistics** — route planning from real coordinates.

### Coverage, honestly

OpenStreetMap is volunteer-mapped, so completeness varies by country and by
category. Measured on 966 Bordeaux restaurants: 98.8 % had a name, 74.3 % a
street address, 48.9 % opening hours, 41.5 % a website, 41.1 % a phone
number, 12.2 % an email address.

Dense European cities are mapped well. Rural areas and some categories are
thinner. This Actor reports what is in the database — it does not invent
missing fields, and it will not pretend a village has ten dentists.

### Behaviour and limits

- Several Overpass mirrors are used in turn; a loaded or failing mirror is
  skipped automatically.
- Very large areas with no administrative boundary fall back to a tiled
  scan, deduplicated across tiles.
- Places with no name are skipped: a nameless point is not a business.
- Nominatim's usage policy is respected — one geocoding request per run.

### How much does it cost?

You pay per place returned: **$0.003 each**, that is $3.00 per 1,000. There is no start fee, and subscription plans pay less per place.

The example input below asks for up to 200 places, so it costs **$0.60 at most**.

If a run reaches the spending limit you set, the output stops at that limit and never goes past it. You are never charged for rows that were not delivered.

### Use OpenStreetMap Scraper as an API

Call it from your own code with the Apify client, here in Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("DataIO/openstreetmap-overpass-poi-scraper").call(run_input={
    'location': 'Bordeaux, France',
    'category': 'restaurants',
    'maxItems': 200,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

It also works from JavaScript, Make, Zapier, n8n, and from AI agents through the Apify MCP server.

### Other actors you might like

- [Google Hotels Scraper](https://apify.com/DataIO/google-hotels-scraper): Hotel Prices & Ratings
- [GLEIF LEI Lookup](https://apify.com/DataIO/gleif-lei-lookup): Legal Entity Identifier API
- [NPI Registry Scraper](https://apify.com/DataIO/nppes-npi-provider-registry): US Healthcare Providers

### FAQ

#### Is it legal to use this data?

The actor reads public data from its official source, without logging in and without bypassing any access control. What you do with the data, for example contacting people listed in it, is your responsibility under the laws that apply to you, such as GDPR in Europe.

#### Can I run it on a schedule?

Yes. Create a schedule in Apify Console, daily or weekly for example, and each run delivers a fresh dataset, which you can send by email, webhook or integration.

#### Can AI agents use it?

Yes. It is available through the Apify MCP server, and every input field is described in its input schema, so an agent can call it directly.

# Actor input Schema

## `location` (type: `string`):

A town, city, district or region — for example "Bordeaux, France", "Brooklyn, New York" or "Bavaria". Resolved to an area automatically. Leave empty only if you supply a bounding box or a centre point below.

## `category` (type: `string`):

82 ready-made categories. For anything not listed, use Custom OSM tags below.

## `maxItems` (type: `integer`):

Stops once this many places have been collected. Large areas are split into tiles and queried automatically.

## `requirePhone` (type: `boolean`):

Useful for call lists. Roughly 40% of places carry a phone number, so this shrinks the result substantially.

## `requireWebsite` (type: `boolean`):

Roughly 40% of places carry a website.

## `boundingBox` (type: `array`):

Exact area as \[south, west, north, east] in decimal degrees. Overrides Place when set.

## `center` (type: `object`):

Used with Radius, as {"lat": 44.84, "lon": -0.58}.

## `radiusMeters` (type: `integer`):

Used with Centre point.

## `customTags` (type: `array`):

Raw OpenStreetMap tag filters, as \["amenity=restaurant", "shop=bakery"]. Overrides the category when set. Use the OSM wiki or taginfo.openstreetmap.org to find tags.

## Actor input object example

```json
{
  "location": "Bordeaux, France",
  "category": "restaurants",
  "maxItems": 500,
  "requirePhone": false,
  "requireWebsite": false
}
```

# Actor output Schema

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

Every row produced by the run, in JSON.

# 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 = {
    "location": "Bordeaux, France",
    "maxItems": 500
};

// Run the Actor and wait for it to finish
const run = await client.actor("dataio/openstreetmap-overpass-poi-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 = {
    "location": "Bordeaux, France",
    "maxItems": 500,
}

# Run the Actor and wait for it to finish
run = client.actor("dataio/openstreetmap-overpass-poi-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 '{
  "location": "Bordeaux, France",
  "maxItems": 500
}' |
apify call dataio/openstreetmap-overpass-poi-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dataio/openstreetmap-overpass-poi-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/aIbdp59E1d9SdqUY4/builds/8xtLvfzzGu9m44rHj/openapi.json
