# Local Business Leads from Google Maps: Phones & Emails (`vncntlabs/local-business-leads`) Actor

Google Maps lead generation without a browser: local business leads by category and city with name, phone, website, address, hours, rating and reviews. 1,000 leads in seconds, filters for rating, reviews, claimed/unclaimed profile and no-website businesses, optional business emails. Pay per lead.

- **URL**: https://apify.com/vncntlabs/local-business-leads.md
- **Developed by:** [vncntlabs Labs](https://apify.com/vncntlabs) (community)
- **Categories:** Lead generation, Marketing, SEO tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 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 from Google Maps: phones, websites and emails by category and city

**Build local business lead lists from Google Maps data in seconds:** dentists in Austin, plumbers in Manchester, restaurants in Munich. For every business you get name, category, phone, website, address, opening hours, Google rating and review count, claimed status and a Google Maps link, with filters for rating, reviews, claimed or unclaimed profile, website or no website, and open status, plus optional business emails.

Made for **agencies** prospecting local clients, **B2B sales teams** building territory lists, and **local
marketers** sizing a market. 1,000 leads per location come back in a few seconds, not minutes, because the data is
served from DataForSEO's licensed Google Business Profile database instead of a live browser crawl.

### What you get

| Field | Example |
|---|---|
| `name`, `category`, `additionalCategories` | Acme Dental, Dentist, \[Cosmetic dentist, ...] |
| `phone`, `website`, `domain` | `+15125550100`, `https://acme-dental.com/`, `acme-dental.com` |
| `address`, `street`, `city`, `zip`, `countryCode` | 123 Main St, Austin, TX 78701 |
| `rating`, `reviews`, `isClaimed`, `businessStatus` | 4.9, 812, true, operational |
| `openingHours`, `priceLevel` | Mon 08:00-17:00; ...; Sun closed |
| `latitude`, `longitude`, `distanceKm` | distance from the searched location's center |
| `placeId`, `cid`, `mapsUrl` | Google identifiers and a Maps link to check the listing |
| `lastUpdated`, `firstSeen` | when the listing data was last refreshed |
| `emails`, `email` (optional) | `info@acme-dental.com` |

Plus one `location` row per searched location (businesses available, delivered, opted-out, duplicates) and a run
summary in `OUTPUT`. Views: **Leads**, **Contacts (CRM import)**, **Details**, **Locations searched**. Export as CSV,
Excel or JSON, or pull it through the Apify API, MCP, Zapier or Make.

### Input examples

Dentists in two cities, 4.0+ rating, with a phone number:

```json
{"categories": ["dentist"], "locations": ["Austin, TX", "Dallas, TX"], "minRating": "4", "requirePhone": true,
 "maxLeadsPerLocation": 500}
```

Plumbers and electricians within 25 km of Manchester, with business emails:

```json
{"categories": ["plumber", "electrician"], "locations": ["Manchester, UK"], "radiusKm": 25,
 "includeBusinessEmails": true}
```

Web-design and local SEO prospects: plumbers with **no website** and an **unclaimed** Google profile:

```json
{"categories": ["plumber"], "locations": ["Phoenix, AZ"], "onlyWithoutWebsite": true, "onlyUnclaimed": true}
```

Any business named "*pediatric*" around a point:

```json
{"nameContains": "pediatric", "locations": ["30.2672,-97.7431"], "radiusKm": 15}
```

Locations: `City, Region` or `City, Country` (`Austin, TX`, `Toronto, ON`, `Manchester, UK`, `München`) or
`latitude,longitude`. Categories: Google's own business categories in plain words (`dentist`, `hvac`, `pizza
restaurant`, `real estate agency`); plurals and common synonyms work, and unknown ones are reported with suggestions.

### Pricing (pay per event)

| Event | When it is charged |
|---|---|
| Actor start | once per run |
| `lead` | one business delivered to your dataset |

Permanently closed businesses, duplicates across your locations, opted-out businesses, businesses dropped by "only
with a business email", and failed requests are **never charged**. Set a maximum charge per run and the run stops
there (it requests only as many rows as your limit covers).

**Apify free plan:** 20 leads from 1 location per run, so you can test it on your own city. Any paid Apify plan
unlocks up to 50 locations and 5,000 leads per location per run.

### Data and privacy

**Data and privacy.** This Actor returns publicly listed **business** information from Google Business Profiles
(name, category, address, business phone, website, hours, rating), delivered through DataForSEO's licensed Business
Listings data. It does not return reviewer data, owner names or personal social profiles.
Business emails are optional and off by default. When enabled, only addresses on the business's own website domain
are returned; free-mail and personal-looking addresses are removed, and for businesses in the EU, EEA and UK only
role addresses (such as info@ or contact@) are returned.

**You are responsible for how you use the data.** If you contact businesses, follow the rules that apply to you,
for example GDPR and the ePrivacy/PECR rules in the EU and UK (which can require prior consent for marketing emails
to sole traders and individuals), CAN-SPAM in the US and CASL in Canada. Always offer an unsubscribe and honor it.

**Opt-out.** A business that wants to be excluded from this Actor's results can send its Google Maps link or website
to the opt-out contact hello@vncntlabs.com. We add it to a suppression list applied to all future runs, usually within 7 days.

> EU/EEA/UK businesses: only role email addresses (info@, contact@...) on the business's own domain are returned.
> Marketing emails to sole traders and individuals may require prior consent under GDPR/ePrivacy (PECR in the UK).

### FAQ

**How fresh is the data?** It is a regularly refreshed database of Google Business Profiles, not a live crawl; most
listings were refreshed within the last few months. Every row has `lastUpdated`, and `mapsUrl` opens the live
listing. Permanently closed businesses are removed.

**How complete is it?** In our test of 6 city/category pairs (Austin, Manchester, Munich; dentists and plumbers),
55 of the top 60 businesses on live Google Maps were in the data; the missing ones were brand-new or spam-style
listings.

**Why do some businesses have no email?** Emails come from what the business publishes and are filtered strictly
(own domain, no free-mail, no personal names, role-only in Europe). Typically 20-30% of businesses have one.

**Can I get reviews, owner names or photos?** No. This tool returns business data only.

**Why is `websiteIsSocialProfile` true?** The business lists a Facebook/Instagram page as its website; emails are
never matched against social domains.

City names: GeoNames (geonames.org), CC BY 4.0. Google and Google Maps are trademarks of Google LLC, named only for
description; this Actor is not affiliated with or endorsed by Google.

# Actor input Schema

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

Google business categories, e.g. <code>dentist</code>, <code>plumber</code>, <code>pizza restaurant</code>, <code>real estate agency</code> (plurals and common synonyms work). Up to 10 per run; a business matching any of them is returned once.

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

Cities as <code>City, Region</code> or <code>City, Country</code> (e.g. <code>Austin, TX</code>, <code>Manchester, UK</code>, <code>München</code>), or a point as <code>latitude,longitude</code>. Up to 50 per run. Each is searched within the radius below.

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

Search radius around each location's center. Cities: 10–25 km covers most metro areas.

## `maxLeadsPerLocation` (type: `integer`):

Stop after this many leads per location. You pay only for leads delivered.

## `nameContains` (type: `string`):

Optional keyword that must appear in the business name, e.g. <code>pediatric</code>. Can be used instead of categories.

## `minRating` (type: `string`):

Only businesses with at least this Google rating.

## `minReviews` (type: `integer`):

Only businesses with at least this many Google reviews.

## `onlyClaimed` (type: `boolean`):

Only businesses whose owner has claimed the Google Business Profile.

## `onlyUnclaimed` (type: `boolean`):

Only businesses whose Google Business Profile has not been claimed by the owner: prospects for profile-management and local SEO services.

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

Skip businesses without a phone number (filtered at the source, never charged).

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

Skip businesses without a website (filtered at the source, never charged).

## `onlyWithoutWebsite` (type: `boolean`):

Only businesses with no website on their Google profile: prospects for web-design agencies. Emails are not available for these (they must match the business's own domain).

## `excludeTemporarilyClosed` (type: `boolean`):

Permanently closed businesses are always excluded.

## `sortBy` (type: `string`):

Which businesses come first when a location has more than your maximum.

## `includeBusinessEmails` (type: `boolean`):

Off by default. When on, only addresses on the business's own website domain are returned; free-mail and personal-looking addresses are removed. <b>EU/EEA/UK businesses: only role email addresses (info@, contact@...) on the business's own domain are returned. Marketing emails to sole traders and individuals may require prior consent under GDPR/ePrivacy (PECR in the UK).</b>

## `requireEmail` (type: `boolean`):

Turns on business emails and keeps only businesses that have one after filtering (others are not charged).

## `includeOpeningHours` (type: `boolean`):

Weekly hours as text, e.g. Mon 09:00-17:00; ...; Sun closed.

## Actor input object example

```json
{
  "categories": [
    "dentist"
  ],
  "locations": [
    "Austin, TX"
  ],
  "radiusKm": 10,
  "maxLeadsPerLocation": 50,
  "minRating": "any",
  "onlyClaimed": false,
  "onlyUnclaimed": false,
  "requirePhone": false,
  "requireWebsite": false,
  "onlyWithoutWebsite": false,
  "excludeTemporarilyClosed": true,
  "sortBy": "reviews",
  "includeBusinessEmails": false,
  "requireEmail": false,
  "includeOpeningHours": true
}
```

# Actor output Schema

## `leads` (type: `string`):

No description

## `contacts` (type: `string`):

No description

## `locations` (type: `string`):

No description

## `all` (type: `string`):

No description

## `run` (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 = {
    "categories": [
        "dentist"
    ],
    "locations": [
        "Austin, TX"
    ],
    "maxLeadsPerLocation": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("vncntlabs/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"],
    "maxLeadsPerLocation": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("vncntlabs/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"
  ],
  "maxLeadsPerLocation": 50
}' |
apify call vncntlabs/local-business-leads --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,vncntlabs/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/cMltmdRk2aP1fFXhY/builds/googzdV0VdxYjW4pv/openapi.json
