# Landscaping & Lawn Care Lead Scraper – Google Maps (Unofficial) (`brainy_frostfield/landscaping-lawn-care-lead-scraper`) Actor

UNOFFICIAL Google Maps landscaping lead scraper with public website emails and free MX checks. Not affiliated with Google. No AI language models.

- **URL**: https://apify.com/brainy\_frostfield/landscaping-lawn-care-lead-scraper.md
- **Developed by:** [Viv K](https://apify.com/brainy_frostfield) (community)
- **Categories:** Lead generation, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 place leads

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/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

## Landscaping & Lawn Care Lead Scraper – Google Maps + Phone Email (Unofficial)

Build **landscaping lead lists** from public Google Maps listings and optional public website emails — with phone numbers, ratings, and free MX domain checks. No AI language models. No Google Places API key required.

> **UNOFFICIAL** — not affiliated with Google LLC. Residential proxy recommended for Maps.

### What does this Landscaping lead scraper do?

This Actor searches **Google Maps** for landscaping and lawn care contractors and related local businesses, then optionally visits each business’s **public website** to collect contact emails, social links, and contact-page URLs. It is built for agencies, SaaS founders, and sales teams who need structured **landscaping leads** with **phone + email** fields for CRM import.

You configure cities and keywords (for example `landscaping` in `Austin, TX`), set a small max results value for a test run, and download a clean dataset. Enrichment never invents emails with LLMs — only addresses that appear on public pages are saved.

### Features / What data you get

- Google Maps discovery by **search terms** + **locations**
- Core listing fields: **businessName**, **phone**, **phoneUnformatted**, **website**, **address** / **city**, **rating**, **reviewsCount**, **googleMapsUrl**, **placeId**, **lat** / **lng**, **category** (Maps category)
- Optional website enrichment: **emails** (with source URL + **mxValid**), **primaryEmail**, **socials**, **contactPageUrl**, **hasContactForm**
- Quality flags: **emailFound**, **enrichmentStatus** (`ok` | `skipped` | `failed`), **enrichmentError**
- Light **niche** tag from Maps/category text (lawn care, hardscape, tree service, irrigation, commercial, residential — no LLM)
- Dedup by **placeId**, residential Maps proxy by default, soft-fail enrichment (Maps row still saved if a site fails)

### How to run

1. Open the Actor Input tab.
2. Set **Target locations** to one city (try `Austin, TX`).
3. Set **Search terms** to `landscaping` (add related keywords later).
4. Set **Max results per query** to **1–5** for a first run.
5. Keep **Extract emails** on if you want website enrichment; set **Max pages per website** to 1–2 for a cheap test.
6. Confirm **Proxy for Google Maps** uses Apify Proxy → **RESIDENTIAL**.
7. Click **Start**, wait for the run to finish, then open the Dataset (**Overview** / **Contacts** views).

### Pricing

Pay-per-event (example, FREE tier — see the Pricing tab for live prices):

- **Actor start:** $0.00005
- **Place lead:** ~$0.004 per business saved from Maps
- **Email enrichment:** ~$0.005 only when at least one public website email is found

Example: 100 places, 40 with email ≈ 100×$0.004 + 40×$0.005 + start ≈ **$0.60** + proxy/platform usage.

### Input example

```json
{
  "locations": ["Austin, TX"],
  "searchTerms": ["landscaping"],
  "maxPlacesPerQuery": 1,
  "extractEmails": true,
  "validateMxRecords": true,
  "maxWebsitePagesPerPlace": 1,
  "maxScrolls": 3,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"]
  }
}
```

### Output example

```json
{
  "businessName": "Austin Premier Landscaping",
  "placeId": "ChIJxxxxxxxx",
  "category": "Landscaping contractor",
  "phone": "+1 512-555-0100",
  "phoneUnformatted": "15125550100",
  "primaryEmail": "info@austinpremierlandscape.com",
  "emails": [
    {
      "email": "info@austinpremierlandscape.com",
      "sourceUrl": "https://austinpremierlandscape.com/contact",
      "sourceType": "mailto",
      "mxValid": true,
      "confidence": "high"
    }
  ],
  "website": "https://austinpremierlandscape.com",
  "address": "123 Congress Ave, Austin, TX 78701",
  "city": "Austin",
  "rating": 4.7,
  "lat": 30.2672,
  "lng": -97.7431,
  "googleMapsUrl": "https://www.google.com/maps/place/?q=place_id:ChIJxxxxxxxx",
  "socials": { "facebook": null, "instagram": null },
  "contactPageUrl": "https://austinpremierlandscape.com/contact",
  "enrichmentStatus": "ok",
  "enrichmentError": null,
  "niche": "Landscaping contractor",
  "emailFound": true,
  "scrapedAt": "2026-09-23T12:00:00.000Z"
}
```

### Limitations

- Google Maps UI and anti-bot behavior change; residential proxy and retries help but do not guarantee 100% coverage.
- Some contractor sites are form-only or block bots — **enrichmentStatus** may be `failed` / `skipped` even when the Maps row is valid.
- Closed or temporarily closed listings can still appear depending on Maps results.
- Email miss rate is normal for franchise or JS-heavy sites; this Actor does not use LLM APIs to invent contacts.
- Large `maxPlacesPerQuery` values increase proxy and PPE spend — start small.

### FAQ / Legal

#### Is this an official Google tool?

No. This Actor is **unofficial** and **not affiliated with Google**. It collects
**publicly available** business information from Google Maps listings and from
public business websites.

#### Legal / compliance

You must use the data in line with applicable laws and Google’s terms. This tool
does not send emails or SMS. You are solely responsible for outreach compliance
(including CAN-SPAM, GDPR/CCPA where applicable) and for Apify’s Acceptable Use Policy.

Collects publicly available business information from Google Maps and public websites. Not affiliated with Google. Do not use for unlawful spam.

### Related Actors

| Actor slug | Niche |
|---|---|
| `dentist-lead-scraper-google-maps-email-finder` | Dentist |
| `roofing-lead-scraper-google-maps-phone-email` | Roofing |
| `plumbing-lead-scraper` | Plumbing |
| `electrician-lead-scraper` | Electrician |
| `hvac-lead-scraper-google-maps-phone-email` | HVAC |
| `pest-control-lead-scraper-google-maps-email` | Pest control |
| `garage-door-lead-scraper-google-maps` | Garage door |
| `locksmith-lead-scraper-google-maps-phone` | Locksmith |

Search these slugs on Apify under the same publisher family for sibling lead scrapers.

### Support

Use the Actor **Issues** tab on Apify for bugs, schema questions, or feature requests. Include run ID, input JSON (without secrets), and a short description of expected vs actual output.

# Actor input Schema

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

Enter Google Maps keywords (e.g. landscaping, lawn care, lawn mowing). Keep location separate in Target locations.

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

Enter cities, states, or ZIP codes (e.g. Austin, TX). Add more cities for multi-market runs.

## `maxPlacesPerQuery` (type: `integer`):

Set the maximum businesses per location × search term. Use 1 for a quick test; raise to 20–100 for production lists.

## `maxTotalPlaces` (type: `integer`):

Optionally cap the whole run. Leave empty or 0 to rely only on Max results per query.

## `includeNoWebsite` (type: `boolean`):

Keep listings even when Google Maps shows no website.

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

Enable to keep only leads that have a phone number.

## `onlyWithEmail` (type: `boolean`):

Enable to keep only leads with at least one public website email.

## `onlyMxValid` (type: `boolean`):

Enable to keep only leads where at least one email domain passes the MX check.

## `extractEmails` (type: `boolean`):

Enable to visit each business website (homepage, contact, about) and collect public emails. Form-only sites may have no email.

## `validateMxRecords` (type: `boolean`):

Enable a free DNS MX check so each email gets an mxValid flag.

## `maxWebsitePagesPerPlace` (type: `integer`):

Set how many website pages to check for emails (homepage, contact, about, etc.).

## `emailRequestDelayMs` (type: `integer`):

Set wait time between website page requests for polite crawling.

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

Use Apify residential proxy for Maps. Datacenter IPs are often blocked.

## `websiteProxyConfiguration` (type: `object`):

Optionally set a separate proxy for website email crawling. Leave empty to use the default network.

## `maxScrolls` (type: `integer`):

Set how many times to scroll the Maps results list to load more businesses.

## `debugLog` (type: `boolean`):

Enable to show more detail in the run log for troubleshooting.

## Actor input object example

```json
{
  "searchTerms": [
    "landscaping"
  ],
  "locations": [
    "Austin, TX"
  ],
  "maxPlacesPerQuery": 1,
  "includeNoWebsite": true,
  "onlyWithPhone": false,
  "onlyWithEmail": false,
  "onlyMxValid": false,
  "extractEmails": true,
  "validateMxRecords": true,
  "maxWebsitePagesPerPlace": 2,
  "emailRequestDelayMs": 800,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "maxScrolls": 10,
  "debugLog": false
}
```

# Actor output Schema

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

Default dataset of dentist lead rows (overview + contacts views).

# 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": [
        "landscaping"
    ],
    "locations": [
        "Austin, TX"
    ],
    "maxPlacesPerQuery": 1,
    "maxWebsitePagesPerPlace": 2
};

// Run the Actor and wait for it to finish
const run = await client.actor("brainy_frostfield/landscaping-lawn-care-lead-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": ["landscaping"],
    "locations": ["Austin, TX"],
    "maxPlacesPerQuery": 1,
    "maxWebsitePagesPerPlace": 2,
}

# Run the Actor and wait for it to finish
run = client.actor("brainy_frostfield/landscaping-lawn-care-lead-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": [
    "landscaping"
  ],
  "locations": [
    "Austin, TX"
  ],
  "maxPlacesPerQuery": 1,
  "maxWebsitePagesPerPlace": 2
}' |
apify call brainy_frostfield/landscaping-lawn-care-lead-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,brainy_frostfield/landscaping-lawn-care-lead-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/WPnGaY4uobPTTM0hi/builds/ZE0ksaL35S4hcASbT/openapi.json
