# Local Business Leads – OpenStreetMap, Emails & Phones (`dedicated_crest/osm-local-business-leads`) Actor

Find local businesses by category and city: name, address, phone, website, opening hours, coordinates and social links from OpenStreetMap, plus optional emails and phones from each business's own website. Legal Google Maps alternative. $3 per 1,000 leads.

- **URL**: https://apify.com/dedicated_crest/osm-local-business-leads.md
- **Developed by:** [Ben Barazandeh](https://apify.com/dedicated_crest) (community)
- **Categories:** Lead generation, Travel, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 business leads

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

## Local Business Leads – OpenStreetMap, Emails & Phones

Build **local business lead lists by category and city**: plumbers in Denver, dentists in Austin, restaurants in Manchester, lawyers in Lyon. Each lead has the **name, category, full address, phone, website, email, opening hours, GPS coordinates and social links**. You can also turn on **website enrichment**, which visits each business's own website and adds the emails, phone numbers and Facebook/Instagram/LinkedIn/X/YouTube/TikTok links it finds there.

The data comes from **OpenStreetMap** (© OpenStreetMap contributors, ODbL), the open, community-built world map that powers thousands of apps and websites. This Actor does **not** scrape Google Maps, Yelp or any other site that forbids it. No login, no cookies, no proxies, no API key.

**$3 per 1,000 leads.** Website enrichment adds $2 per 1,000 websites it reaches. You only pay for leads you actually get.

### Who is it for?

- **Lead-gen agencies and B2B sales teams** selling to local businesses: web design, SEO, POS, payments, insurance, software, supplies
- **Cold-outreach and CRM building**: email and phone lists for a niche and city
- **Market research and site selection**: count competitors by category and neighbourhood, with coordinates you can map
- **Data and AI teams** that need clean, openly licensed POI data that can be stored and reused (Google Maps data can't)

### Features

- 🗂️ **95 ready-made categories** in plain English (dentist, plumber, hvac, roofer, restaurant, cafe, hair salon, lawyer, accountant, real estate agent, gym, car repair, veterinarian, hotel…) plus **any raw OSM tag** (`shop=bakery`, `craft=*`, `cuisine~pizza`)
- 📍 **Locations as plain text** ("Austin, TX", "Manchester, UK"). The Actor finds the **official city boundary** in OpenStreetMap, so it doesn't pick up the next town over. You can also search a **radius around a lat/lng**.
- 📞 Phone, website, email, opening hours, address parts, coordinates, brand, operator, cuisine, wheelchair access, Wikidata ID, OSM link and last-edit date
- 📧 **Optional website enrichment**: homepage plus up to 4 contact/about/impressum pages. Business's own domain only, **robots.txt respected**, 1 request per second per site, identifiable User-Agent.
- ⭐ **Contact-rich leads first**, so a small `maxItems` still returns the businesses you can actually contact
- 🧹 Filters: only businesses with a phone, website, email or any contact; named businesses only
- ♻️ Retries with exponential backoff and automatic failover between public Overpass servers. Deduplication across categories and locations.
- 💵 Stops cleanly at your **Maximum cost per run**

### How to use it

1. Click **Try for free**.
2. Enter one or more **categories** (e.g. `plumber`, `electrician`) and **locations** (e.g. `Denver, CO`).
3. Optional: turn on **Find emails, phones & social links on the business website**.
4. Run it, then export to CSV, Excel or JSON, or connect it to Google Sheets, HubSpot, Make, Zapier or n8n.

### Input example

```json
{
  "categories": ["plumber", "electrician", "hvac", "roofer"],
  "locations": ["Denver, CO"],
  "enrichWebsites": true,
  "maxItems": 100
}
```

### Output example

Real output (one lead from live run Pg4f6iGnVcPeccHjM, Denver roofers):

```json
{
  "name": "Assurance Contractors",
  "category": "roofer",
  "osmCategory": "craft=roofer",
  "address": "1660 South Albion Street Suite 339, Denver, CO 80222",
  "street": "1660 South Albion Street Suite 339",
  "city": "Denver",
  "state": "CO",
  "postcode": "80222",
  "country": "US",
  "phone": "+1-720-837-1630",
  "phones": [
    "+1-720-837-1630"
  ],
  "email": "service@assurancecontractors.com",
  "emails": [
    "service@assurancecontractors.com"
  ],
  "website": "https://assurancecontractors.com/roofing-denver-co/",
  "openingHours": "Mo-Fr 09:00-17:00; Sa-Su closed",
  "latitude": 39.6863292,
  "longitude": -104.9391307,
  "facebook": null,
  "instagram": null,
  "twitter": null,
  "linkedin": null,
  "youtube": null,
  "tiktok": null,
  "brand": null,
  "operator": "Steve Arends",
  "cuisine": null,
  "description": "Assurance Contractors is a family owned roofing company with offices in Denver and Fort Collins. Our Colorado roots go back to 1981.",
  "wheelchair": null,
  "wikidata": null,
  "osmId": "node/9053239725",
  "osmUrl": "https://www.openstreetmap.org/node/9053239725",
  "googleMapsUrl": "https://www.google.com/maps/search/?api=1&query=Assurance%20Contractors%2039.6863292%2C-104.9391307",
  "lastEditedAt": "2023-09-20T05:33:48Z",
  "searchLocation": "Denver, Colorado, US",
  "searchArea": "Denver (admin level 6)",
  "websiteStatus": "ok",
  "websiteFinalUrl": "https://assurancecontractors.com/roofing-denver-co/",
  "websiteEmails": [
    "info@assurancecontractors.com",
    "info@assurancecontrators.com"
  ],
  "websitePhones": [
    "720-837-1630",
    "970-797-2502",
    "719-313-5901",
    "307-222-5516"
  ],
  "websiteSocials": {},
  "websitePagesFetched": 3,
  "attribution": "© OpenStreetMap contributors, ODbL 1.0 – https://www.openstreetmap.org/copyright",
  "scrapedAt": "2026-10-17T20:41:52.951Z"
}
```

A `SUMMARY` record in the key-value store shows how each location was resolved, the number of OSM objects found and how fresh the OSM data was.

### Real test results

Live runs on Apify, 17 Oct 2026:

| Search | Leads | Phone | Website | Email | Opening hours | Address (street) |
|---|---|---|---|---|---|---|
| Plumbers, electricians, HVAC, roofers in Denver, CO + website enrichment | 32 | 46% | 43% | 25% (12% from OSM tags, the rest added from websites) | 28% | 100% |
| Restaurants + cafés in Manchester, UK, only with phone or website | 200 | 55% | 87% | 17% | 58% | 97% |
| Dentists in Austin, TX + enrichment, Maximum cost $0.05 (stopped at 10 leads + 9 enrichments = $0.048) | 10 | 100% | 100% | 60% | 90% | 100% |
| Roofers/plumbers/electricians in Denver, only with email (enrichment on) | 6 | 100% | 100% | 100% | 66% | 100% |
| `shop=bakery` within 2 km of central Paris (radius search) | 25 | 80% | 88% | 24% | 100% | 60% |

How complete each field is depends on how well local mappers have covered the area. Restaurants, cafés, shops, healthcare and hotels in big cities are usually covered well. Trades (plumbers, roofers) often have fewer entries than Google Maps.

### Pricing

| Event | Price |
|---|---|
| Business lead (saved to dataset) | $0.003 ($3 per 1,000) |
| Website contact enrichment (only when on and the site was reached) | $0.002 ($2 per 1,000) |

For comparison, the popular Google Maps scrapers on the Store charge $4 per 1,000 places, plus $2 per 1,000 for contact details.

### OpenStreetMap vs Google Maps data

| | This Actor (OpenStreetMap) | Google Maps scrapers |
|---|---|---|
| Licence | **ODbL: you may store, reuse and resell with attribution** | Google ToS forbid scraping and storing |
| Ratings and reviews | ❌ not in OSM | ✅ |
| Coverage | Very good in Europe and big cities, uneven for trades in small towns | Most complete |
| Coordinates, hours, website, phone | ✅ where mapped | ✅ |
| Price | $3 per 1,000 | ~$4–6 per 1,000 |

### FAQ

**Is this legal?** Yes. OpenStreetMap data is open under the ODbL licence. You must credit "© OpenStreetMap contributors" when you use it publicly, and if you publish a database derived from it, that database must also be under the ODbL (share-alike). Every item carries an `attribution` field. Website enrichment only reads public pages on the business's own site, follows robots.txt and never logs in. You are responsible for how you use contact data, e.g. GDPR, CAN-SPAM and CASL rules for cold email.

**Which servers does it use?** By default it uses public Overpass API instances whose published usage policy allows use in any project: [VK Maps](https://maps.mail.ru/osm/tools/overpass/) and [Private.coffee](https://overpass.private.coffee/). It does not use overpass-api.de, because that server's policy asks commercial users to self-host or pay. It does not call the public Nominatim geocoder: locations are resolved with Overpass itself. Queries run one at a time with a pause between them. If you run large or frequent jobs, put your own or a paid Overpass endpoint in **Overpass API endpoints**.

**Does it store anything in my account?** Yes, one small thing. Resolved city boundaries are cached in a named key-value store, `osm-local-business-leads-cache`, so repeat runs for the same city need fewer requests to the public servers. You can delete it at any time.

**Why did a run take a few minutes?** The public Overpass servers are often busy and reply "try again later". The Actor waits and retries with exponential backoff, switching between servers, rather than hammering them. A typical city search returns in 1–5 minutes. If the servers stay unavailable for about 10 minutes, the run fails with a clear message and nothing is charged.

**Why are some fields empty?** OpenStreetMap only has what volunteers have mapped. Turn on website enrichment to fill in emails, phones and social links from the business's own website.

**Can I get reviews or ratings?** No. OpenStreetMap does not store them.

**Can I search a whole state or country?** Yes, if you list the cities. Very large areas can time out on the free public servers. Split them into cities, or use your own Overpass endpoint.

### Attribution

Map data © [OpenStreetMap contributors](https://www.openstreetmap.org/copyright), available under the [Open Database License (ODbL) 1.0](https://opendatacommons.org/licenses/odbl/).

# Actor input Schema

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

What kind of businesses to find (or use Custom OpenStreetMap tags below). Plain words, not case-sensitive (plurals OK). Supported: restaurant, cafe, bar, fast food, bakery, ice cream, caterer, brewery, winery, nightclub, hotel, motel, guest house, dentist, doctor, clinic, hospital, pharmacy, veterinarian, physiotherapist, chiropractor, optician, psychologist, nursing home, hair salon, beauty salon, nail salon, barber, massage, spa, tattoo, gym, yoga studio, lawyer, accountant, tax advisor, notary, real estate agent, insurance, financial advisor, bank, architect, it company, marketing agency, consulting, employment agency, coworking, travel agency, moving company, storage rental, plumber, electrician, hvac, roofer, carpenter, painter, locksmith, gardener, photographer, printing shop, tailor, dry cleaner, car repair, car dealer, car wash, car rental, tyre shop, gas station, driving school, language school, music school, kindergarten, school, supermarket, convenience store, butcher, liquor store, florist, clothing store, shoe store, jewelry, furniture, hardware store, electronics, pet store, pet grooming, bookstore, bicycle shop, sports store, gift shop, cosmetics, vape shop, cannabis dispensary, funeral home, wedding venue.

## `locations` (type: `array`):

Cities, towns or neighbourhoods, e.g. "Austin, TX", "Denver, Colorado", "Manchester, UK", "Lyon, France". Adding the state or country picks the right place when names repeat. The search covers the official city boundary when OpenStreetMap has one, otherwise a radius around the town centre.

## `customOsmTags` (type: `array`):

Extra filters as raw OSM tags, e.g. shop=bakery, office=lawyer, craft=\* or cuisine~pizza. See wiki.openstreetmap.org/wiki/Map_features.

## `latitude` (type: `string`):

Optional: search around a point instead of (or as well as) the locations above, e.g. 40.7128.

## `longitude` (type: `string`):

e.g. -74.0060

## `radiusKm` (type: `integer`):

Used with latitude + longitude.

## `onlyWithContact` (type: `string`):

Skip businesses without these details. With website enrichment on, emails/phones found on the website count too.

## `enrichWebsites` (type: `boolean`):

Visits each business's own website (homepage + up to 2 contact/about pages), respecting robots.txt, and adds emails, phone numbers and Facebook/Instagram/LinkedIn/X/YouTube/TikTok links. Charged as a separate event only when the website was reached.

## `maxPagesPerWebsite` (type: `integer`):

Homepage plus contact/about/impressum pages.

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

Skip map objects without a name.

## `sortByCompleteness` (type: `boolean`):

Within each location, return businesses with phone/website/email/address first.

## `includeAllTags` (type: `boolean`):

Adds an osmTags object with every OpenStreetMap tag (payment methods, opening dates, socials, etc.).

## `overpassEndpoints` (type: `array`):

Leave empty to use public instances that allow use in any project (VK Maps, Private.coffee). Put your own or a paid Overpass server here for faster, more reliable large runs.

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

Stop after this many leads. The run also stops cleanly at your Maximum cost per run.

## Actor input object example

```json
{
  "categories": [
    "dentist"
  ],
  "locations": [
    "Austin, TX"
  ],
  "radiusKm": 5,
  "onlyWithContact": "none",
  "enrichWebsites": false,
  "maxPagesPerWebsite": 3,
  "requireName": true,
  "sortByCompleteness": true,
  "includeAllTags": false,
  "maxItems": 50
}
```

# Actor output Schema

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

Business leads

## `summary` (type: `string`):

Locations resolved, counts, attribution

# 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": [
        "dentist"
    ],
    "locations": [
        "Austin, TX"
    ],
    "maxItems": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("dedicated_crest/osm-local-business-leads").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": ["dentist"],
    "locations": ["Austin, TX"],
    "maxItems": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("dedicated_crest/osm-local-business-leads").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": [
    "dentist"
  ],
  "locations": [
    "Austin, TX"
  ],
  "maxItems": 50
}' |
apify call dedicated_crest/osm-local-business-leads --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dedicated_crest/osm-local-business-leads"
        }
    }
}
```

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/CaXtHyEnLdr2XQOD3/builds/2LkOUUbZT0t253Ao6/openapi.json
