# OpenStreetMap Places API — Businesses & POIs by Area (`insight.solutions/osm-places-api`) Actor

Businesses and points of interest from OpenStreetMap by category and area: cafés in a city, dentists near a point, hotels in a box. Name, address, coordinates, website, phone, opening hours, brand, cuisine, wheelchair access and raw tags. No API key, from $0.50 per 1,000 places.

- **URL**: https://apify.com/insight.solutions/osm-places-api.md
- **Developed by:** [Insight Solutions](https://apify.com/insight.solutions) (community)
- **Categories:** Lead generation, Business, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.30 / 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

## OpenStreetMap Places API — Businesses & POIs by Area

**A category and a place in, one row per business or point of interest out** —
from OpenStreetMap, with no API key. "Cafés in Berlin", "bicycle shops in
Cambridge", "pharmacies in this bounding box", "dentists within 2 km of
52.52,13.40".

Every row carries the name, the category, the address, coordinates, website,
phone, opening hours, brand, cuisine, wheelchair access, the OSM link and — if
you want them — the raw OSM tags. Areas come from a place name (looked up once
on Nominatim), a bounding box, or a point and a radius. The places come from
the public Overpass API, one polite query at a time.

No login. No browser. No API key of anyone's. Data © OpenStreetMap contributors,
available under the Open Database License (ODbL) — every row says so.

### At a glance

**Input** — this is the Store prefill; paste it and run:

```json
{ "categories": ["amenity=cafe"], "areas": [], "bboxes": ["52.50,13.38,52.52,13.42"], "points": [],
  "radiusMeters": 2000, "useAreaBoundary": true, "requireName": true, "keywords": [], "maxPlaces": 100,
  "reverseGeocode": false, "includeRawTags": true, "maxRunSecs": 240,
  "proxyConfiguration": { "useApifyProxy": true } }
```

That is one Overpass query and 100 named cafés in central Berlin, in a few
seconds. Put `"Berlin, Germany"` in `areas` instead of the box for the whole
city.

**Output** — one `place` row per business or point of interest. The fields you
will use most are `name`, `category`, `address`, `phone`, `website`,
`openingHours`, `lat`, `lon` and `osmUrl` (full list under *Output reference*).
Each area searched adds one free `area` row, and anything that could not be
read comes back as a free diagnostic row (`ok: false`, `errorType`, `error`)
instead of a charge.

**Price** — $0.50 per 1,000 places (+ $0.001 per run); areas, diagnostics and
empty runs free; no API key, no browser, limited permissions, works over the
Apify MCP server (`mcp.apify.com`) and with x402 agentic payments.

**From code** — `client.actor("insight.solutions/osm-places-api").call(run_input={…})`
with `apify-client`, or
`POST https://api.apify.com/v2/acts/insight.solutions~osm-places-api/run-sync-get-dataset-items`.

***

### What you get

One real row from the prefill's box, run with `"maxPlaces": 0` (the prefill's
cap of 100 stops just before it) — a café mapped as a building outline, so its
coordinates are the building's centre (abridged; `tags` shortened):

```json
{
  "ok": true,
  "rowType": "place",
  "input": "amenity=cafe in 52.50,13.38,52.52,13.42",
  "osmType": "way",
  "osmId": 113084569,
  "osmUrl": "https://www.openstreetmap.org/way/113084569",
  "name": "Café am Engelbecken",
  "category": "amenity=cafe",
  "categoryLabel": "A generally informal place with sit-down facilities selling beverages and light meals and/or snacks.",
  "lat": 52.5062646,
  "lon": 13.4186304,
  "street": "Michaelkirchplatz",
  "houseNumber": "25",
  "postcode": "10179",
  "city": "Berlin",
  "address": "Michaelkirchplatz 25, 10179 Berlin",
  "website": "https://www.cafe-am-engelbecken.de/",
  "phone": "+49 157 75431795",
  "openingHours": "Mo-Su 10:00-24:00",
  "wheelchair": "yes",
  "outdoorSeating": "yes",
  "internetAccess": "yes",
  "tags": { "amenity": "cafe", "name": "Café am Engelbecken", "website": "http://www.cafe-am-engelbecken.de", "…": "…" },
  "areaName": "52.50,13.38,52.52,13.42",
  "rank": 135,
  "source": "openstreetmap",
  "sourceUrl": "https://overpass-api.de/api/interpreter?data=%5Bout%3Ajson%5D…",
  "attribution": "© OpenStreetMap contributors, ODbL"
}
```

A chain outlet carries its brand too — the Starbucks in the same box comes back
with `"brand": "Starbucks"`, `"brandWikidata": "Q37158"` and
`"openingHours": "Mo-Fr 07:00-21:00; Sa 08:00-21:00; Su 09:00-19:30"`.

`sourceUrl` is the exact Overpass query the row came from, as a link: open it
and you see the raw response.

### Quick start

**Cafés in a city** — the name is looked up once and searched inside the city's
exact boundary:

```json
{ "categories": ["cafe"], "areas": ["Berlin, Germany"], "maxPlaces": 500 }
```

**Bicycle shops inside a boundary**, two categories at once:

```json
{ "categories": ["shop=bicycle", "amenity=bicycle_rental"], "areas": ["Cambridge, UK"] }
```

**Dentists around a point**, nearest first, with `distanceMeters`:

```json
{ "categories": ["dentist"], "points": ["52.52,13.40"], "radiusMeters": 2000 }
```

`dentist` is a bare name that both `amenity` and `healthcare` use, so both are
searched in one union query.

**Every hotel in a bounding box, to CSV** — `maxPlaces: 0` means no cap:

```json
{ "categories": ["tourism=hotel"], "bboxes": ["48.80,2.25,48.91,2.42"], "maxPlaces": 0, "includeRawTags": false }
```

then download the dataset as CSV (Storage → Export, or
`…/datasets/{id}/items?format=csv&clean=true`). Turning `includeRawTags` off keeps
the CSV to the named columns.

**Only vegan places**, filtered on any tag:

```json
{ "categories": ["cafe", "restaurant"], "areas": ["Kreuzberg, Berlin"], "keywords": ["vegan"] }
```

### Category names

Write a category as an OSM tag, `key=value` (`amenity=cafe`), as `key=*` for every
value of a key (`craft=*`), or as a bare name from the table below (`cafe`,
`bicycle`, `hotel`, `fitness centre`). A bare name that more than one key uses —
`dentist`, `pharmacy`, `tailor` — searches all of them. A bare key name
(`office`, `tourism`) means every value of that key. Anything else comes back as a
free `invalid-input` row telling you to write it as `key=value` — any OSM tag
works in that form, including ones not listed here.

`amenity` and `shop` are the 100 most-used values of each as published by
taginfo on 2026-09-30, with taginfo's own description (`bar` and `pub` have none
there). The other five keys are hand-written from the OSM wiki.

**`amenity`** (100 values, taginfo, top 100 by use)

| Value | Description |
|---|---|
| `parking` | A place for parking cars. |
| `parking_space` | A single parking space on a parking lot. |
| `bench` | A place for people to sit, allowing room for one or more people. |
| `place_of_worship` | A place where religious services are conducted. |
| `restaurant` | A restaurant sells full sit-down meals with servers, and may sell alcohol. |
| `school` | A primary or secondary school (pupils typically aged 6 to 18). |
| `waste_basket` | A single small container for depositing garbage that is easily accessible for pedestrians. |
| `bicycle_parking` | A parking space designed for bicycles. |
| `shelter` | A small structure for protection against bad weather conditions |
| `fast_food` | A place which offers self-service and take-away food. |
| `cafe` | A generally informal place with sit-down facilities selling beverages and light meals and/or snacks. |
| `recycling` | A container or centre that accepts waste material for reuse or recycling. |

Also: `fuel`, `toilets`, `pharmacy`, `post_box`, `bank`, `vending_machine`, `drinking_water`, `kindergarten`, `waste_disposal`, `hunting_stand`, `parking_entrance`, `bar`, `atm`, `community_centre`, `clinic`, `post_office`, `hospital`, `doctors`, `charging_station`, `fountain`, `pub`, `social_facility`, `townhall`, `police`, `dentist`, `grave_yard`, `fire_station`, `car_wash`, `library`, `parcel_locker`, `marketplace`, `bicycle_rental`, `childcare`, `telephone`, `college`, `bus_station`, `ice_cream`, `veterinary`, `university`, `theatre`, `taxi`, `public_bookcase`, `motorcycle_parking`, `bbq`, `letter_box`, `water_point`, `loading_dock`, `grit_bin`, `shower`, `ferry_terminal`, `events_venue`, `clock`, `driving_school`, `public_building`, `car_rental`, `courthouse`, `cinema`, `watering_place`, `arts_centre`, `trolley_bay`, `nightclub`, `bicycle_repair_station`, `bureau_de_change`, `lounger`, `studio`, `food_court`, `monastery`, `internet_cafe`, `prison`, `ticket_validator`, `social_centre`, `music_school`, `payment_terminal`, `vehicle_inspection`, `compressed_air`, `animal_breeding`, `public_bath`, `prep_school`, `car_sharing`, `weighbridge`, `lavoir`, `nursing_home`, `sanitary_dump_station`, `mobile_money_agent`, `language_school`, `biergarten`, `dojo`, `vacuum_cleaner`.

**`shop`** (100 values, taginfo, top 100 by use)

| Value | Description |
|---|---|
| `convenience` | A small local shop carrying a variety of everyday products, such as packaged food and hygiene products. |
| `supermarket` | A large shop selling groceries, fresh produce, and other goods. |
| `clothes` | A shop which primarily sells clothing |
| `hairdresser` | A hairdressers or barbers shop, where hair is cut |
| `car_repair` | A business where cars are repaired. |
| `bakery` | A shop selling bread |
| `yes` | A shop of unspecified type or an indicator that a feature such as a fuel station has a shop. |
| `beauty` | A non-hairdresser beauty shop, spa, nail salon, etc. |
| `car` | A place that primarily sells cars (automobiles) |
| `hardware` | Shop selling primarily metal fasteners and tools, sometimes also other workshop and homeware products. |
| `butcher` | A shop selling meat or meat products. |
| `kiosk` | A small shop on the pavement that sells magazines, tobacco, newspapers, sweets and stamps. |

Also: `mobile_phone`, `furniture`, `car_parts`, `alcohol`, `variety_store`, `florist`, `optician`, `electronics`, `jewelry`, `outpost`, `shoes`, `vacant`, `mall`, `gift`, `doityourself`, `greengrocer`, `chemist`, `laundry`, `books`, `bicycle`, `department_store`, `pet`, `travel_agency`, `stationery`, `sports`, `confectionery`, `tyres`, `storage_rental`, `tobacco`, `cosmetics`, `trade`, `massage`, `tailor`, `computer`, `funeral_directors`, `copyshop`, `pastry`, `motorcycle`, `dry_cleaning`, `farm`, `garden_centre`, `beverages`, `newsagent`, `general`, `ticket`, `interior_decoration`, `deli`, `houseware`, `toys`, `seafood`, `wine`, `tattoo`, `wholesale`, `paint`, `second_hand`, `pawnbroker`, `medical_supply`, `charity`, `photo`, `bed`, `kitchen`, `bookmaker`, `art`, `lottery`, `agrarian`, `outdoor`, `antiques`, `e-cigarette`, `fabric`, `coffee`, `perfumery`, `gas`, `motorcycle_repair`, `hearing_aids`, `appliance`, `craft`, `electrical`, `telecommunication`, `money_lender`, `pet_grooming`, `tea`, `bag`, `dairy`, `baby_goods`, `musical_instrument`, `rental`, `fashion_accessories`, `cannabis`.

**`tourism`** (20 values, hand-written from the OSM wiki)

| Value | Description |
|---|---|
| `hotel` | An establishment providing accommodation with en-suite rooms and services. |
| `guest_house` | A small accommodation such as a bed and breakfast or guest house. |
| `hostel` | Cheap accommodation with shared bedrooms. |
| `motel` | A roadside hotel with parking directly outside each room. |
| `apartment` | A furnished apartment or flat rented for short stays. |
| `chalet` | A holiday cottage or hut rented as a whole. |
| `camp_site` | An area where people can camp overnight using tents or vehicles. |
| `caravan_site` | An area where people can stay overnight in caravans or motorhomes. |
| `alpine_hut` | A mountain hut, usually staffed, providing shelter and meals. |
| `wilderness_hut` | An unstaffed hut in a remote area, free or cheap to use. |
| `attraction` | A generic tourist attraction. |
| `museum` | An institution that displays collections of historical, cultural or scientific objects. |

Also: `gallery`, `artwork`, `viewpoint`, `information`, `picnic_site`, `theme_park`, `zoo`, `aquarium`.

**`leisure`** (24 values, hand-written from the OSM wiki)

| Value | Description |
|---|---|
| `fitness_centre` | A gym or fitness centre with exercise equipment. |
| `sports_centre` | A facility where a range of sports take place. |
| `sports_hall` | A large indoor hall for sports. |
| `swimming_pool` | A swimming pool. |
| `water_park` | An amusement park with water slides and pools. |
| `stadium` | A major sports arena with substantial tiered seating. |
| `pitch` | An area designed for playing a particular sport. |
| `track` | A track for running, cycling or other non-motorised racing. |
| `golf_course` | The course of a golf club. |
| `miniature_golf` | A miniature golf course. |
| `ice_rink` | A place where people skate on ice. |
| `bowling_alley` | A place for ten-pin or nine-pin bowling. |

Also: `marina`, `park`, `playground`, `garden`, `nature_reserve`, `dog_park`, `sauna`, `dance`, `escape_game`, `amusement_arcade`, `horse_riding`, `fitness_station`.

**`office`** (24 values, hand-written from the OSM wiki)

| Value | Description |
|---|---|
| `company` | An office of a private company. |
| `government` | An office of a government agency or authority. |
| `estate_agent` | An office of a real estate agent. |
| `insurance` | An office of an insurance company or broker. |
| `lawyer` | An office of a lawyer or law firm. |
| `accountant` | An office of an accountant. |
| `tax_advisor` | An office of a tax advisor. |
| `notary` | An office of a notary. |
| `architect` | An office of an architect or architecture firm. |
| `it` | An office of an IT specialist or IT company. |
| `consulting` | An office of a consulting firm. |
| `financial` | An office of a financial services company. |

Also: `advertising_agency`, `employment_agency`, `travel_agent`, `telecommunication`, `logistics`, `coworking`, `ngo`, `association`, `educational_institution`, `research`, `political_party`, `religion`.

**`healthcare`** (24 values, hand-written from the OSM wiki)

| Value | Description |
|---|---|
| `doctor` | A doctor's practice. |
| `dentist` | A dentist's practice. |
| `pharmacy` | A pharmacy: a shop where medicines are dispensed. |
| `hospital` | A hospital providing in-patient medical treatment. |
| `clinic` | A medical centre with more than one doctor, usually without overnight stays. |
| `physiotherapist` | A physiotherapy practice. |
| `psychotherapist` | A psychotherapy practice. |
| `optometrist` | An optometrist or eye-care practice. |
| `audiologist` | A hearing-care practice. |
| `podiatrist` | A podiatry or foot-care practice. |
| `speech_therapist` | A speech and language therapy practice. |
| `occupational_therapist` | An occupational therapy practice. |

Also: `alternative`, `laboratory`, `sample_collection`, `rehabilitation`, `counselling`, `midwife`, `nurse`, `dialysis`, `blood_donation`, `vaccination_centre`, `hospice`, `birthing_centre`.

**`craft`** (24 values, hand-written from the OSM wiki)

| Value | Description |
|---|---|
| `carpenter` | A workplace of a carpenter who works with timber. |
| `electrician` | A workplace or office of an electrician. |
| `plumber` | A workplace or office of a plumber. |
| `hvac` | A heating, ventilation and air-conditioning installer. |
| `painter` | A workplace of a house or decorative painter. |
| `roofer` | A workplace of a roofer. |
| `glaziery` | A workplace of a glazier who cuts and fits glass. |
| `locksmith` | A workplace of a locksmith. |
| `key_cutter` | A place where keys are cut. |
| `metal_construction` | A workplace for metal construction and fabrication. |
| `window_construction` | A workplace for making and fitting windows. |
| `stonemason` | A workplace of a stonemason. |

Also: `gardener`, `photographer`, `shoemaker`, `tailor`, `upholsterer`, `jeweller`, `confectionery`, `brewery`, `winery`, `beekeeper`, `handicraft`, `blacksmith`.

### Input

| Field | Type | Default | What it does |
|---|---|---|---|
| `categories` | string\[] | `["amenity=cafe"]` | OSM `key=value` pairs, `key=*`, or bare names from the table above. Each category is searched in each area separately. |
| `areas` | string\[] | `[]` | Place names — `Berlin, Germany`, `Cambridge, UK`, `Kreuzberg, Berlin`. One Nominatim lookup each. |
| `bboxes` | string\[] | `[]` | `south,west,north,east` in decimal degrees. |
| `points` | string\[] | `[]` | `lat,lon`, searched within `radiusMeters`. |
| `radiusMeters` | integer | `2000` | For `points`. 50–20,000. |
| `useAreaBoundary` | boolean | `true` | For a named area that is an administrative boundary, search inside the exact boundary rather than its bounding box. |
| `requireName` | boolean | `true` | Skip unnamed elements (benches, parking spaces, anonymous vending machines). |
| `keywords` | string\[] | `[]` | Keep only places whose name, brand, cuisine or any tag (`key=value`) contains one of these words, case-insensitive. |
| `maxPlaces` | integer | `500` | Per category and area. `0` = no cap (up to 5,000 per Overpass query, within `maxRunSecs`). |
| `reverseGeocode` | boolean | `false` | For places with no `addr:*` tag at all, ask Nominatim for the nearest address. One request a second, at most 200 a run. |
| `includeRawTags` | boolean | `true` | Add the place's OSM tags as a `tags` object. |
| `maxRunSecs` | integer | `240` | 30–3,600. No new query is started after this. |
| `proxyConfiguration` | object | `{ "useApifyProxy": true }` | Apify datacenter proxy by default; both services answered through it in testing. |

At least one valid category and one of `areas`, `bboxes` or `points` are needed;
a run with neither fails straight away without sending a request, and costs
nothing. There is no concurrency setting: this Actor keeps exactly one Overpass
query in flight, always (see *Fair use*).

### Output reference

Every row has the same columns; the ones that do not apply are `null`.

**Envelope (every row):** `ok`, `rowType` (`place`, `area` or `diagnostic`),
`input` (the category and area, as `amenity=cafe in Berlin, Germany`), `error`,
`errorType`, `scrapedAt`, `source` (`openstreetmap`), `sourceUrl`,
`attribution` (`© OpenStreetMap contributors, ODbL`).

**`place` rows (paid):**

| Column | From | Notes |
|---|---|---|
| `osmType`, `osmId`, `osmUrl` | the element | `node`, `way` or `relation`; the id is permanent. |
| `name`, `brand`, `brandWikidata` | `name`, `brand`, `brand:wikidata` | |
| `category`, `categoryKey`, `categoryValue`, `categoryLabel` | the tag it was found by | `amenity=cafe`; the label is taginfo's description. For `key=*` the element's own value. |
| `cuisine` | `cuisine` | An array, split on `;`. |
| `lat`, `lon` | the node, or the centre of a way or relation | WGS84. |
| `street`, `houseNumber`, `postcode`, `city`, `suburb` | `addr:*` | |
| `country` | `addr:country`, else the named area's country | ISO 3166-1 alpha-2. |
| `address` | the above, joined in local order | Or `addr:full`, or the reverse-geocoded address. |
| `website` | `website` → `contact:website` → `brand:website` | Normalised to an `https://` URL; the tag's own spelling stays in `tags`. |
| `phone` | `phone` → `contact:phone` | The first number when several are tagged. |
| `email` | `email` → `contact:email` | Only on a named business (see *Personal data*). |
| `openingHours` | `opening_hours` | Exactly as tagged, in OSM's opening-hours syntax. |
| `wheelchair`, `outdoorSeating`, `takeaway`, `delivery`, `internetAccess`, `level` | the matching tags | Values as tagged (`yes`, `no`, `limited`, `wlan`…). |
| `checkDate` | `check_date` | When a mapper last confirmed the place. |
| `wikidata`, `wikipedia` | `wikidata`, `wikipedia` | The Wikipedia tag as an article URL. |
| `tags` | every tag | Minus the personal ones; null when `includeRawTags` is off. |
| `areaName`, `areaOsmId` | the area searched | `areaOsmId` for named areas (62422 for Berlin). |
| `distanceMeters` | points mode | Straight-line metres from your point. |
| `rank` | | Position within its category and area: OSM id order for areas and boxes, nearest first for points. |

**`area` rows (free, one per area):** `areaName`, `displayName`, `osmType`,
`osmId`, `osmUrl`, `boundingBox` (`{ south, west, north, east }`), `areaId` (the
Overpass area id, 3600000000 + the relation id), `country`, `addressType`,
`lat`/`lon` (Nominatim's centre for a named area, the point itself for a points
search), `tiles` (Overpass queries it took, across all categories) and
`placeCount`.

**`diagnostic` rows (free):**

| `errorType` | Meaning |
|---|---|
| `invalid-input` | A category, box, point or area that could not be used, and why. |
| `area-not-found` | Nominatim had no match for the name. |
| `no-results` | The query worked and nothing matched — or everything it found was dropped by `requireName`, `keywords`, or had already been returned. |
| `overpass-busy` | Both public Overpass instances answered 429 or 5xx (see *Fair use*). |
| `overpass-timeout` | Part of an area could not be finished within Overpass's 60 s limit even after halving it. |
| `rate-limited`, `blocked` | Nominatim answered 429 or 403, or Overpass answered 403 twice. |
| `http`, `timeout` | Any other HTTP status, or no answer in time. |
| `deadline` | `maxRunSecs` ran out; what was delivered is kept. |
| `budget` | Your maximum total charge was reached; what was delivered is kept. |
| `upstream-format` | A response in a shape this Actor does not recognise, or Overpass refusing the query or the User-Agent. |
| `actor-error` | The Actor itself failed; the run is marked FAILED. |

The dataset has three views: **Places** (`name`, `category`, `city`, `address`,
`phone`, `website`, `openingHours`, `lat`, `lon`, `osmUrl`), **Areas** and
**Diagnostics**.

### How areas are resolved

- **A name** goes to OpenStreetMap's Nominatim geocoder once:
  `search?q=<name>&format=jsonv2&limit=1&addressdetails=1`. Its first hit gives a
  bounding box and, when it is an administrative boundary (an OSM relation, as
  cities and districts are), the boundary itself. With `useAreaBoundary` on, the
  search is `area(3600000000 + relation id)` — exactly the city, not the edge of
  the next one. Otherwise, or when the hit is not a boundary, its bounding box is
  used. Nominatim is asked **once per distinct name per run** however many
  categories you list, and never more than **one request per second**, as its
  usage policy requires: https://operations.osmfoundation.org/policies/nominatim/.
  A 429 or 403 from Nominatim is never retried and stops every further Nominatim
  request in that run.
- **A bounding box** is used as given.
- **A point** is searched with Overpass's `around` filter, and the results sorted
  nearest first.

A name Nominatim cannot find is a free `area-not-found` row; the other areas
still run. Adding the country usually fixes it ("Cambridge, UK", not
"Cambridge").

### Fair use

Overpass and Nominatim are run by volunteers and the OSM Foundation on donated
hardware. This Actor treats them accordingly:

- **One identifying User-Agent on every request:**
  `insight-solutions-osm-places-api/0.1 (+https://apify.com/insight.solutions)`.
  Overpass refuses generic ones — in testing it answered a `curl` and a browser
  User-Agent with HTTP 406 — and both services' policies ask for it.
- **One Overpass query in flight** for the whole run, a short pause between
  queries, and `[timeout:60]` on every query.
- **Small queries.** A box larger than 0.5° × 0.5° is split into tiles of at most
  0.25° a side, queried one after another; more than 64 tiles (about 2° × 2°) is
  refused — name the area instead. Every query is capped with `out … n`: at what
  the run still needs, or at 5,000 when `keywords` or a points search mean the
  filtering and sorting happen on our side.
- **Busy servers are left alone.** A 429 or 5xx waits 10 seconds and tries the
  other public instance (`overpass-api.de` ↔ `lz4.overpass-api.de`) from a
  fresh proxy exit, then waits 20 and 30 seconds for two more alternations
  made directly, without the proxy — four attempts spread over about a minute
  — and then gives up on that query with a free `overpass-busy` row. Three of
  those in a row and the run stops querying altogether.
- **Oversized queries are halved.** A query that hits the 60-second limit is
  halved and retried, down to an eighth of the original, and a category that
  times out six times in one area stops there with one `overpass-timeout` row.
- **Reverse geocoding is opt-in**, one request a second, at most 200 a run, and
  only for places with no address at all.
- **The Store's daily test run never calls Nominatim** — the prefill is a
  bounding box.

### Attribution

The data is © OpenStreetMap contributors and is available under the **Open
Database License (ODbL)**: https://www.openstreetmap.org/copyright. Every row
carries `"attribution": "© OpenStreetMap contributors, ODbL"`, and a successful
run's status message ends with it. If you publish or redistribute the data — a map, a
directory, a report — you must credit OpenStreetMap contributors and keep the
ODbL's share-alike terms for any database you derive from it.

### What is and isn't in OSM

OpenStreetMap is mapped by volunteers, so coverage varies: dense and current in
most European and many North American cities, thinner elsewhere, and a small
village café may simply not be mapped. Measured on the 137 named cafés of the
prefill box (central Berlin, 2026-09-30):

| Field | Filled |
|---|---|
| `openingHours` | 64% |
| `address` | 64% |
| `website` | 39% |
| `phone` | 26% |
| `email` | 13% |
| `wheelchair` | 68% |
| `outdoorSeating` | 69% |
| `cuisine` | 40% |
| `brand` | 16% (chains only) |

- **There are no reviews, ratings, photos or price levels** — OSM does not
  collect them.
- **Opening hours are as tagged**, in OSM's own syntax (`Mo-Fr 07:00-21:00; Sa
  08:00-21:00`); this Actor does not evaluate them into "open now". `checkDate`,
  where present, says when someone last confirmed the place.
- A place closed since it was last mapped is still there until a mapper removes
  it.

### Personal data

OSM describes places, but its free-form tags occasionally name a person. This
Actor returns organisation-level facts only:

- `contact:person`, `contact:name`, `owner` and `contact:owner` are never
  returned — not as a column and not in `tags`.
- An `operator` that looks like a personal name (two or three capitalised words
  with no company marker such as GmbH, Ltd, Inc or e.V.) is removed from `tags`.
  The test errs on the side of removing: a company whose name looks like a
  person's is removed too.
- `email` is returned only for a **named** business — an element with one of
  the seven category keys and a `name` — where it is the organisation's
  published mailbox; otherwise it is removed from `tags` as well.
- A business `phone` is kept: it is the business's number.

### What you are never charged for

- The `area` row for each area searched.
- Every diagnostic row: areas not found, categories with nothing mapped, busy or
  timed-out Overpass queries, rate limits, the time budget and the charge limit.
- Places dropped by `requireName` or `keywords` — they are filtered before they
  are written.
- A place already returned earlier in the same run, under another category, in a
  neighbouring tile or in an overlapping area.
- Nominatim lookups and the addresses `reverseGeocode` fills in.
- A run that returns no place at all: it finishes SUCCEEDED with a "0 results …
  Nothing was charged." status message, and the start fee is not billed either.

### Pricing

| Event | FREE | BRONZE | SILVER | GOLD |
|---|---|---|---|---|
| Run started (once, only when a place is returned) | $0.001 | $0.001 | $0.001 | $0.001 |
| Place | $0.0005 | $0.0005 | $0.0004 | $0.0003 |

That is $0.50 per 1,000 places on the FREE tier. The prefill costs $0.051; every
café in central Berlin (about 1,400) costs 1,400 × $0.0005 + $0.001 = $0.701.
Set a maximum total charge on the run and it stops querying when it gets there,
keeping everything already delivered.

### Use it from an AI agent, or from code

Over the Apify MCP server (`mcp.apify.com`) an agent can call it as
`insight.solutions/osm-places-api` with the same JSON input. From Python:

```python
## pip install apify-client
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("insight.solutions/osm-places-api").call(run_input={
    "categories": ["amenity=cafe"],
    "areas": ["Berlin, Germany"],
    "maxPlaces": 200,
})
for place in client.dataset(run["defaultDatasetId"]).iterate_items():
    if place["rowType"] == "place":
        print(place["name"], place["address"], place["website"])
```

Or in one HTTP call:
`POST https://api.apify.com/v2/acts/insight.solutions~osm-places-api/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>`
with the input as the JSON body.

### FAQ

**Do I need an OpenStreetMap or Overpass account or key?** No. Both services are
public; this Actor identifies itself with its own User-Agent.

**Why did "Cambridge" give me the wrong Cambridge?** Nominatim returns its best
match, and there are several. Add the country — `Cambridge, UK` or
`Cambridge, MA, USA` — or pass a bounding box.

**Why is `address` empty for some places?** Because nobody has tagged an address
on them in OSM. Turn on `reverseGeocode` to fill it from the nearest address
Nominatim knows (slow by design: one a second, 200 a run).

**Why is `website` https when the tag says http?** The column is normalised so
every value is a link you can open over TLS; the original is in `tags.website`.

**How do I get more than 500 places?** Raise `maxPlaces`, or set it to `0` for
no cap. Large areas take more queries and more time; raise `maxRunSecs` too.

**Can I search a whole country?** By name, with `useAreaBoundary` on, it is one
boundary query per category — which Overpass may not finish in 60 s for a
common category; the Actor then halves the area a few times and tells you what
it could not finish. A city or region at a time is faster and more reliable.

**Is the same place ever charged twice?** Not in one run. Across runs, yes —
each run returns what is in OSM at the time.

**What does `categoryLabel` say for `bar`?** Nothing: taginfo publishes no
description for it, and the Actor does not invent one.

### Limitations

- **The upstream formats may change.** Overpass, Nominatim and OSM's tagging
  conventions are maintained by volunteers; a changed response shape comes back
  as a free `upstream-format` row rather than bad data.
- Coverage and freshness are OSM's, and vary by place and category.
- Public Overpass instances are shared and sometimes busy; a busy run returns
  free diagnostics rather than retrying aggressively.
- At most 5,000 places per Overpass query; a tile that would hold more is cut at
  that number.
- Boxes across the 180th meridian are not supported; split them in two.
- The personal-name check on `operator` is a heuristic and errs on the side of
  removing.
- Opening hours are returned as tagged, not evaluated.
- Nominatim resolves a name to its single best match; there is no disambiguation
  prompt.

### Our other Actors

Every Insight Solutions Actor is pay-per-result with no browser, no login and no API key, and every one of them returns free diagnostic rows instead of billing for failures. Prices are per 1,000 results.

**Video, audio & social**

- [YouTube Transcript API](https://apify.com/insight.solutions/youtube-transcript-api) — captions as timed segments, text, SRT or VTT, with language fallback and translation.
- [YouTube Comments API](https://apify.com/insight.solutions/youtube-comments-api) — comments and replies with likes, pinned and hearted flags, newest or top sort.
- [YouTube Channel API](https://apify.com/insight.solutions/youtube-channel-api) — a channel's videos, Shorts and live streams, plus YouTube search.
- [Podcast Search, Episodes & Charts API](https://apify.com/insight.solutions/podcast-api) — Apple Podcasts search, charts and full episode feeds.
- [Bluesky Scraper](https://apify.com/insight.solutions/bluesky-scraper) — profiles, posts, followers and follows from the public AT Protocol API.
- [Telegram Channel Scraper](https://apify.com/insight.solutions/telegram-channel-scraper) — posts, views and channel stats from public Telegram channels.
- [Substack Scraper](https://apify.com/insight.solutions/substack-scraper) — posts with full free text, comments and publication profiles.
- [Hacker News API](https://apify.com/insight.solutions/hacker-news-api) — stories, comments, users, front page and a structured "Who is hiring?" parser from the official HN APIs.
- [Discourse Forum API](https://apify.com/insight.solutions/discourse-forum-api) — topics, posts and categories from any Discourse community via its own JSON endpoints, usernames only.

**News, documents & the web**

- [Google News Search, Topics & Real Article URLs](https://apify.com/insight.solutions/google-news-api) — news search and topic feeds with the publisher's real URL decoded.
- [Website to Markdown — Content Extractor for LLMs & RAG](https://apify.com/insight.solutions/website-content-extractor) — any site as clean Markdown, text and heading-aware chunks.
- [Internet Archive API](https://apify.com/insight.solutions/internet-archive-api) — archive.org search, item metadata, files and reviews.
- [Wayback Machine Toolkit](https://apify.com/insight.solutions/wayback-toolkit) — archived URL inventories, snapshots and text diffs between dates.
- [Website Technology Detector](https://apify.com/insight.solutions/website-tech-detector) — the tech stack behind any site, with the evidence for each detection.
- [Domain Intelligence API](https://apify.com/insight.solutions/domain-intelligence-api) — DNS, RDAP registration, TLS certificate and HTTP facts in one row per domain.
- [SEO Page Audit](https://apify.com/insight.solutions/seo-page-audit) — sitemap crawl with on-page checks, structured data and broken-link reports.
- [Keyword Suggestions API](https://apify.com/insight.solutions/keyword-suggestions-api) — Google, YouTube, Bing, Amazon and eBay autocomplete with alphabet and question expansions.
- [Website Contact Extractor](https://apify.com/insight.solutions/website-contact-extractor) — emails, phone numbers and social profiles from any list of websites.
- [Web Search Results API](https://apify.com/insight.solutions/web-search-api) — Bing and DuckDuckGo organic results with snippets, no key, no browser.
- [Company Enrichment API](https://apify.com/insight.solutions/company-enrichment-api) — a domain in, a company profile out: firmographics, contacts, tech stack, DNS and hiring signal.
- [Company Dossier API](https://apify.com/insight.solutions/company-dossier-api) — one company in, twelve sections out: profile, tech, contacts, DNS, open roles, news, SEC filings, federal awards, recalls, YC batch and apps.
- [Press Releases API](https://apify.com/insight.solutions/press-releases-api) — GlobeNewswire and PR Newswire releases plus any newsroom feed, by keyword, company, ticker or subject.
- [Federal Register API](https://apify.com/insight.solutions/federal-register-api) — rules, proposed rules, notices and the Public Inspection desk with dockets, comment deadlines and CFR references.
- [Academic Papers Search API](https://apify.com/insight.solutions/academic-papers-api) — OpenAlex, Crossref, arXiv and PubMed in one row per paper: abstract, citations, open-access PDF, authors and venue.
- [RSS & Atom Feed Monitor](https://apify.com/insight.solutions/rss-feed-monitor) — any RSS, Atom or JSON feed (or an OPML file) in, only the new items out, with keyword filters and a webhook.
- [Website Change Monitor](https://apify.com/insight.solutions/website-change-monitor) — watch any pages, diff the text between runs, get change rows with added/removed lines, keyword alerts and a webhook.
- [Wikipedia & Wikidata API](https://apify.com/insight.solutions/wikipedia-api) — article text, search, daily pageviews and Wikidata entity facts, any language edition.

**Business, finance & jobs**

- [Congress & Insider Trades API](https://apify.com/insight.solutions/congress-insider-trades-api) — STOCK Act periodic transaction reports and SEC Form 4 insider trades in one schema.
- [Federal Contracts, Grants & Lobbying API](https://apify.com/insight.solutions/federal-contracts-grants-api) — SAM.gov opportunities, USAspending awards, Grants.gov notices and Senate lobbying filings in one schema.
- [SEC EDGAR API](https://apify.com/insight.solutions/sec-edgar-api) — filings, XBRL financials and full-text search by ticker or CIK.
- [Clinical Trials & FDA API](https://apify.com/insight.solutions/clinical-trials-fda-api) — ClinicalTrials.gov studies plus openFDA recalls, labels, approvals, 510(k)s and adverse-event reports.
- [Product & Vehicle Recalls API](https://apify.com/insight.solutions/product-recalls-api) — CPSC, NHTSA, FDA and USDA recalls, vehicle complaints and ratings, plus a VIN decoder.
- [Y Combinator Companies, Batches & Founders](https://apify.com/insight.solutions/yc-companies-directory) — the YC directory with founders and social links, filterable by batch, industry and hiring status.
- [Career Site Jobs API](https://apify.com/insight.solutions/ats-jobs-api) — jobs straight from Greenhouse, Lever, Ashby, Workable and 10+ other ATS career sites.
- [New Job Postings Monitor](https://apify.com/insight.solutions/job-postings-monitor) — new, closed and changed postings on the career sites you watch.
- [Hiring Signals API — Open Roles & Hiring Surge by Company](https://apify.com/insight.solutions/hiring-signals-api) — one row per company per run: open roles, what opened and closed, department and seniority breakdowns, and a hiring-surge flag.
- [Remote Jobs API](https://apify.com/insight.solutions/remote-jobs-api) — RemoteOK, Remotive, We Work Remotely, Himalayas, Jobicy and more in one schema, deduplicated.
- [Shopify Products API](https://apify.com/insight.solutions/shopify-products-api) — any Shopify store's catalogue, variants, prices and stock signals.
- [Shopify Store Monitor](https://apify.com/insight.solutions/shopify-store-monitor) — price drops, sales, restocks, sell-outs and new products on any Shopify store, one row per change.
- [Public Tenders API](https://apify.com/insight.solutions/public-tenders-api) — EU TED, UK Find a Tender and Contracts Finder notices by keyword, CPV code, country, stage and deadline.
- [Nonprofit & IRS 990 Lookup API](https://apify.com/insight.solutions/nonprofit-990-api) — search US nonprofits and get EIN, NTEE code and multi-year Form 990 financials.

**Apps & games**

- [App Store & Google Play Reviews API](https://apify.com/insight.solutions/app-reviews-api) — reviews from both stores with ratings, versions and developer replies.
- [App Store Top Charts & App Search API](https://apify.com/insight.solutions/app-charts-api) — Apple top charts by country and genre, plus app search and details.
- [App Store Keyword Rank Tracker](https://apify.com/insight.solutions/app-store-keyword-rank-tracker) — where any app ranks for any keyword on the App Store and Google Play, with rank changes and ASO suggestions.
- [Steam Reviews API](https://apify.com/insight.solutions/steam-reviews-api) — Steam reviews with playtime, helpfulness and game details.
- [Steam Game Data API](https://apify.com/insight.solutions/steam-store-stats-api) — prices, tags, review scores, live player counts and top charts.

# Actor input Schema

## `categories` (type: `array`):

What to look for, as OpenStreetMap tags: `amenity=cafe`, `shop=bicycle`, `tourism=hotel`, `office=company`, `healthcare=dentist`, `leisure=fitness_centre`, or `craft=*` for every value of a key. Bare names work too — `cafe`, `bicycle`, `hotel`, `fitness centre` — and are looked up in the bundled table of the most-mapped values of amenity, shop, tourism, leisure, office, healthcare and craft (listed in the README). A name that more than one key uses, like `dentist`, searches all of them. Each category is searched in each area separately.

## `areas` (type: `array`):

Cities, districts, regions: `Berlin, Germany`, `Cambridge, UK`, `Kreuzberg, Berlin`. Each name is looked up once on OpenStreetMap's Nominatim geocoder (one request per second, per its usage policy) and turned into a bounding box and, for administrative areas, the exact boundary. Add the country when a name is ambiguous.

## `bboxes` (type: `array`):

`south,west,north,east` in decimal degrees, for example `52.50,13.38,52.52,13.42`. Boxes larger than 0.5° × 0.5° are split into 0.25° tiles queried one after another; boxes needing more than 64 tiles (about 2° × 2°) are refused — split them or name the area.

## `points` (type: `array`):

`lat,lon` in decimal degrees, for example `52.52,13.40`, searched within `radiusMeters`. Places come back nearest first, with `distanceMeters` filled in.

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

How far from each point to search. 50 to 20,000 metres.

## `useAreaBoundary` (type: `boolean`):

When an area name resolves to an administrative boundary (a city, a district), search inside that exact boundary instead of its bounding box — so "Berlin" does not include the edge of Brandenburg. Areas without a boundary always use their bounding box.

## `requireName` (type: `boolean`):

Skip unnamed elements — parking spaces, benches, anonymous vending machines. On by default; turn it off for infrastructure categories where names are rare.

## `keywords` (type: `array`):

Keep only places whose name, brand, cuisine or any tag contains one of these words (case-insensitive). `vegan` matches `diet:vegan=yes`; `starbucks` matches the brand. Places that do not match are never charged.

## `maxPlaces` (type: `integer`):

Stop each category in each area after this many places. 0 means no cap — every place the tiling and `maxRunSecs` allow (up to 5,000 per Overpass tile).

## `reverseGeocode` (type: `boolean`):

For places with no `addr:*` tags at all, ask Nominatim for the nearest address. Paced at one request per second and capped at 200 per run, per Nominatim's usage policy — so it is slow, and off by default.

## `includeRawTags` (type: `boolean`):

Add every OpenStreetMap tag of the place as a `tags` object (minus the personal ones this Actor never emits — see the README).

## `maxRunSecs` (type: `integer`):

Stop starting new queries after this long and finish with what has been collected. 30 to 3,600.

## `proxyConfiguration` (type: `object`):

Overpass and Nominatim answered through the Apify datacenter proxy in testing, which is the default. Every request carries this Actor's own identifying User-Agent whichever proxy you pick.

## Actor input object example

```json
{
  "categories": [
    "amenity=cafe"
  ],
  "areas": [],
  "bboxes": [
    "52.50,13.38,52.52,13.42"
  ],
  "points": [],
  "radiusMeters": 2000,
  "useAreaBoundary": true,
  "requireName": true,
  "keywords": [],
  "maxPlaces": 100,
  "reverseGeocode": false,
  "includeRawTags": true,
  "maxRunSecs": 240,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

One row per place, plus free area and diagnostic rows, all in one schema. Delivered as JSON items in the default dataset.

# 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 = {
    "categories": [
        "amenity=cafe"
    ],
    "areas": [],
    "bboxes": [
        "52.50,13.38,52.52,13.42"
    ],
    "points": [],
    "radiusMeters": 2000,
    "useAreaBoundary": true,
    "requireName": true,
    "keywords": [],
    "maxPlaces": 100,
    "reverseGeocode": false,
    "includeRawTags": true,
    "maxRunSecs": 240,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("insight.solutions/osm-places-api").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 = {
    "categories": ["amenity=cafe"],
    "areas": [],
    "bboxes": ["52.50,13.38,52.52,13.42"],
    "points": [],
    "radiusMeters": 2000,
    "useAreaBoundary": True,
    "requireName": True,
    "keywords": [],
    "maxPlaces": 100,
    "reverseGeocode": False,
    "includeRawTags": True,
    "maxRunSecs": 240,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("insight.solutions/osm-places-api").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 '{
  "categories": [
    "amenity=cafe"
  ],
  "areas": [],
  "bboxes": [
    "52.50,13.38,52.52,13.42"
  ],
  "points": [],
  "radiusMeters": 2000,
  "useAreaBoundary": true,
  "requireName": true,
  "keywords": [],
  "maxPlaces": 100,
  "reverseGeocode": false,
  "includeRawTags": true,
  "maxRunSecs": 240,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call insight.solutions/osm-places-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,insight.solutions/osm-places-api"
        }
    }
}
```

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/i68tbOenQ9O6bVTno/builds/4QLQch5CQhUOeROUH/openapi.json
