# Google Maps Leads Scraper – Multi-City Business Lead Lists (`locomint/multi-city-lead-list-builder`) Actor

Pick business categories and a list of cities - anywhere in the world - and get one deduplicated lead list: name, phone, website, rating, hours, plus business emails, social profiles and WhatsApp from each website. Free filters, flat price per lead.

- **URL**: https://apify.com/locomint/multi-city-lead-list-builder.md
- **Developed by:** [Umaid Ali](https://apify.com/locomint) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 results

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Multi-City Lead List Builder

Pick your **business categories**, paste your **list of cities** - anywhere in the
world - and get **one deduplicated lead list** with every business's phone, website,
rating, opening hours, and the contact points from its website: business emails,
Facebook / Instagram / LinkedIn / X / YouTube / TikTok, WhatsApp.

- 🌍 **Any city, any country.** 25 categories × 50 cities per run, up to 500 leads per
  search. Whole-city coverage, not just the first page of results.
- 📬 **Contacts included.** Emails, socials and WhatsApp are pulled from each business
  website at no extra charge. No add-ons.
- 🧹 **One row per business.** A gym that also matches "fitness centre" is delivered and
  charged once. Every row says which city and category found it.
- 🆓 **Free filters.** Minimum rating, only with / without a website, skip closed
  places, category words. Filtered-out places cost nothing.
- 💵 **One flat price per lead.** Nothing else.

***

### 🎯 Who is it for?

- **Agencies and freelancers** building outreach lists city by city.
- **SaaS and local marketplaces** seeding supply in new cities.
- **Sales teams** who want "every dentist in these 12 cities" in a spreadsheet by lunch.
- **Web designers**: `websiteFilter = without` gives you every business with no website.

***

### ▶️ How to use it

1. Enter categories, one per line: `dentist`, `physiotherapist`.
2. Enter cities with the country: `Lisbon, Portugal`, `Porto, Portugal`.
3. Set the cap per search and any filters. Run.
4. Download as CSV / Excel / JSON, or push to Google Sheets, Zapier, Make.

### ⚙️ Input

| Field | Type | Default | Notes |
|---|---|---|---|
| `categories` | string\[] | – | Up to 25 |
| `cities` | string\[] | – | "City, Country"; up to 50 (100 searches per run max) |
| `maxPlacesPerCombination` | integer | 20 | Per city × category, up to 500 |
| `placeMinimumStars` | string | – | e.g. `"4"`; unrated places are skipped |
| `websiteFilter` | string | `any` | `with` / `without` |
| `skipClosedPlaces` | boolean | false | |
| `categoryFilterWords` | string\[] | – | Keep places whose category contains a word |
| `includeDetails` | boolean | true | Description, weekly hours, plus code, timezone, photos, attributes |
| `includeEnrichment` | boolean | true | Emails, socials, WhatsApp, contact page, tech stack from the website |
| `language` | string | `en` | Any BCP-47 code |

### 🧾 Output

Every row is a full business record - the same fields as *Locomint - Local Business
Data* - plus `search_city` and `search_category`:

```json
{
  "place_id": "ChIJ…", "name": "Clínica Dentária Central", "categories": ["Dentist"],
  "address": "Av. da Liberdade 10, 1250-096 Lisboa", "city": "Lisbon", "country_code": "PT",
  "lat": 38.72, "lng": -9.14, "phone": "+351 21 000 0000", "website": "https://…",
  "rating": 4.8, "reviews_count": 231, "status": "open",
  "hours": {"monday": [{"open": "09:00", "close": "19:00"}], "…": "…"},
  "emails": ["geral@clinica.pt"], "socials": {"instagram": "https://www.instagram.com/…"},
  "whatsapp": "+351910000000",
  "search_city": "Lisbon, Portugal", "search_category": "dentist"
}
```

***

### 💰 Pricing

Flat price per lead delivered, enrichment included. Compare: other tools charge a
base price plus $1 per 1,000 for *each* filter and again for contact details.

***

### 🛡️ What it deliberately does not do

- **No owner names, no personal emails.** Business contact points only. Data-removal
  requests: hello@locomint.io.
- **No bypassing.** Rate-limited, polite fetching; if the source pushes back we back
  off - we never retry through another IP.
- **No mixing cities up.** Results outside the resolved city area are dropped
  (a "Lagos, Nigeria" search will never hand you Lagos, Portugal).

***

### ❓ FAQ

**How many leads will I get?** Up to `maxPlacesPerCombination` per city × category,
minus filters and duplicates. Big categories in big cities reach the cap; niche ones
return what exists.

**Can I run the same list monthly?** Yes - schedule it. Place IDs are stable, so you
can diff runs to find new businesses.

**Why must cities include the country?** "Warsaw" alone can resolve to Warsaw,
Indiana. "Warsaw, Poland" cannot.

***

### 🧑‍💻 Support

Issues tab, or hello@locomint.io. See also *Locomint - Local Business Data* (single
city, more options) and *Business Record Enricher* (you already have the IDs).

# Actor input Schema

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

What kind of businesses, e.g. "dentist", "gym", "car rental". Each category is searched in every city. Up to 25.

## `cities` (type: `array`):

One per line, always with the country: "Lisbon, Portugal", "Dubai, UAE". Up to 50 cities; up to 100 city x category searches per run.

## `maxPlacesPerCombination` (type: `integer`):

Upper limit per search. You pay per lead delivered; a lead matching two categories is delivered and charged once.

## `placeMinimumStars` (type: `string`):

Only deliver places rated at least this. Places without a rating are skipped. Free - filtered places are not charged.

## `websiteFilter` (type: `string`):

Only places with a website (good for enrichment) or only places without one (good for web-design outreach).

## `skipClosedPlaces` (type: `boolean`):

Leave out places marked temporarily or permanently closed.

## `categoryFilterWords` (type: `array`):

Keep only places whose category contains at least one of these words, e.g. \["dentist", "orthodontist"]. Case-insensitive.

## `includeDetails` (type: `boolean`):

Adds description, weekly opening hours, plus code, timezone, photos and attributes for each place. Included in the price.

## `includeEnrichment` (type: `boolean`):

Visits each business's own website to extract business emails, social profiles, WhatsApp, contact page and tech stack. Included in the price. Never collects personal data.

## `language` (type: `string`):

BCP-47 language for names and categories (en, ar, de, ja, ...).

## Actor input object example

```json
{
  "categories": [
    "dentist"
  ],
  "cities": [
    "Lisbon, Portugal"
  ],
  "maxPlacesPerCombination": 5,
  "placeMinimumStars": "",
  "websiteFilter": "any",
  "skipClosedPlaces": false,
  "includeDetails": true,
  "includeEnrichment": true,
  "language": "en"
}
```

# Actor output Schema

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

One row per business, deduplicated across cities and categories: identity, location, contact, reputation, hours, website enrichment, plus search\_city and search\_category.

# 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"
    ],
    "cities": [
        "Lisbon, Portugal"
    ],
    "maxPlacesPerCombination": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("locomint/multi-city-lead-list-builder").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"],
    "cities": ["Lisbon, Portugal"],
    "maxPlacesPerCombination": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("locomint/multi-city-lead-list-builder").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"
  ],
  "cities": [
    "Lisbon, Portugal"
  ],
  "maxPlacesPerCombination": 5
}' |
apify call locomint/multi-city-lead-list-builder --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,locomint/multi-city-lead-list-builder"
        }
    }
}

```

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/76Vzti9jKM6PENPju/builds/W9GxuCzPWf7XVFzIx/openapi.json
