# Google Maps Place Matcher: Business Lookup by Name & Address (`scrapebench/google-maps-place-matcher`) Actor

Match a messy list of business names and addresses to Google Maps: place ID, clean address, coordinates, phone, website, rating and reviews per row. A wrong house number or name is never billed.

- **URL**: https://apify.com/scrapebench/google-maps-place-matcher.md
- **Developed by:** [ScrapeBench](https://apify.com/scrapebench) (community)
- **Categories:** Lead generation
- **Security:** Limited permissions
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.0015 / place matched

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

## Google Maps Place Matcher: Business Lookup by Name & Address

### Pain points

- A lead list or CRM export holds the same business three ways ("Starbucks", "STARBUCKS #1234", "Starbucks Coffee Lafayette"), so you cannot dedupe or enrich it without a shared key.
- Google's Places API needs a Cloud project, a billing account and an API key, and new projects can no longer turn on the legacy Places API.
- Taking a search's first answer as the match fills a list with the wrong business at a similar address, and you only notice when a sales rep calls it.
- Looking businesses up one at a time in Google Maps to copy a phone number and address takes minutes per row.

### What we solve

- One Google place ID per business, the key to dedupe a list and join it to anything else keyed on Google Maps.
- A check before billing: a house number that does not match, or a name that does not fit, is a free no-match row, never a charged near-miss.
- No API key, no Google Cloud account: send names and addresses, get places.
- Your own id goes in and comes back out, so the result joins straight back to your spreadsheet or CRM.

### Summary

Paste the lines of a CRM export, a lead list or a spreadsheet, as messy as they are ("starbucks lafayette ca 94549", "Blue Bottle Coffee 480 9th St Oakland", an address on its own), or send rows with a name, address, city and your own id. For each one the actor asks Google Maps, then checks Google's answer before it bills: every house number you gave must be in the place's address, and the name you gave must fit the place's name. A match comes back as one row with Google's place ID, the name and address as Google Maps writes them (street, city, state and ZIP split out), latitude and longitude, phone, website, rating, review count, categories, a Google Maps link, how it matched and your id. An input that fits nothing comes back as a free row that names the closest places Google offered, so a wrong place never lands in your list as a match.

### Who it's for

- Sales and RevOps teams cleaning a CRM or a purchased lead list
- Data teams that need a Google place ID per business to dedupe or join records
- Marketing agencies building local campaigns from messy client lists
- Developers replacing a Places API lookup with a no-key alternative

### How to use

Set the input, run the actor, and collect results from the run's dataset (export to JSON/CSV/Excel, or pull via the Apify API). Example input:

```json
{
  "queries": [
    "Blue Bottle Coffee 480 9th St Oakland",
    "starbucks lafayette ca 94549",
    "1600 Amphitheatre Pkwy Mountain View CA"
  ]
}
```

See **Inputs** below for every available field.

### What you get

One row per record:

| Field | Description |
|---|---|
| `input` | What was looked up (your line, or a row's fields joined) |
| `input_id` | The id you gave the row, echoed back |
| `place_id` | Google's own place ID |
| `name` | The place's name on Google Maps |
| `address` | Full address as Google Maps writes it |
| `street` | Street line(s) |
| `city` | City |
| `state` | Two-letter state code |
| `zip_code` | 5-digit ZIP code |
| `latitude` | Latitude |
| `longitude` | Longitude |
| `phone` | Phone number as Google Maps lists it |
| `website` | The website the place lists on Google Maps |
| `rating` | Google rating, 1 to 5 |
| `review_count` | Number of Google reviews |
| `categories` | Google Maps categories, primary first |
| `google_maps_url` | Opens the place on Google Maps |
| `matched_by` | name + address, name, or address: what Google's answer was checked against |
| `confidence` | high: Google answered this one place; medium: Google's first of several; low: a later one of several |
| `other_matches` | Up to 4 other places Google answered for the same input (name, address, place ID) |
| `source_url` | The place's Google Maps link |

Sample:

```json
{
  "input": "Blue Bottle Coffee 480 9th St Oakland",
  "input_id": null,
  "place_id": "ChIJLRIbILeAj4ARyWoMWFQmkSY",
  "name": "Blue Bottle Coffee",
  "address": "480 9th St, Oakland, CA 94607",
  "street": "480 9th St",
  "city": "Oakland",
  "state": "CA",
  "zip_code": "94607",
  "latitude": 37.8012466,
  "longitude": -122.2739477,
  "phone": "(510) 653-3394",
  "website": "https://bluebottlecoffee.com/us/eng/northern-california-cafes?utm_source=google&utm_medium=organic&utm_campaign=cafe_business_listing_norcal",
  "rating": 4.4,
  "review_count": 396,
  "categories": [
    "Coffee shop"
  ],
  "google_maps_url": "https://www.google.com/maps/search/?api=1&query=Blue%20Bottle%20Coffee&query_place_id=ChIJLRIbILeAj4ARyWoMWFQmkSY",
  "matched_by": "name + address",
  "confidence": "high",
  "other_matches": [],
  "source_url": "https://www.google.com/maps/search/?api=1&query=Blue%20Bottle%20Coffee&query_place_id=ChIJLRIbILeAj4ARyWoMWFQmkSY"
}
```

### Inputs

| Field | Required | Type | Default | Description |
|---|---|---|---|---|
| `queries` | no | array | `["Blue Bottle Coffee 480 9th St Oakland", "starbucks lafayette ca 94549", "1600 Amphitheatre Pkwy Mountain View CA"]` | One per line, as messy as your list is: a business name with its address or city ("Blue Bottle Coffee 480 9th St Oakland"), a name and a ZIP code ("starbucks lafayette ca 94549"), or an address alone. Each line returns the one Google Maps place it is, or a free row when nothing fits. |
| `query` | no | string | — | A single lookup, for API calls and saved tasks. Combined with the list above. |
| `rows` | no | array | `[{"id": "crm-17", "name": "Tartine Bakery", "city": "San Francisco", "state": "CA"}]` | A JSON list of objects with any of id, name, address, city, state, zip, country, e.g. \[{"id": "crm-17", "name": "Tartine Bakery", "city": "San Francisco"}]. Your id comes back on the matched row as input_id, so you can join the result to your own list. When a row gives a name, the place must share a word with it; when it gives an address, the place must have its house number. |
| `maxItems` | no | integer | — | Optional spend cap for the whole run: only the first this-many inputs are looked up, and a free row says how many were left. Leave empty to look up every input. |
| `proxyConfiguration` | no | object | `{"useApifyProxy": true}` | Apify's datacenter proxy by default, which is what this actor was built for. |

### Pricing (Pay Per Event)

You pay per result (`place-matched`) — **no charge for empty runs**. Example: **1000 matched places** at *$0.0015/result* ≈ **$1.50**.

Lookups go through Apify Proxy, billed by Apify as platform usage on your plan, like compute.

### Use cases

- CRM cleanup: match every account to its Google place ID, then dedupe on the ID and fill in missing phones and websites.
- Lead enrichment before outreach: name and city in, phone, website, rating and category out.
- Address cleanup and geocoding: messy addresses in, Google's address split into street, city, state and ZIP, plus latitude and longitude.
- Place IDs without an API key: for teams moving off the legacy Places API, or that never had a Google Cloud billing account.

### Why this actor

- Checks before it bills: house numbers and names are compared with Google's answer, and a mismatch is a free row that lists what Google offered.
- Batch-friendly: plain lines or rows with your own id, which comes back on each match.
- Every match says how it matched (name + address, name, or address) and how sure it is.

### Limitations & updates

Built and tested on US businesses and addresses: the address is split into street, city, state and ZIP the US way, and a non-US address keeps only its full address line. The data is what Google Maps shows for the place at the time of the run; a place with no phone or website on Google Maps has none here. The match check compares numbers and name words; it can still pass a place at the same house number with a similar name, and it refuses a business whose Google Maps name shares too few words with the name you sent (send the name as it appears on Google Maps, or an address alone). Input as a Google place ID (looking up a place you already have the ID of) is not supported.

### FAQ

**What can I send?**

Lines of text, one business or address each, as messy as your list is: a name with its street address or city, a name with a ZIP code, or an address alone. Or rows (JSON) with any of id, name, address, city, state, zip and country; the id comes back on the match as input_id.

**How does it avoid the wrong business?**

Before a match is billed, every number you gave (house number, ZIP) must be in the place's address, and at least half of the place's name words must be in what you sent (and, for a row with a name, half of your name's words in the place's name). So "Peet's Coffee 410 9th St Oakland" does not bill for Blue Bottle Coffee at 480 9th St: it comes back as a free row listing the Peet's locations Google offered.

**What does an address alone return?**

The place Google Maps has at that address, whatever it is called: "350 5th Ave New York NY" returns the Empire State Building, "1600 Amphitheatre Pkwy Mountain View CA" a Google building. matched_by says "address".

**What does confidence mean?**

high: Google Maps answered with this one place. medium: Google answered with several and this was its first. low: Google's first answers failed the check and a later one passed. other_matches lists the rest, which helps with chains (two Starbucks on the same street).

**Do I need a Google API key?**

No. The actor reads Google Maps' own search, the one the website uses, so there is no Cloud project, billing account or key.

**How am I charged?**

$0.0015 per input matched to a place. Inputs that match nothing, lookups Google refused and input mistakes are free rows. Set "Maximum inputs to look up" to cap a run's spend.

**How fast is it?**

Measured on 2026-11-06: 10 lookups in about 2 seconds, five at a time.

**Which countries?**

It was built and tested on US businesses and addresses, and the address fields (state, ZIP) are split the US way. A non-US query is sent to Google as written; include the city and country, and check the first rows before a large run.

### Which actor to choose

Works with:

- **Business Email, Phone & Contact Details Scraper** — You have the matched websites and want each business's email and social links.

### Guides & use cases

Written up on **[scrapebench.dev](https://scrapebench.dev)** — the bench that runs and verifies this actor against the live source every night:

- **How-to:** [How to run Google Maps Place Matcher: Business Lookup by Name & Address](https://scrapebench.dev/guides/how-to-google-maps-place-matcher/)
- **Use case:** [Match a business list to Google Maps place IDs](https://scrapebench.dev/use-cases/match-business-list-to-google-maps/)

More actors, coverage and nightly verification results: **[scrapebench.dev](https://scrapebench.dev)**

### Works with AI assistants (MCP)

Callable as an MCP tool, so Claude, Cursor, VS Code Copilot and other MCP clients can run it directly. Grab the config from the [MCP tab](https://apify.com/scrapebench/google-maps-place-matcher/api/mcp) on this page — Apify hosts the server and keeps that snippet current, and OAuth signs you in on first connect, so no API token goes in your config file.

Then just ask:

> "Find the Google Maps listing, phone number and place ID for Blue Bottle Coffee at 480 9th St, Oakland."

One business per question is the natural call; send a list of lines for a batch. Runs started this way bill exactly like any other run.

### Data & lawful use

This actor collects publicly available information that Google (Google Maps) publishes for public
lookup — licence records, business listings and the contact details professionals list there.
Some of it identifies individuals (sole proprietors, licence holders, agents), so treat any
names, phone numbers and emails in your results as personal data.

When you run this actor, you decide what is collected and what it is used for, so you are the
controller of that data and we act only as your processor (Apify Standard Actor Contract).
You need a lawful basis for your use, must honour opt-out and deletion requests, and must
follow the marketing rules that apply to you (CAN-SPAM, TCPA, GDPR, CCPA and similar).
Don't use the output for unsolicited bulk messaging, for screening covered by the FCRA, or
for anything the source's own terms forbid.

Your results are stored in your own Apify account. We don't keep a copy of your results and
don't sell or share them.

### Disclaimer

This is an independent tool. It is not affiliated with, endorsed by or sponsored by
Google (Google Maps). Names and marks are used only to describe the data source. Records are
provided as published by the source and may be out of date or incomplete. For anything
consequential (hiring, a permit, a legal decision), confirm the record with the issuing
agency. You are responsible for making sure your use complies with applicable law and the
source's terms.

### Need help?

Open an issue on this actor's **Issues** tab and we'll respond there. Bug reports, missing
fields and feature requests are all welcome. Guides and examples: [scrapebench.dev](https://scrapebench.dev).

If you are a person named in this data and want your record removed from our copy, email
apify-help@scrapebench.dev; the source agency remains the official record.

Your run may be used to improve our services. If something looks off, or you want this actor to fit your use better, please share your run data with us: [Apify Console → Settings → Security → Share run data with developers](https://console.apify.com/settings/security). It lets us see exactly what went wrong and keep improving the actor.

# Actor input Schema

## `queries` (type: `array`):

One per line, as messy as your list is: a business name with its address or city ("Blue Bottle Coffee 480 9th St Oakland"), a name and a ZIP code ("starbucks lafayette ca 94549"), or an address alone. Each line returns the one Google Maps place it is, or a free row when nothing fits.

## `query` (type: `string`):

A single lookup, for API calls and saved tasks. Combined with the list above.

## `rows` (type: `array`):

A JSON list of objects with any of id, name, address, city, state, zip, country, e.g. \[{"id": "crm-17", "name": "Tartine Bakery", "city": "San Francisco"}]. Your id comes back on the matched row as input_id, so you can join the result to your own list. When a row gives a name, the place must share a word with it; when it gives an address, the place must have its house number.

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

Optional spend cap for the whole run: only the first this-many inputs are looked up, and a free row says how many were left. Leave empty to look up every input.

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

Apify's datacenter proxy by default, which is what this actor was built for.

## Actor input object example

```json
{
  "queries": [
    "Blue Bottle Coffee 480 9th St Oakland",
    "starbucks lafayette ca 94549",
    "1600 Amphitheatre Pkwy Mountain View CA"
  ],
  "rows": [
    {
      "id": "crm-17",
      "name": "Tartine Bakery",
      "city": "San Francisco",
      "state": "CA"
    }
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

One row per matched input: place ID, name, address, coordinates, phone, website, rating, how it matched.

# 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 = {
    "queries": [
        "Blue Bottle Coffee 480 9th St Oakland",
        "starbucks lafayette ca 94549",
        "1600 Amphitheatre Pkwy Mountain View CA"
    ],
    "rows": [
        {
            "id": "crm-17",
            "name": "Tartine Bakery",
            "city": "San Francisco",
            "state": "CA"
        }
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapebench/google-maps-place-matcher").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 = {
    "queries": [
        "Blue Bottle Coffee 480 9th St Oakland",
        "starbucks lafayette ca 94549",
        "1600 Amphitheatre Pkwy Mountain View CA",
    ],
    "rows": [{
            "id": "crm-17",
            "name": "Tartine Bakery",
            "city": "San Francisco",
            "state": "CA",
        }],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("scrapebench/google-maps-place-matcher").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 '{
  "queries": [
    "Blue Bottle Coffee 480 9th St Oakland",
    "starbucks lafayette ca 94549",
    "1600 Amphitheatre Pkwy Mountain View CA"
  ],
  "rows": [
    {
      "id": "crm-17",
      "name": "Tartine Bakery",
      "city": "San Francisco",
      "state": "CA"
    }
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call scrapebench/google-maps-place-matcher --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scrapebench/google-maps-place-matcher"
        }
    }
}
```

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/Z8QBqgGSGzvBdw30z/builds/ZO3DuQd9c8nTOBhhZ/openapi.json
