# Google Maps Business Directory (`joseolmedosotoaguirre/google-maps-business-directory`) Actor

Search Google Maps by query + location and extract PUBLIC business listing data for market research: name, category, address, rating, review count, website, phone, and opening hours.

- **URL**: https://apify.com/joseolmedosotoaguirre/google-maps-business-directory.md
- **Developed by:** [jose olmedo soto aguirre](https://apify.com/joseolmedosotoaguirre) (community)
- **Categories:** Lead generation, Travel, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#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

## Google Maps Business Directory

Extract **public business listings** from Google Maps by search query + location/zone. Built for **market research** and **B2B lead generation** in Colombia and LatAm.

> **Ethics & scope:** This actor collects only **public business attributes** shown on Google Maps listing cards/panels (name, category, address, rating, review count, website, business phone if shown, opening hours). It is **not** designed to harvest personal contacts, private profiles, or emails. Use responsibly, respect Google’s Terms of Service, and apply rate limits.

***

### What you get

| Field | Description |
| --- | --- |
| `placeId` | Google place identifier when available |
| `name` | Business name |
| `category` | Category / type (when shown) |
| `address` | Public address |
| `rating` | Star rating (e.g. `4.5`) |
| `reviewCount` | Number of reviews |
| `website` | Public website URL (if listed) |
| `phone` | Business phone shown on the listing (if listed) |
| `openingHours` | Hours snippet if visible |
| `mapsUrl` | Google Maps URL |
| `searchQuery` / `location` | Your input echo |
| `scrapedAt` | ISO timestamp |

Results are **deduplicated** by `placeId`, or by `name + address` when `placeId` is missing.

***

### Input

| Field | Required | Default | Notes |
| --- | --- | --- | --- |
| `searchQuery` | ✅ | — | e.g. `cafeterías`, `gimnasios`, `coworking` |
| `location` | ✅ | — | e.g. `Bogotá, Colombia`, `Chapinero, Bogotá` |
| `maxResults` | | `20` | Max **100** |
| `language` | | `es` | `es` / `en` / `pt` |
| `proxyConfiguration` | | Apify Proxy on | Recommended for Google Maps |

#### Example input

```json
{
  "searchQuery": "cafeterías",
  "location": "Bogotá, Colombia",
  "maxResults": 10,
  "language": "es",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

***

### Sample output (real run)

Search: **cafeterías** in **Bogotá, Colombia** (`maxResults: 10`) — local `apify run`, 2026-07-29. Extracted **10** unique businesses.

```json
{
  "placeId": "0x8e3f9aa7c7d75f0f:0xac7b506ab04e46e7",
  "name": "Café San Alberto Usaquén",
  "category": "Cafetería",
  "address": "Cl. 117 # 6A-47 6a",
  "rating": 4.6,
  "reviewCount": null,
  "website": "http://www.cafesanalberto.com/",
  "phone": "317 5026246",
  "openingHours": "Cerrado",
  "mapsUrl": "https://www.google.com/maps/place/Café+San+Alberto+Usaquén/...",
  "searchQuery": "cafeterías",
  "location": "Bogotá, Colombia",
  "scrapedAt": "2026-07-29T04:32:32.343Z"
}
```

Other names from the same run: *Érase una vez café de especialidad*, *Azahar Café*, *Gracia - Coffee & Brunch*, *Café Cécile*, *Café Mundano*, *Arte y pasión Café*, *Casa Galería*, *Café Amor Perfecto Chapinero Alto*, *Juan Valdez - Zona G*.

***

### Use cases

- Competitive map of cafés, restaurants, gyms, clinics, or retail in a city/zone
- Density / coverage analysis for expansion (e.g. Bogotá neighborhoods)
- B2B outreach lists of **businesses** (website + public business phone only)
- Enrich market research decks with ratings and review volume

***

### How it works

1. Opens Google Maps search for `searchQuery` + `location`
2. Scrolls the results feed with **concurrency 1** and **3–5s delays**
3. Extracts public card/panel fields with resilient selectors
4. Deduplicates and pushes structured dataset items
5. Optionally enriches a small subset by opening place panels (website / phone / hours)

Stack: **Apify SDK + Crawlee + Playwright**, **Apify Proxy**, Docker image `apify/actor-node-playwright-chrome`.

***

### Pricing (suggested)

| Plan | Price | Best for |
| --- | --- | --- |
| Pay per result | **$1.50 – $3.00 / 1,000 places** | Occasional market maps |
| Rental | **$29 – $49 / month** | Agencies & recurring research |

Configure in Apify Console → Actor → **Publication → Pricing**.

Recommended compute: start with **$1.50–2.00 / 1,000 results** for list-only scrapes; closer to **$3.00** if you enable heavier enrichment.

***

### Local development

```bash
cd google-maps-business-directory
npm install --registry https://registry.npmjs.org/
## Ensure APIFY_TOKEN is available (parent ../.env or export)
export $(grep -v '^#' ../.env | xargs)
apify run
```

Input for local runs: `storage/key_value_stores/default/INPUT.json`.

Push to Apify:

```bash
export $(grep -v '^#' ../.env | xargs)
apify push
```

***

### Responsible use

- Only **public business** listing data
- Do **not** use this actor to collect personal emails or private contact databases
- Keep `maxResults` reasonable; concurrency is fixed at **1** with delays
- Comply with Google Terms of Service and applicable privacy laws (e.g. Colombia’s Law 1581 / Habeas Data for any downstream CRM use of business contacts)

***

### Limitations

- Google Maps UI changes can break selectors; the actor fails gracefully and logs warnings
- CAPTCHA / soft blocks may reduce yield — use Apify Proxy (residential if needed)
- Not every listing shows website, phone, or hours
- `maxResults` capped at **100** per run

***

### Support

Built for Colombian / LatAm market research workflows. Open an issue on the Actor page or contact the publisher on Apify.

# Actor input Schema

## `searchQuery` (type: `string`):

What to search for on Google Maps (e.g. "cafeterías", "restaurantes", "gimnasios", "coworking").

## `location` (type: `string`):

City, neighborhood, or zone to search in (e.g. "Bogotá, Colombia", "Medellín, Colombia", "Chapinero, Bogotá").

## `maxResults` (type: `integer`):

Maximum number of unique business listings to extract (1–100).

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

Google Maps UI language (hl parameter). Use "es" for Spanish, "en" for English.

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

Apify Proxy settings. Residential or datacenter proxies recommended for Google Maps.

## Actor input object example

```json
{
  "searchQuery": "cafeterías",
  "location": "Bogotá, Colombia",
  "maxResults": 20,
  "language": "es",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

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

Items pushed to 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 = {
    "searchQuery": "coffee",
    "location": "Bogotá, Colombia",
    "maxResults": 5,
    "language": "es",
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("joseolmedosotoaguirre/google-maps-business-directory").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 = {
    "searchQuery": "coffee",
    "location": "Bogotá, Colombia",
    "maxResults": 5,
    "language": "es",
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("joseolmedosotoaguirre/google-maps-business-directory").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchQuery": "coffee",
  "location": "Bogotá, Colombia",
  "maxResults": 5,
  "language": "es",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call joseolmedosotoaguirre/google-maps-business-directory --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=joseolmedosotoaguirre/google-maps-business-directory",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/rwTfdQj1px6X0Ojjz/builds/rssWXFv5pW6tL9D7M/openapi.json
