Local Business Leads: Emails & Phones from OpenStreetMap
Pricing
from $3.00 / 1,000 leads
Local Business Leads: Emails & Phones from OpenStreetMap
Generate local business leads with phone, email, website and address for any city and category, from OpenStreetMap open data, with optional website enrichment. Commercial use allowed with attribution.
Pricing
from $3.00 / 1,000 leads
Rating
0.0
(0)
Developer
Fetchsmith Labs
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
9 days ago
Last modified
Categories
Share
Find local businesses by city and category and get their phone numbers, email addresses, websites, addresses and opening hours, straight from OpenStreetMap open data. Pick a place ("Potsdam, Germany", "Austin, Texas") and one or more business types (dentists, plumbers, restaurants, hairdressers, lawyers and 30+ more), and the Actor returns a clean, deduplicated list of local business leads with phone numbers normalized to E.164. Optionally it visits each business website (respecting robots.txt) to find emails and phone numbers that OpenStreetMap does not list. Built for local lead generation, sales prospecting, market research, local SEO and directory building.
All data comes from the OpenStreetMap contributor community via the public Overpass API. No login, no API key, no headless browser.
What data you get
One dataset item per business.
| Field | Description |
|---|---|
osmId, osmType | OpenStreetMap id and element type (node, way, relation) |
name | Business name |
category | The category key you searched for (for example dentist), or the raw tag for custom tags (for example craft=plumber) |
osmTags | Relevant classification tags (amenity, shop, craft, office, healthcare, leisure, tourism) |
street, houseNumber, postcode, city, country | Address parts (country is an ISO 3166-1 alpha-2 code) |
fullAddress | Address in one line, ordered according to local convention |
latitude, longitude | Coordinates (center point for buildings and areas) |
phone | First valid phone number in E.164 format, for example +4933160083080 |
phoneRaw | The original OpenStreetMap phone text, only set when it could not be normalized |
email | Email address from OpenStreetMap, lower-cased |
website | Website URL |
openingHours | OpenStreetMap opening_hours string |
socials | Social profile tags such as facebook, instagram, twitter, youtube, linkedin, tiktok (object or null) |
wheelchair | Wheelchair accessibility tag (yes, limited, no) |
emailsFromWebsite, phonesFromWebsite | Emails and E.164 phones found on the business website (only with website enrichment) |
enriched | true when website enrichment found at least one email or phone that OpenStreetMap did not have. This is what the enriched-lead event is billed on |
enrichmentStatus | not_requested, no_website, not_needed, ok, ok_nothing_new, robots_disallowed, blocked, not_found, not_html or error |
osmUrl | Link to the OpenStreetMap object |
searchLocation | The location text you searched for |
source | OpenStreetMap contributors (ODbL) |
scrapedAt | ISO timestamp |
Duplicates are merged: the same business mapped as a point and as a building outline (same name and address, or the same name within 100 m) appears once, with the contact data of both combined. Within one run, the businesses with the richest contact data (email, phone, website) come first, so a low maxItems gives you the best leads.
How to use
- Enter one or more locations as free text, ideally "City, Country".
- Choose categories (dentist, plumber, restaurant, and so on) and optionally custom OSM tags such as
craft=plumber. - Keep Only businesses with contact data on for lead lists, or switch it off to get every mapped business.
- Turn on Require an email address if you only want leads you can email.
- Turn on Enrich from business website to look for missing emails and phones on the websites.
- Set Max businesses and run. Download the dataset as JSON, CSV or Excel.
Supported categories: restaurant, cafe, bar, hotel, dentist, doctor, pharmacy, hairdresser, beauty, car_repair, car_dealer, plumber, electrician, carpenter, painter, roofer, lawyer, accountant, real_estate, insurance, fitness, bakery, florist, optician, veterinary, physiotherapist, architect, it_services, kindergarten, school, supermarket, clothes, furniture, hardware, bicycle. Each maps to the matching OpenStreetMap tags, for example dentist covers amenity=dentist and healthcare=dentist, plumber covers craft=plumber, lawyer covers office=lawyer.
Input parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
locations | string[] | ["Potsdam, Germany"] | Cities, regions or countries as free text, ideally "City, Country" |
categories | string[] | ["dentist"] | Business types from the supported list below |
customTags | string[] | [] | Raw OpenStreetMap tags as key=value, key=* for any value, a|b for alternatives |
onlyWithContact | boolean | true | Only output businesses with a phone, email or website |
requireEmail | boolean | false | Only output businesses with an email address |
enrichFromWebsite | boolean | false | Look for missing emails and phones on the business website (robots.txt respected) |
maxItems | integer | 20 | Total businesses across all locations (1 to 50,000), richest contact data first |
Input example
{"locations": ["Potsdam, Germany"],"categories": ["dentist"],"customTags": [],"onlyWithContact": true,"requireEmail": false,"enrichFromWebsite": false,"maxItems": 20}
Output example
{"osmId": 566647874,"osmType": "node","name": "Small Smile","category": "dentist","osmTags": { "amenity": "dentist", "healthcare": "dentist" },"street": "Berliner Straße","houseNumber": "14","postcode": "14467","city": "Potsdam","country": "DE","fullAddress": "Berliner Straße 14, 14467 Potsdam","latitude": 52.3996481,"longitude": 13.0674676,"phone": "+4933160083080","phoneRaw": null,"email": "info@smallsmile.de","website": "https://smallsmile.de/","openingHours": "\"Termine nach Vereinbarung\"","socials": null,"wheelchair": "limited","emailsFromWebsite": [],"phonesFromWebsite": [],"enriched": false,"enrichmentStatus": "not_requested","osmUrl": "https://www.openstreetmap.org/node/566647874","searchLocation": "Potsdam, Germany","source": "OpenStreetMap contributors (ODbL)","scrapedAt": "2026-10-11T06:49:37.595Z"}
Use the local business leads finder from your code (API)
Every run can be started over the Apify API, so you can refresh lead lists for new cities or categories automatically and push them into your CRM.
Node.js with the apify-client package:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });const run = await client.actor('fetchsmith-labs/local-business-leads').call({locations: ['Munich, Germany'],categories: ['plumber', 'electrician'],requireEmail: true,maxItems: 100,});const { items } = await client.dataset(run.defaultDatasetId).listItems();for (const lead of items) console.log(lead.name, lead.phone, lead.email, lead.website);
Python with the apify-client package:
from apify_client import ApifyClientclient = ApifyClient("YOUR_APIFY_TOKEN")run = client.actor("fetchsmith-labs/local-business-leads").call(run_input={"locations": ["Austin, Texas"],"categories": ["dentist"],"enrichFromWebsite": True,"maxItems": 50,})for lead in client.dataset(run["defaultDatasetId"]).iterate_items():print(lead["name"], lead["phone"], lead["email"] or lead["emailsFromWebsite"])
cURL, synchronous run that returns the dataset items directly:
curl -X POST "https://api.apify.com/v2/acts/fetchsmith-labs~local-business-leads/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"locations": ["Potsdam, Germany"], "categories": ["hairdresser"], "maxItems": 20}'
Results can also go straight to Google Sheets, HubSpot, Make, Zapier, n8n or a webhook through the Apify integrations on the Actor page. Need more contacts per lead? Pass the website values to the Website Contact Extractor Actor from Fetchsmith Labs to get all emails, phones, social profiles and imprint data per site.
Pricing
Pay per event, you only pay for results:
| Event | Price | When it is charged |
|---|---|---|
lead | $0.003 | For every business written to the dataset |
enriched-lead | $0.003 | Extra, only when website enrichment found at least one new email or phone for that business |
Example: 1,000 businesses cost $3.00. If website enrichment finds new contact data for 300 of them, add $0.90, so $3.90 in total. If you set a maximum spend per run, the Actor stops cleanly when the limit is reached. Platform usage (compute) is kept very low because the Actor only makes HTTP requests.
How it works and data coverage
- Each location is resolved to an OpenStreetMap area with Nominatim (at most one request per second).
- One Overpass API query per location fetches all matching businesses that have a name. The Actor runs one query at a time and retries with backoff on rate limits and timeouts, rotating across four public Overpass servers within a fixed time budget, so an overloaded server cannot stall the run.
- Elements are mapped, phones are normalized with the country of the location, duplicates are merged and filtered.
- Optional enrichment fetches the homepage and one or two obvious contact or imprint pages (HTTP only, 10 second timeout, 5 websites in parallel).
OpenStreetMap is volunteer-maintained, so coverage differs by country and category. In our test runs with onlyWithContact switched off, the share of mapped businesses with a phone, email or website was:
| Search | Businesses | With phone | With email | With website |
|---|---|---|---|---|
| Dentists, Potsdam | 73 | 82% | 51% | 70% |
| Restaurants, Potsdam | 234 | 72% | 36% | 74% |
| Hairdressers, Potsdam | 127 | 57% | 25% | 46% |
| Dentists, Austin (Texas) | 119 | 45% | 13% | 45% |
| Restaurants, Austin (Texas) | 1,114 | 43% | 6% | 51% |
Expect strong coverage in Germany and much of Europe, and thinner contact data for the United States. Website enrichment helps most where a website exists but the email is missing.
OpenStreetMap license and attribution (ODbL)
The data is (c) OpenStreetMap contributors and available under the Open Database License (ODbL) 1.0. You may use it commercially, including for sales and marketing, under these conditions:
- Attribution: credit "OpenStreetMap contributors" wherever you publish or share the data. Every item carries
source: "OpenStreetMap contributors (ODbL)". - Share-alike for databases: if you publicly distribute a database derived from this data, that derived database must also be offered under the ODbL. Using the data internally, in a CRM or for outreach does not trigger this.
- Details: https://www.openstreetmap.org/copyright
Website enrichment data (emailsFromWebsite, phonesFromWebsite) comes from the business pages themselves and is not part of the OpenStreetMap database.
Use cases
- Build local lead lists for agencies, freelancers and B2B sales teams.
- Find tradespeople, clinics or shops in a region for market research.
- Seed a local directory or comparison site with names, addresses and opening hours.
- Check competitor density by category and city.
- Prepare territory planning with coordinates for any category.
FAQ
Is this legal? The Actor only reads public, openly licensed OpenStreetMap data through the documented Overpass and Nominatim APIs, and optionally public business web pages whose robots.txt allows access. Business contact details are public information, but how you use them (for example cold email) is subject to the laws that apply to you, such as GDPR and e-privacy rules in the EU. You are responsible for lawful use.
Does website enrichment bypass blocks? No. It respects robots.txt, identifies itself honestly, and treats 403, 429 and bot-protection pages as "blocked" for that business without retrying or working around them.
Why are there few results for my search? The Actor only returns what volunteers mapped. Try a larger area, more categories, a neighbouring city, or switch off onlyWithContact.
Why does my location not resolve? Use a clear place name such as "Potsdam, Germany". If nothing can be resolved the run fails with a message naming the locations that did not work.
How many results can I get? maxItems is the total across all locations. Very large areas (whole countries) with common categories can be slow, because the Overpass server has to select every match first. Prefer cities or regions.
Does it include people? No. It covers businesses and organizations as published in OpenStreetMap, not private individuals.
Can I export the leads to CSV or Excel? Yes. Open the run's Storage tab and download the dataset as CSV, Excel, JSON, XML or HTML. Nested fields such as socials and osmTags are flattened into columns.
How long does a run take? Most city and category searches finish in under a minute. Busy public Overpass servers can add a few minutes; website enrichment adds roughly one to three seconds per business with a website.
Limitations
- Coverage depends on OpenStreetMap contributors and varies by country and category.
- Phone numbers that cannot be validated are not normalized (see
phoneRaw). - Only public Overpass servers are used, so very large queries can hit their fair-use limits. The Actor backs off and retries, then reports a clear error.
- Locations that resolve to a single point or street (not an area) are searched in a small bounding box around the point.
- Website enrichment reads server-rendered HTML only; emails hidden behind JavaScript, images or forms are not found, and sites that disallow robots or block automated access are skipped.
Support
Questions, missing categories or a bug? Open an issue from the Actor page in Apify Console.