# Google Maps No-Website Leads: Business Prospects (`deepmine/google-maps-no-website-leads`) Actor

Find businesses on Google Maps with no website, only a Facebook or booking page, or a dead or weak site. Each lead: phone, address, rating, reviews, claimed status, a lead score with reasons and the evidence link. Many cities, a radius, only-new monitoring. No login.

- **URL**: https://apify.com/deepmine/google-maps-no-website-leads.md
- **Developed by:** [DeepMine](https://apify.com/deepmine) (community)
- **Categories:** Lead generation, Travel, Marketing
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.59 / 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.
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

## Google Maps No-Website Leads: Business Prospects

Type a business type and a city (`roofer` in `Austin, TX`) and get **businesses on Google Maps that have no website of their own**: no website link at all, or only a Facebook / Instagram page, a booking page or a directory listing. Optionally also **dead websites** (domains that don't resolve, error pages, parked or for-sale domains) and **weak websites** (no HTTPS, no mobile layout, a free builder subdomain, an old copyright). Every lead comes with its **phone**, address, rating, reviews, **claimed status**, a **lead score with its reasons** and the **evidence link** behind its web-presence verdict. You pay per lead only: businesses with a working website are checked and left out for free. No login, no browser, no proxy setup.

| Business | Category | Phone | Web presence | Lead score | Rating | Claimed |
|---|---|---|---|---|---|---|
| Lifetime Quality Roofing | Roofing contractor | (512) 956-7663 | none | 100 hot | 4.7 (94) | yes |
| Miller Brothers Roofing & Construction | Roofing contractor | (512) 710-0606 | none | 95 hot | 4.9 (37) | yes |
| Riveras Brothers Remodeling | Deck builder | (512) 767-4726 | none | 95 hot | 5.0 (11) | yes |

<sub>Collected 2026-10-19 (business type "roofer" in "Austin, TX", the form's example). `outreachAngle` of the first: "No website, but 4.7★ from 94 reviews: pitch a simple site that turns Maps searchers into calls."</sub>

### What you get

- **One lead per business** without a real website, for every business type in every city or area you enter: Google's own ranking first, then every ZIP code inside the city, so a search isn't stuck at the ~200 places one Google Maps query shows. The city's own boundary is used, or a radius around its centre (`searchRadiusKm`), and each lead's `distanceKm` from the centre.
- **Web presence with evidence**: `webPresence` is `none`, `socialOnly`, `bookingOnly`, `directoryOnly`, `deadWebsite`, `parkedDomain` or `weakWebsite`, `webPresenceReasons` says why in words, and `webPresenceEvidenceUrl` is the link that decided it. In the dead / weak modes, `websiteCheck` holds the homepage check: HTTP status, final URL, HTTPS, mobile viewport, copyright year, site builder.
- **Lead fields**: name, categories, phone (as shown and in international format), full address and its parts, coordinates, rating, review count, reviews per star, opening hours and today's hours, owner description, Google Maps link, place ID, CID; **`claimed`** (does the owner manage the Google profile?) and Google's **Claim this business** link of an unclaimed one.
- **Lead score**: `leadScore` 0-100 from fixed points (presence up to 40, phone 20, reviews up to 15, rating 4+ 10, claimed 10, opening hours 5), `leadTier` hot / warm / cold, every point listed in `leadReasons`, and a one-line `outreachAngle`.
- **Contacts we can find honestly**: a social page the business links instead of a website goes into `facebooks` / `instagrams` / ...; a weak website's homepage is read for its emails, phones and social profiles. A business without a website gets no made-up email.
- **Only new leads**: give a 🔔 **Monitor name** and run the same search again (by hand or on a schedule): leads the monitor already delivered are skipped and not charged, or, with *Only new leads* off, every lead comes back tagged `new`, `changed` (with `changedFields`) or `unchanged`, with `firstSeenAt`.

A missing website link on Google Maps is reported as exactly that: some businesses have a website they never added to their Google profile. A site that blocks automated visits or times out is never called dead; it stays out of the leads.

### Pricing

Pay per lead, no start fee:

- **$0.99 per 1,000 leads** on the Starter plan ($1.18 Free, $0.79 Scale, $0.59 Business).

Each business is charged once per run, even when several business types or cities find it. Businesses with a working website, and leads your filters leave out, are never charged.

### Input

| Field | What it does |
|---|---|
| 🏷️ Business types | What you'd type in Google Maps (`roofer`, `hair salon`, `food truck`); each is searched in every city |
| 📍 Cities or areas | One or more cities, ZIP codes, counties or states |
| 💯 Number of leads per business type and city | Cap per business type and city (empty = every lead in the area) |
| 🎯 Which businesses are leads | No real website (default) / No website link only / Also dead websites / Also weak websites |
| 📞 Only leads with a phone, ⭐ Minimum rating, 💬 Minimum reviews, ✅ Claimed profile | Lead filters; businesses left out are not charged |
| 📏 Radius around each city (km) | A circle around each city's centre instead of its boundary |
| 🔔 Monitor name, 🆕 Only new leads | Repeat runs return only new leads |
| 🎛️ More filters | Category words, name match, skip closed (on), places to leave out |
| 🌍 Language and location by parts / 🛰️ Custom search area | Language; country, city, state, county, postal code; or a GeoJSON polygon / point + radius |
| 🔗 Google Maps links and place IDs | Places you already have: always returned with their web presence |

Example API input:

```json
{
  "searchStringsArray": ["roofer", "landscaper"],
  "locations": ["Austin, TX", "San Antonio, TX"],
  "maxCrawledPlacesPerSearch": 200,
  "leadFilter": "noWorkingWebsite",
  "onlyWithPhone": true,
  "monitorName": "texas-trades"
}
```

Input from other no-website lead scrapers works as it is: `searchTerms`, `location`, `locations`, `maxResults`, `searchRadiusKm` / `searchRadiusMiles`, `category`, `requirePhone`, `minRating`, `minReviews`, `onlyUnclaimed`, `searchQueries`, `maxLeadsPerQuery`, `locationQuery`, and the compass/crawler-google-places keys (`searchStringsArray`, `maxCrawledPlacesPerSearch`, `startUrls`, `placeIds`).

### Output

Views: **🎯 No-website leads** first (business, category, phone, web presence, score, tier, rating, reviews, claimed, address, city, distance, evidence, Facebook, Instagram, emails, Google Maps link, change, search), then **📣 Outreach** (tier, score, angle, score reasons, presence evidence, phone, today's hours, profile name, claim link), **📊 Overview**, **📈 Stats** and **📍 Location**.

Fields, in row order: `title`, `subTitle`, `description`, `ownerDescription`, `price`, `categoryName`, `address`, `neighborhood`, `street`, `city`, `postalCode`, `state`, `countryCode`, `website`, `phone`, `phoneUnformatted`, `claimThisBusiness`, `location`, `locatedIn`, `parentPlaceUrl`, `floor`, `plusCode`, `plusCodeGlobal`, `totalScore`, `permanentlyClosed`, `temporarilyClosed`, `placeId`, `categories`, `fid`, `cid`, `reviewsCount`, `reviewsDistribution`, `imagesCount`, `reserveTableUrl`, `googleFoodUrl`, `openingHours`, `openingHoursStatus`, `wasOpenAtScrapeTime`, `additionalOpeningHours`, `placesTags`, `reviewsTags`, `additionalInfo`, `url`, `language`, `imageUrl`, `imageUrls`, `kgmid`, `businessProfileId`, `tableReservationLinks`, `tableReservationProviders`, `restaurantData`, `orderBy`, `ownerName`, `ownerId`, `ownerProfileUrl`, `additionalPhones`, `domain`, `timezone`, `emails`, `phones`, `phonesUncertain`, `whatsapps`, `linkedIns`, `twitters`, `instagrams`, `facebooks`, `youtubes`, `tiktoks`, `pinterests`, `discords`, `yelps`, `tripadvisors`, `hasWebsite`, `webPresence`, `webPresenceEvidenceUrl`, `webPresenceReasons`, `websiteCheck`, `claimed`, `claimThisBusinessUrl`, `distanceKm`, `openingHoursToday`, `leadScore`, `leadTier`, `leadReasons`, `outreachAngle`, `changeTag`, `changedFields`, `firstSeenAt`, `searchString`, `rank`, `searchPageUrl`, `inputStartUrl`, `inputPlaceId`, `isAdvertisement`, `scrapedAt`.

`website`, `domain` and `websiteCheck` are filled only for dead or weak websites (the modes that keep a business with a link). Service-area businesses (many roofers, cleaners, contractors) hide their street address on Google Maps, so `address` is empty for them; `location` and `distanceKm` are still there.

How many businesses are leads depends on the trade and the area. Measured on 2026-10-19: roofers in Austin, TX, 172 leads of 739 businesses inside the city (23%), 277 of 1,121 within 25 km of the centre (25%, in under 5 minutes); hair salons, landscapers and food trucks in Phoenix and Tampa 180 of 941 (19%). The first lead lands 5-15 seconds after you press Start. Every lead is checked against the business's own Google Maps record, so a business whose profile links a website is never sold as a no-website lead.

### Related

- [Google Maps Business Leads](https://apify.com/deepmine/google-maps-business-leads): leads with a website, with the emails and social profiles found on it.
- [Google Maps Email Extractor](https://apify.com/deepmine/google-maps-email-extractor): the full place record with its website contacts.
- [Google Maps Scraper](https://apify.com/deepmine/google-maps-scraper): the full place record with up to 15 reviews and 100 photos per place.

# Actor input Schema

## `searchStringsArray` (type: `array`):

The kind of business you want leads for, as you would type it in Google Maps, e.g. <strong>roofer</strong>, <strong>hair salon</strong> or <strong>food truck</strong>. Each one is searched in every city or area below.

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

One or more cities, ZIP codes, counties or states, e.g. <strong>Austin, TX</strong> or <strong>Phoenix, AZ</strong>. Leads stay inside each place's own boundary (or the radius below); big areas are searched ZIP code by ZIP code automatically.

## `maxCrawledPlacesPerSearch` (type: `integer`):

Leads each business type returns in each city at most, e.g. 500. Empty = every lead Google Maps has there. Businesses that aren't leads are left out and don't count.

## `leadFilter` (type: `string`):

<strong>No real website</strong> (default): no website link on Google Maps, or the link is only a Facebook / Instagram / Linktree page, a booking or ordering page (Booksy, Vagaro, Square, Toast...) or a directory listing (Yelp, Angi...). <strong>No website link only</strong>: strictly no link at all. <strong>Also dead websites</strong>: also checks each website link and keeps domains that don't resolve, error pages and parked or for-sale domains. <strong>Also weak websites</strong>: also keeps sites without HTTPS or a mobile layout, on a free builder subdomain, with a coming-soon page or a copyright 4+ years old. A business that blocks the check stays out (never called dead).

## `onlyWithPhone` (type: `boolean`):

Keep only businesses that list a phone number on Google Maps.

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

Keep only places rated at least this. Places without a rating are left out when this is set.

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

Keep only businesses with at least this many Google reviews (an active business), e.g. 5.

## `claimStatus` (type: `string`):

Claimed = the owner manages the Google profile (reachable, active). Unclaimed = nobody has claimed it (Google shows 'Claim this business'): a profile-setup pitch too.

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

Search a circle of this many kilometres around each city's centre instead of the city's own boundary, e.g. 25. Each lead's <code>distanceKm</code> is measured from the centre.

## `monitorName` (type: `string`):

Name a monitor (e.g. <strong>roofers-austin</strong>) and run it again later, by hand or on a schedule: it remembers the leads it delivered (in a named storage of your account), so a repeat run returns only new businesses, and every lead says when it was first seen.

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

On: leads the monitor delivered before are skipped (not charged). Off: every lead is returned again with <code>changeTag</code> new, changed (phone, rating, website...) or unchanged. Needs a monitor name.

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

Keep only places with a category containing one of these words, e.g. <strong>dentist</strong>, <strong>orthodontist</strong>. Empty = every category. Places left out are not charged.

## `searchMatching` (type: `string`):

Keep only places whose name contains the search term, or is exactly the search term.

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

Leave out places Google marks permanently or temporarily closed (on by default: a closed business isn't a lead).

## `excludePlaceIds` (type: `array`):

Place IDs, CIDs or Google Maps links of businesses you already have (never returned, never charged).

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

Language of names, categories, hours and reviews, as Google Maps shows them.

## `countryCode` (type: `string`):

Used with the fields below when 📍 Location is empty; also sets the Google country, e.g. <strong>de</strong>. Two letters.

## `city` (type: `string`):

e.g. <strong>Pittsburgh</strong>.

## `state` (type: `string`):

e.g. <strong>Massachusetts</strong>.

## `county` (type: `string`):

e.g. <strong>King County</strong>.

## `postalCode` (type: `string`):

e.g. <strong>10001</strong>. Combine with 🗺️ Country.

## `customGeolocation` (type: `object`):

A GeoJSON Polygon or MultiPolygon (\[longitude, latitude] order), or a Point with <code>radiusKm</code>. Overrides the location. Only places inside are kept.

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

Place links (<code>https://www.google.com/maps/place/...</code>, <code>maps.app.goo.gl/...</code>) are checked and always returned with their web presence; search links (<code>https://www.google.com/maps/search/roofer/@30.27,-97.74,12z</code>) run as one more business type.

## `placeIds` (type: `array`):

Google place IDs (<code>ChIJdzf8kEZZwokRXtSOY0-Kwaw</code>), CIDs (<code>12448382918606115934</code>) or FIDs (<code>0x89c2594690fc3777:0xacc18a4f638ed45e</code>).

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

Leave as is: Apify datacenter proxy works for Google Maps. A call every datacenter IP refused is retried once on a residential IP.

## Actor input object example

```json
{
  "searchStringsArray": [
    "roofer"
  ],
  "locations": [
    "Austin, TX"
  ],
  "maxCrawledPlacesPerSearch": 50,
  "leadFilter": "noRealWebsite",
  "onlyWithPhone": false,
  "placeMinimumStars": "",
  "claimStatus": "any",
  "onlyNewLeads": true,
  "searchMatching": "all",
  "skipClosedPlaces": true,
  "language": "en",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `places` (type: `string`):

No description

## `summary` (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 = {
    "searchStringsArray": [
        "roofer"
    ],
    "locations": [
        "Austin, TX"
    ],
    "maxCrawledPlacesPerSearch": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("deepmine/google-maps-no-website-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 = {
    "searchStringsArray": ["roofer"],
    "locations": ["Austin, TX"],
    "maxCrawledPlacesPerSearch": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("deepmine/google-maps-no-website-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 '{
  "searchStringsArray": [
    "roofer"
  ],
  "locations": [
    "Austin, TX"
  ],
  "maxCrawledPlacesPerSearch": 50
}' |
apify call deepmine/google-maps-no-website-leads --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,deepmine/google-maps-no-website-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/PY13Ujg2TFtRDrsEA/builds/8lccUkLG6MkZ15XMA/openapi.json
