# OpenStreetMap Places Scraper - Google Maps alternative (`krasyn-side/osm-places-scraper`) Actor

Extract local businesses and POIs from OpenStreetMap by category and city: name, address, coordinates, phone, website, email, opening hours, cuisine, brand. Open data (ODbL), official Overpass API, no proxies. Pay per place.

- **URL**: https://apify.com/krasyn-side/osm-places-scraper.md
- **Developed by:** [Krasyn Labs](https://apify.com/krasyn-side) (community)
- **Categories:** Lead generation, Travel, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.50 / 1,000 place returneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## OpenStreetMap Places Scraper (Google Maps alternative, open data)

Extract **local businesses and points of interest (POI data)** from **OpenStreetMap** by category and location: name, category, full address, latitude/longitude, phone, website, email, opening hours, cuisine, brand, wheelchair access and selected raw OSM tags. One clean row per place, ready for CSV, Excel, JSON or the Apify API.

The data comes from the **public Overpass API**, which serves OpenStreetMap data. Locations are resolved with **Nominatim**. No HTML scraping, no browser, no proxies, no login.

### Why OpenStreetMap instead of Google Maps?

- **Open license.** OSM data is published under the Open Database License (ODbL). You can store, combine and reuse it, including commercially, as long as you attribute OpenStreetMap and follow the ODbL share-alike terms for derived databases.
- **Cheap and predictable.** You pay only per place returned. No start fee.
- **Stable.** It uses a documented public API, not a page layout that can change.

**What it is not:** OpenStreetMap is community-mapped. It has **no reviews, ratings, photos or popularity data**, and coverage varies a lot by region and category. City centres in Europe are usually well mapped. Suburbs and small towns in some countries may be missing many businesses, phone numbers or websites. If you need reviews and ratings, use a Google Maps scraper. If you need open, reusable POI data or a cheaper first pass at business leads, this actor is a good fit.

### Use cases

- **Business leads / lead generation**: every dentist, plumber, lawyer or hotel in a city with the phone and website mapped in OSM. Use the filters to keep only places with a website or phone.
- **Market research and site selection**: count cafes, gyms or pharmacies per city or bounding box.
- **POI datasets for apps and maps**: coordinates plus opening hours, cuisine, brand and accessibility.
- **Data enrichment**: match your own records against OSM by name and address.

### Input

| Field | Type | Description |
|---|---|---|
| `searchTerms` | array of strings | Categories in plain words (`restaurant`, `dentist`, `plumber`, `coffee shop`, `hotel`, `hair salon`, `lawyer`, `gym` ...) or raw OSM tags (`shop=bakery`, `craft=electrician`, `amenity=*`). Required. |
| `location` | string | City, region or country, e.g. `Boise, Idaho` or `Lisbon, Portugal`. Resolved to an OSM boundary. |
| `boundingBox` | string | Alternative to `location`: `south,west,north,east`, e.g. `38.69,-9.20,38.75,-9.10`. |
| `maxItems` | integer | Max places returned. Default 100. |
| `onlyWithWebsite` | boolean | Keep only places with a website tag. |
| `onlyWithPhone` | boolean | Keep only places with a phone tag. |
| `onlyWithEmail` | boolean | Keep only places that published an email in OSM (low coverage in most regions). |
| `onlyNamed` | boolean | Skip unnamed features. Default true. |

Plain words are mapped to the usual OSM tags (for example `dentist` → `amenity=dentist` and `healthcare=dentist`, `coffee shop` → `amenity=cafe` and `shop=coffee`, `plumber` → `craft=plumber`). Unknown words are tried as values of `shop`, `amenity`, `craft`, `office`, `tourism`, `leisure` and `healthcare`. For full control, use raw `key=value` tags. See the [OSM Map Features wiki](https://wiki.openstreetmap.org/wiki/Map_features).

Example:

```json
{
  "searchTerms": ["coffee shop", "bakery"],
  "location": "Lisbon, Portugal",
  "maxItems": 500,
  "onlyWithWebsite": true
}
```

### Output

One dataset item per place (the example below is a real row from a Boise dentists run; many OSM places lack phone or website). Contact tags are normalized: `phone` also reads `contact:phone` and `mobile`, `website` also reads `contact:website` and `url`, `email` also reads `contact:email`. The email is only ever the one the business itself published in OpenStreetMap. Places are deduplicated by OSM element.

```json
{
  "osmType": "node",
  "osmId": 7278212226,
  "osmUrl": "https://www.openstreetmap.org/node/7278212226",
  "name": "Fred J. Stillings, Dmd",
  "category": "amenity=dentist",
  "categoryValue": "dentist",
  "street": "West Garverdale Court",
  "housenumber": "10552",
  "postcode": "83704",
  "city": "Boise",
  "state": "ID",
  "country": null,
  "fullAddress": "10552 West Garverdale Court, 83704 Boise, ID",
  "lat": 43.6210417,
  "lon": -116.313753,
  "phone": null,
  "website": null,
  "email": null,
  "facebook": null,
  "instagram": null,
  "openingHours": null,
  "cuisine": null,
  "brand": null,
  "wheelchair": null,
  "tags": { "amenity": "dentist", "healthcare": "dentist" },
  "attribution": "Data © OpenStreetMap contributors, ODbL 1.0. https://www.openstreetmap.org/copyright",
  "scrapedAt": "2026-10-14T22:52:47.673Z"
}
```

Ways and relations (for example a building mapped as an area) are returned with the coordinates of their centre.

### Pricing

Pay per event: **$0.0005 per place returned** (about $0.50 per 1,000 places). No start fee. Runs that find nothing cost nothing beyond Apify platform usage. Set a maximum cost per run in the Apify console and the actor stops when it is reached.

### Attribution and license (required)

Data © [OpenStreetMap contributors](https://www.openstreetmap.org/copyright), available under the [Open Database License (ODbL) 1.0](https://opendatacommons.org/licenses/odbl/1-0/). Every row carries an `attribution` field. **If you publish or share this data or anything made from it, you must credit "© OpenStreetMap contributors"**, and databases derived from it are subject to the ODbL share-alike terms.

Using OSM data for outreach is your responsibility: follow anti-spam and privacy law (for example CAN-SPAM, GDPR, PECR) in your jurisdiction.

### Fair use of public services

The actor sends **one Overpass query per run** with a server-side timeout, retries with backoff on 429/504 errors, falls back to other public Overpass instances, and makes at most one Nominatim request per second with a descriptive User-Agent, as the [Overpass](https://wiki.openstreetmap.org/wiki/Overpass_API) and [Nominatim](https://operations.osmfoundation.org/policies/nominatim/) usage policies ask. Very large areas (a whole country with a common category) can be slow or time out on the public servers; split them into regions or bounding boxes.

### FAQ

**Why are some phones or websites missing?** They are not mapped in OSM for that place. Use `onlyWithPhone` / `onlyWithWebsite` to filter, or add the data to OpenStreetMap yourself.

**How fresh is the data?** Overpass serves the live OSM database, usually only minutes behind edits.

**Can I fix wrong data?** Yes. Edit it on [openstreetmap.org](https://www.openstreetmap.org). Your change will show up in the next run.

### Disclaimer

Built and maintained by an AI agent (Claude, by Anthropic) operated by Krasyn LLC. Not affiliated with or endorsed by the OpenStreetMap Foundation, Google or Apify. OpenStreetMap is a trademark of the OpenStreetMap Foundation. Issues and feature requests: use the Issues tab on this actor.

# Actor input Schema

## `searchTerms` (type: `array`):

Business or place categories in plain words, e.g. restaurant, dentist, plumber, coffee shop, hotel, hair salon, lawyer, gym. Raw OpenStreetMap tags also work: shop=bakery, craft=electrician, amenity=\*.

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

Place name resolved to an OpenStreetMap boundary via Nominatim, e.g. "Boise, Idaho", "Lisbon, Portugal", "Bavaria". Ignored when a bounding box is given.

## `boundingBox` (type: `string`):

Alternative to location: south,west,north,east in decimal degrees, e.g. 38.69,-9.20,38.75,-9.10.

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

Maximum number of places to return (you pay per place returned).

## `onlyWithWebsite` (type: `boolean`):

Return only places that have a website tag in OpenStreetMap.

## `onlyWithPhone` (type: `boolean`):

Return only places that have a phone tag in OpenStreetMap.

## `onlyWithEmail` (type: `boolean`):

Return only places whose OpenStreetMap tags include a business email. Coverage is low in most regions.

## `onlyNamed` (type: `boolean`):

Skip unnamed features (recommended for business lists).

## Actor input object example

```json
{
  "searchTerms": [
    "dentist"
  ],
  "location": "Boise, Idaho",
  "maxItems": 20,
  "onlyWithWebsite": false,
  "onlyWithPhone": false,
  "onlyWithEmail": false,
  "onlyNamed": true
}
```

# 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 = {
    "searchTerms": [
        "dentist"
    ],
    "location": "Boise, Idaho",
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("krasyn-side/osm-places-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 = {
    "searchTerms": ["dentist"],
    "location": "Boise, Idaho",
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("krasyn-side/osm-places-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 '{
  "searchTerms": [
    "dentist"
  ],
  "location": "Boise, Idaho",
  "maxItems": 20
}' |
apify call krasyn-side/osm-places-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,krasyn-side/osm-places-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/dMYGsCDj11CQayjtB/builds/UdQSLqCqLdAnuN2ow/openapi.json
