# Google Maps No-Website Leads Scraper | Unclaimed + Lead Score (`corvuslab/google-maps-no-website-leads-scraper`) Actor

Find local businesses with no website on Google Maps: name, category, phone, address, rating, reviews, weekly hours, time zone and a 0–100 lead score with reasons. Adds dead-website, directory-only and unclaimed-profile leads, on-trade matches only. Many cities per run, only-new mode, Notion rows.

- **URL**: https://apify.com/corvuslab/google-maps-no-website-leads-scraper.md
- **Developed by:** [Corvuslab](https://apify.com/corvuslab) (community)
- **Stats:** 3 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

### What does Google Maps No-Website Leads Scraper do?

Google Maps No-Website Leads Scraper finds **local businesses on Google Maps that have no website of their own**, so web designers, agencies and SMMA teams get a phone-ready prospect list instead of a raw map dump. Give it a trade (`plumber`, `roofer`, `dentist`) and one or more cities, and it searches the whole radius, keeps the businesses with no real website, and returns each one with its phone number, address, rating, reviews, opening hours and a **0–100 lead score with every point explained**.

"No website" means what a web designer means by it: no link at all, or only a Facebook or Instagram page, a link-in-bio page or a directory profile. Optionally it also **checks every listed website live** and keeps the ones that are down, parked or expired. Run it with no code and export to JSON, CSV, Excel, Notion, the API or an AI agent.

> New to Apify? Sign up free and use the included monthly platform credit to try this Actor — no credit card needed.

***

### What data can you extract about Google Maps no-website leads?

Every lead is one record with **37 fields**:

| Group | Fields |
|---|---|
| **Business** | name `title`, main and all categories (`categoryName`, `categories`), Google IDs (`cid`, `fid`, `placeId`), `mapsUrl` |
| **Location** | `address`, `street`, `neighborhood`, `city`, `state`, `postalCode`, `countryCode`, coordinates `location`, `distanceFromCenterKm`, `timezone` |
| **Contact & hours** | `contactPhone` (international format), `openingHoursToday`, the full week in `openingHours` |
| **Web presence** | `website`, `displayDomain`, `websiteKind` (`none` / `social` / `linkinbio` / `directory` / `builder` / `deadsite`), `websiteIssue` for dead sites, `hasFacebook`, `socialPagePlatform`, `socialProfiles` |
| **Reputation** | `totalScore` (stars), `reviewsCount`, `claimThisBusiness` (the Google profile is unclaimed) |
| **Scoring & tracking** | `leadScore` 0–100, `leadTier`, `leadScoreReasons`, `changeType` (NEW / UPDATED / UNCHANGED), `searchTerm`, `searchLocation`, `scrapedAt` |

***

### Key features

- 🎯 **Finds more than "no link"** — social-only, link-in-bio and directory/booking-only businesses count as leads by default (a Yelp, Houzz, Booksy or Google profile page is not a website of their own). Free site-builder subdomains are one click away. Each lead says which case it is.
- 🪦 **Dead-website leads (opt-in)** — every listed website is checked live, and the ones that are down, gone or parked are kept with the reason. On landscapers in Phoenix, **19 of 25 leads** were businesses whose listed site was dead, and every one held up when we checked by hand.
- 🧲 **Only businesses that match the search** — Google mixes other trades into its results (a pool cleaner under "plumber"). On by default, this filter learns what your trade means from Google's best-ranked results, in the run's language, and drops the rest. Austin plumbers and landscapers: **97 of 100 leads** on-trade with it, 83 of 100 without.
- 🗺️ **Deep, radius-accurate coverage** — the radius (1–200 km, or miles) is searched area by area from the centre outwards, not just the first screen of results, and everything outside it is dropped. On plumbers within 25 km of Austin, the finer grid found about **30% more no-website businesses** than a coarser one.
- 🔓 **Only unclaimed profiles** — one checkbox keeps only businesses whose Google profile is unclaimed: prospects for a profile setup as well as a website.
- 🧮 **Explainable lead score** — 0–100 plus a PREMIUM / HIGH / MEDIUM / LOW tier, with the reasons listed (`+30 phone listed`, `+10 profile unclaimed`, …), so you can re-weight it in a spreadsheet.
- 🔎 **Many trades × many cities** — several search terms, a main location plus up to 50 more, each with its own result cap. A business found twice is returned once.
- ♻️ **Only new leads** — scheduled runs skip businesses you already have. Name a lead list to keep a separate memory per campaign.
- 🔔 **Delivered where you work** — Telegram, Slack, Discord, WhatsApp, any webhook, or every lead as a row in your Notion database.
- 🤖 **AI-ready** — compact and drop-empty output modes keep payloads small for LLMs and MCP clients.

***

### 🚀 How to scrape Google Maps for businesses without a website

1. Enter one or more **search terms** (e.g. `plumber`, `roofer`) and a **location** (`Austin, TX`, `Manchester, UK`, a postcode or a region).
2. Set the **search radius** and **max results** per location. Add more cities under **More locations**.
3. Pick what counts as **"no website"**, and tick **Require a phone number** or **Only unclaimed profiles** if you want.
4. (Optional) Turn on **Only new leads**, add a **notification** channel or a **Notion database**, then **Schedule** it.
5. Click **Start**, then download as **JSON, CSV or Excel** or pull from the **API**.

#### Quick-start example input

```json
{ "searchTerms": ["plumber"], "location": "Austin, TX", "maxResults": 100, "requirePhone": true }
```

Up to 100 plumbers within 25 km of central Austin with no website of their own, each with a phone number, a lead score and the reasons behind it.

***

### Input

Configure it in the visual editor with no code, or pass JSON via the API. These are the fields that shape your lead list:

#### 🔎 Search

| Field | Type | What it does |
|---|---|---|
| `searchTerms` | array | Trades or business types, e.g. `plumber`, `roofer`, `dentist`. Several terms run in one go. |
| `location` | string | City, area, postcode or region to search around. |
| `locations` | array | Up to 50 more cities or areas, searched with the same terms. |
| `searchRadiusKm` / `searchRadiusMiles` | integer | Radius around each location: 1–200 km (default 25), or miles instead when set. |
| `maxResults` | integer | Leads to return **per location**, 1–1,000 (default 100). |
| `onlyNewLeads` | boolean | Skip businesses an earlier run already returned. |
| `stateKey` | string | Lead list name: a separate "already seen" memory per campaign. |
| `gl` / `hl` | string | Country (249 to choose from; empty = taken from the location) and result language (default `en`). |

#### 🎯 Filters

| Field | Type | What it does |
|---|---|---|
| `webPresence` | array | What counts as "no website": `none`, `social`, `linkinbio`, `directory` (default), plus `builder` and `deadsite` (live website check). |
| `onlyMatchingBusinesses` | boolean | Drop businesses from a different trade that Google mixes into the results (default on). |
| `minRating` / `minReviews` | integer | Minimum star rating (0–5) and number of reviews. |
| `category` | string | Keep only businesses whose Google category contains this text. |
| `requirePhone` | boolean | Keep only businesses that list a phone number. |
| `onlyClaimable` | boolean | Keep only businesses with an unclaimed Google profile. |
| `skipClosed` | boolean | Leave out closed businesses (default on). |

#### Everything else

| Fields | What they do |
|---|---|
| Notification channels, `notifyOnlyChanges`, `notificationLimit` | Alerts after each run — see the alerts section below. |
| `notionApiKey` + `notionDatabaseId` (+ `notionCreateProperties`) | Every lead as a row in your Notion database, with missing columns created for you. |
| `appConnector` (+ `mcpIssueTeam`) | A one-page run summary to an app you connected in Apify (Notion, or an issue tracker). |
| `startUrls` | Google Maps search or place links instead of the search fields. |
| `compact`, `excludeEmptyFields` | Smaller output for AI pipelines. |
| `query`, `proxyConfiguration` | Alternative search-term field; proxy settings (not needed for normal runs). |

#### More example inputs

Dead websites and builder sites across three cities, established businesses only:

```json
{
  "searchTerms": ["landscaper", "roofer"],
  "location": "Phoenix, AZ",
  "locations": ["Mesa, AZ", "Tempe, AZ"],
  "webPresence": ["none", "social", "linkinbio", "directory", "builder", "deadsite"],
  "minReviews": 10
}
```

Unclaimed Google profiles in the UK, within 10 miles:

```json
{ "searchTerms": ["handyman"], "location": "Manchester, UK", "searchRadiusMiles": 10, "onlyClaimable": true, "requirePhone": true }
```

***

### Output

Each dataset item is one lead. A real record — a Brooklyn barber shop whose only web presence is an Instagram page:

```json
{
  "title": "Thee Brooklyn Barber",
  "categoryName": "Barber shop",
  "placeId": "ChIJJ3eZ0jdZwokRd5NDa9g7gJI",
  "mapsUrl": "https://www.google.com/maps?cid=10556503327255008119",
  "location": { "lat": 40.7198357, "lon": -73.9602472 },
  "address": "158 Wythe Ave, Brooklyn, NY 11249, United States",
  "neighborhood": "Williamsburg",
  "city": "Brooklyn",
  "state": "NY",
  "countryCode": "US",
  "timezone": "America/New_York",
  "totalScore": 4.8,
  "reviewsCount": 360,
  "claimThisBusiness": false,
  "openingHoursToday": "Open · Closes 8.00 pm",
  "openingHours": [
    { "day": "Monday", "hours": "10 am–8 pm" },
    { "day": "Saturday", "hours": "10 am–7 pm" },
    { "day": "Sunday", "hours": "10 am–7 pm" }
  ],
  "website": "https://www.instagram.com/theebrooklynbarber/",
  "websiteKind": "social",
  "hasFacebook": false,
  "socialPagePlatform": "instagram",
  "socialProfiles": { "instagram": "https://www.instagram.com/theebrooklynbarber/" },
  "websiteIssue": null,
  "contactPhone": "+17186900663",
  "searchTerm": "barber",
  "leadScore": 87,
  "leadTier": "PREMIUM",
  "leadScoreReasons": [
    "+30 phone listed",
    "+8 reachable via instagram",
    "+25 360 reviews",
    "+15 rated 4.8",
    "+5 opening hours listed (active business)",
    "+4 street address listed"
  ],
  "changeType": "NEW",
  "scrapedAt": "2026-10-13T19:26:53+00:00"
}
```

On a dead-website lead, `websiteKind` is `deadsite` and `websiteIssue` says why: `unreachable`, `timeout`, `parked` or the error the site returned (e.g. `http_404`). Missing values are `null`. The Output tab has three views: **Leads**, **Call list** (phone, time zone, weekly hours, social profiles, web presence, address, score) and **All fields**. **Compact mode** returns 17 core fields.

***

### ♻️ How to monitor Google Maps for new no-website leads

New businesses open every week, most with a phone and a social page but no website. Schedule the Actor with **Only new leads** on, and each run returns only businesses you have not received before. After the first run, your cost follows how many new businesses appear, not how big the area is.

With **Only new leads** off, a re-run returns every lead again, tagged `NEW`, `UPDATED` (the listing changed, e.g. a new phone or rating) or `UNCHANGED` — useful for refreshing a CRM. The memory is shared across your runs; give each campaign its own **Lead list name** to keep them apart.

1. Configure your search terms, locations and filters, and turn on **Only new leads**.
2. Run it once to seed the baseline.
3. Open the **Schedules** tab and set a recurring run (e.g. weekly).
4. Add a notification channel or a Notion database to receive each batch.

***

### 🔔 How to set up alerts for new Google Maps no-website leads

Fill in only the channels you want:

| Channel | What to configure |
|---|---|
| ✈️ **Telegram** | `telegramToken` (from @BotFather) + `telegramChatId` |
| 💬 **Slack** | `slackWebhookUrl` |
| 🎮 **Discord** | `discordWebhookUrl` |
| 📱 **WhatsApp** | `whatsappAccessToken` + `whatsappPhoneNumberId` + `whatsappTo` |
| 🪝 **Webhook** | `webhookUrl` (+ optional `webhookHeaders`) receives every lead of the run as JSON — n8n, Make, Zapier or your own endpoint |
| 🗃️ **Notion** | `notionApiKey` + `notionDatabaseId`, one row per lead |

Chat messages list the top leads (up to 20, `notificationLimit`); the webhook gets all of them. Turn on **Notify only new / updated** to hear only about businesses that changed. Credentials are secret inputs: encrypted, masked in the UI and never written to the log. A broken channel never stops the run.

***

### 💡 What can you do with Google Maps no-website leads?

- **Sell websites to local businesses.** A plumber with 300 five-star reviews and no website is an easy pitch. Sort by `leadScore` and start with PREMIUM.
- **Win back owners whose site went dark.** Dead-website owners already paid for a domain; they know what a site is worth.
- **Offer Google profile setup.** Unclaimed profiles are an easy upsell: claim, verify, add photos and hours.
- **Feed a cold-calling pipeline.** The Call list view gives callers the number, the time zone and the weekly hours, so they call when the owner is there.

***

### 💰 How much does it cost to scrape Google Maps no-website leads?

This Actor uses Apify's **pay-per-event** model: a small fee when a run starts, plus a fee for each lead returned. The current numbers are on the **Pricing** tab.

You pay only for leads. Businesses that have a website, belong to a different trade, fail your filters, are closed or were already returned (with **Only new leads**) are screened out first and **never charged**, and a business found by two search terms or in two cities is charged once. Every field — phone, social link, score, hours — is included in the lead.

***

### 🔌 Integrations & export

Export to **JSON, CSV, Excel** or HTML, or pull from the **REST API** and the **JavaScript / Python** clients. Runs on a **schedule**, sends leads to **Notion**, **Google Sheets, Slack, Make, Zapier and n8n**, and works as an **MCP tool** for AI agents.

***

### 🔗 Using the API

Run this Actor from your own code with the Apify Python client:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")

run_input = {
    "searchTerms": ["roofer", "plumber"],
    "location": "Tulsa, OK",
    "maxResults": 50,
    "requirePhone": True,
}

run = client.actor("corvuslab/google-maps-no-website-leads-scraper").call(run_input=run_input)

for lead in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(lead["leadScore"], lead["title"], lead["contactPhone"])
```

***

### ❓ FAQ

**What counts as "no website"?** By default: no link at all, or only a social page (Facebook, Instagram, TikTok…), a link-in-bio page (Linktree, Beacons…) or a directory or booking profile (Yelp, Houzz, Booksy, a Google profile link…). Add `builder` for free site-builder subdomains and `deadsite` for listed websites that no longer work. `websiteKind` tells you which case each lead is.

**How does the dead-website check decide a site is dead?** Each listed website is visited during the run. It counts as dead when the domain no longer resolves or never answers, returns "not found" or a server error, or shows a parked or for-sale page. A site that is online but turns visitors away counts as alive, so a real website is not flagged by mistake. It is opt-in because it adds time to a run.

**How many leads can I get per city?** Up to 1,000 per location. How many exist depends on the trade and city: in our Austin test, 99 of the 605 businesses within 25 km were plumbers with no real website.

**Why are some businesses from my search missing?** Usually because they belong to a different trade and **Only businesses that match the search** dropped them. Turn it off for Google's full list, or use `category` for an exact category filter.

**Why is `reviewsCount` empty on some leads?** Google shows no review count for those listings — in our tests about one in eight, almost always a business with no reviews yet. Set `minReviews` to leave them out.

**Does it return email addresses?** No. A business without a website rarely publishes an email, so you get the listed phone and, where there is one, the social or link-in-bio page where the owner can be messaged.

**What do the score tiers mean?** PREMIUM 80+, HIGH 60+, MEDIUM 40+, LOW below 40. Points come from a listed phone, a reachable social page, review volume, rating, an unclaimed profile, listed hours and a street address.

**Which countries and languages are supported?** Any of 249 countries; the country is detected from the location when you leave it empty. `hl` sets the language of category names, opening status and addresses. Phone numbers come in international format everywhere.

**Do I need a Google account or a proxy?** No. It runs without login and needs no proxy for normal runs.

***

### ⚖️ Is it legal to scrape Google Maps?

This Actor collects only **publicly available** business listing data: what anyone sees on Google Maps without logging in. You're responsible for how you use it, in particular for any personal information and for cold outreach. You must comply with Google's terms and applicable law, including the GDPR/LGPD and local telemarketing and do-not-call rules where they apply. Not affiliated with, endorsed by or sponsored by Google.

***

**Keywords:** google maps no website leads · businesses without website · no website leads scraper · google maps leads scraper · google maps scraper · local business leads · web design leads · SMMA leads · unclaimed google business profile · dead website leads · cold calling list · lead score · prospects by radius · google maps lead generation · Notion lead database · export to CSV · export to Excel · MCP tool for AI agents

# Changelog

This Actor's version history is a separate document: https://apify.com/corvuslab/google-maps-no-website-leads-scraper/changelog.md

# Actor input Schema

## `searchTerms` (type: `array`):

What to search for, e.g. "plumber", "roofer", "dentist". Add several to scan multiple trades in one run. A comma-separated line is split into separate terms.

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

City, area, postcode or region to search around, e.g. "Austin, TX" or "Manchester, UK".

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

Search the same terms in more cities or areas in the same run, one per line (up to 50). Max results applies to each location, and a business found in two locations is returned and charged once.

## `searchRadiusKm` (type: `integer`):

How far from the location centre to search. The whole circle is covered map area by map area, and results outside it are dropped.

## `searchRadiusMiles` (type: `integer`):

Optional alternative to km. When you set it, it is used instead of the km radius.

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

Maximum number of leads to return per location.

## `onlyNewLeads` (type: `boolean`):

Skip businesses that an earlier run of this actor already returned to you. Skipped businesses are not returned and not charged. Turn it on for scheduled runs to get only fresh leads.

## `stateKey` (type: `string`):

Optional. Keep a separate memory per campaign: 'Only new leads' and the NEW / UPDATED / UNCHANGED tags then compare against earlier runs that used the same list name. Leave empty to share one memory across all your runs.

## `gl` (type: `string`):

Country to bias the search and location lookup toward. Leave empty to take the country from the location.

## `hl` (type: `string`):

Language Google writes the results in: category names, today's opening status and addresses (2-letter code, e.g. "de", "ja"). Phone numbers, ratings and every other field are the same in every language. The category filter matches category names in this language.

## `webPresence` (type: `array`):

Which kinds of web presence make a business a lead. The default returns businesses with no site of their own. Add "builder" for weak free-builder sites, and "deadsite" to also check every listed website live and keep the ones that are down, parked or expired.

## `onlyMatchingBusinesses` (type: `boolean`):

Drop businesses Google shows for your term that are really a different trade (a pool cleaner in a plumber search). The run learns what the term means from Google's best-ranked results, in any language. Dropped businesses are not charged. Turn off to get Google's full, looser list.

## `minRating` (type: `integer`):

Only keep businesses with at least this star rating (0–5). Leave empty for no minimum.

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

Only keep businesses with at least this many reviews. When set, businesses without a review count are left out.

## `category` (type: `string`):

Keep only businesses with a Google category containing this text (case-insensitive), for example "Plumber". Leave empty to include every category.

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

Keep only businesses that list a phone number (recommended for outreach).

## `onlyClaimable` (type: `boolean`):

Keep only businesses whose Google profile is unclaimed ("Claim this business") — prospects for profile setup as well as a website.

## `skipClosed` (type: `boolean`):

Leave out businesses marked permanently or temporarily closed.

## `telegramToken` (type: `string`):

Telegram bot token (from @BotFather). Required for Telegram notifications.

## `telegramChatId` (type: `string`):

Telegram chat or channel ID. Required when a Telegram token is set.

## `discordWebhookUrl` (type: `string`):

Discord incoming webhook URL.

## `slackWebhookUrl` (type: `string`):

Slack incoming webhook URL.

## `whatsappAccessToken` (type: `string`):

WhatsApp Cloud API access token. The recipient must have messaged your business number within the last 24h.

## `whatsappPhoneNumberId` (type: `string`):

Your WhatsApp Business phone-number ID. Required when a WhatsApp token is set.

## `whatsappTo` (type: `string`):

Recipient phone in E.164 format without + (e.g. "15125550100"). Separate several with commas.

## `webhookUrl` (type: `string`):

Receives a JSON POST with the run's leads after the run finishes (n8n / Make / Zapier / custom).

## `webhookHeaders` (type: `object`):

Optional JSON object of custom headers (e.g. {"Authorization":"Bearer ..."}).

## `notifyOnlyChanges` (type: `boolean`):

Only send notifications for businesses that are new or changed since the previous run.

## `notificationLimit` (type: `integer`):

Maximum number of leads listed in each chat notification (1–20). The webhook always receives every lead.

## `appConnector` (type: `string`):

Optional. Pick an app you connected under Settings → API & Integrations. Notion gets a run-summary page with a lead table; an issue tracker gets one summary issue.

## `mcpIssueTeam` (type: `string`):

Only when the connected app is an issue tracker: the team (name or ID) the summary issue is created under, if that app requires one.

## `notionApiKey` (type: `string`):

Optional, for a full lead database instead of a summary: every lead becomes a row. Create an internal integration at notion.so/my-integrations, then open your database → ⋯ → Connections and connect it.

## `notionDatabaseId` (type: `string`):

The database that receives one row per lead. Paste its URL or ID.

## `notionCreateProperties` (type: `boolean`):

Add any lead column the database is missing (phone, score, web presence, …).

## `startUrls` (type: `array`):

Google Maps search links (…/maps/search/plumber/@30.27,-97.74,13z) or place links. When set, the search fields above are ignored; the radius still applies around each search link's map position.

## `compact` (type: `boolean`):

Return only the core lead fields. Smaller payloads for LLM pipelines and agent tools.

## `excludeEmptyFields` (type: `boolean`):

Drop null, empty-string and empty-array fields from each lead.

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

Alternative to Search terms: one term, a comma-separated list, or a JSON array.

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

Not needed for normal runs. Enable it only if your runs report that searches could not be completed.

## Actor input object example

```json
{
  "searchTerms": [
    "plumber"
  ],
  "location": "Austin, TX",
  "searchRadiusKm": 25,
  "maxResults": 100,
  "onlyNewLeads": false,
  "hl": "en",
  "webPresence": [
    "none",
    "social",
    "linkinbio",
    "directory"
  ],
  "onlyMatchingBusinesses": true,
  "requirePhone": false,
  "onlyClaimable": false,
  "skipClosed": true,
  "notifyOnlyChanges": false,
  "notificationLimit": 5,
  "notionCreateProperties": true,
  "compact": false,
  "excludeEmptyFields": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

No description

## `allItems` (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 = {
    "searchTerms": [
        "plumber"
    ],
    "location": "Austin, TX",
    "maxResults": 100,
    "excludeEmptyFields": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("corvuslab/google-maps-no-website-leads-scraper").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 = {
    "searchTerms": ["plumber"],
    "location": "Austin, TX",
    "maxResults": 100,
    "excludeEmptyFields": False,
}

# Run the Actor and wait for it to finish
run = client.actor("corvuslab/google-maps-no-website-leads-scraper").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 '{
  "searchTerms": [
    "plumber"
  ],
  "location": "Austin, TX",
  "maxResults": 100,
  "excludeEmptyFields": false
}' |
apify call corvuslab/google-maps-no-website-leads-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,corvuslab/google-maps-no-website-leads-scraper"
        }
    }
}
```

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/akaTgLojD4W4ALI4R/builds/ybUx6ghrDXbptmxMm/openapi.json
