Google Maps to Google Sheets, clean email leads
You find a great niche. You open Google Maps. Then you start copying names, websites, and “maybe” emails into a sheet. Twenty minutes later, your rows are a mess and half the sites don’t even have contact info.
Marketing managers trying to feed outreach campaigns feel this pain fast. So do agency owners building lists for clients, and solo consultants who just want Google Maps leads without paying for another database. The goal is simple: a clean, usable list you can actually email.
This n8n workflow turns Google Maps searches into deduped, consistent Google Sheets rows with real websites and business emails. You’ll see how it works, what you need, and where people usually trip up.
How This Automation Works
See how this solves the problem:
n8n Workflow Template: Google Maps to Google Sheets, clean email leads
flowchart LR
subgraph sg0["When chat message received Flow"]
direction LR
n0@{ icon: "mdi:cog", form: "rounded", label: "Remove Duplicates", pos: "b", h: 48 }
n1@{ icon: "mdi:swap-vertical", form: "rounded", label: "Loop Over Items", pos: "b", h: 48 }
n2@{ icon: "mdi:cog", form: "rounded", label: "Wait", pos: "b", h: 48 }
n3@{ icon: "mdi:cog", form: "rounded", label: "Wait1", pos: "b", h: 48 }
n4@{ icon: "mdi:swap-vertical", form: "rounded", label: "Split Out", pos: "b", h: 48 }
n5["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>Extract Emails"]
n6["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>Extract URLs"]
n7["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>Scrape Google Maps"]
n8["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>Scrape Site"]
n9@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Filter Out Empties", pos: "b", h: 48 }
n10@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Filter Google URLs", pos: "b", h: 48 }
n11@{ icon: "mdi:cog", form: "rounded", label: "Remove Duplicates (2)", pos: "b", h: 48 }
n12@{ icon: "mdi:database", form: "rounded", label: "Add to Sheet (or whatever yo..", pos: "b", h: 48 }
n13@{ icon: "mdi:play-circle", form: "rounded", label: "When chat message received", pos: "b", h: 48 }
n2 --> n5
n3 --> n9
n4 --> n11
n8 --> n2
n6 --> n10
n5 --> n1
n1 --> n3
n1 --> n8
n0 --> n1
n10 --> n0
n9 --> n4
n7 --> n6
n11 --> n12
n13 --> n7
end
%% Styling
classDef trigger fill:#e8f5e9,stroke:#388e3c,stroke-width:2px
classDef ai fill:#e3f2fd,stroke:#1976d2,stroke-width:2px
classDef aiModel fill:#e8eaf6,stroke:#3f51b5,stroke-width:2px
classDef decision fill:#fff8e1,stroke:#f9a825,stroke-width:2px
classDef database fill:#fce4ec,stroke:#c2185b,stroke-width:2px
classDef api fill:#fff3e0,stroke:#e65100,stroke-width:2px
classDef code fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
classDef disabled stroke-dasharray: 5 5,opacity: 0.5
class n13 trigger
class n9,n10 decision
class n12 database
class n7,n8 api
class n5,n6 code
classDef customIcon fill:none,stroke:none
class n5,n6,n7,n8 customIcon
The Challenge: Building Outreach Lists That Don’t Fall Apart
Google Maps looks like a goldmine until you try to turn it into an outreach list. You grab a business name, paste a URL, open the website, hunt for a contact page, then repeat. Now multiply that by 50 or 200 listings. It’s not just slow. It’s mentally exhausting, and it’s easy to “accidentally” skip the boring steps (which means you end up emailing fewer real decision-makers). Worse, the data is inconsistent. Some rows have websites, some don’t. Some “emails” are just social links. A week later, you don’t even trust your own sheet.
Here’s where it breaks down in real life.
- Manually opening websites for every listing can take about 5 minutes each, and you still miss emails hiding in footers or privacy pages.
- Google Maps often shows tracking links or internal Google URLs, so your “website” column becomes unusable for scraping.
- Duplicates creep in from similar searches (“Miami lawyers” and “Miami injury lawyer”), so outreach gets messy and embarrassing.
- Even when you do find an email, formatting varies, rows are inconsistent, and the list needs cleaning before it’s safe to send.
The Fix: Google Maps → Websites → Emails → Clean Google Sheet
This workflow builds a practical lead engine using n8n and plain HTTP requests, so you’re not locked into paid lead databases or expensive scraping APIs. It starts with a list of search queries you control (like “Calgary dentist” or “Miami lawyers”). For each query, it pulls Google Maps listing data, extracts real website URLs, and filters out junk links. Then it visits each website, scans the page content, and pulls email addresses using pattern matching (basically, smart text parsing). Finally, it cleans everything up: removing blanks, deduplicating, and pushing consistent rows into a Google Sheet tab that’s ready for outreach.
The workflow starts from a chat-style trigger in n8n, then runs the Google Maps search via HTTP. From there, code steps extract and validate web links, then another HTTP request fetches website content and parses email addresses. At the end, the deduped results append neatly into Google Sheets.
What Changes: Before vs. After
| What This Eliminates | Impact You’ll See |
|---|---|
|
|
Real-World Impact
Say you run 5 Google Maps searches and pull 20 listings per search (about 100 businesses). If you spend roughly 5 minutes per business to open the site, look for an email, and paste everything into a spreadsheet, that’s about 8 hours of tedious work. With this workflow, the “manual” part is adding the 5 searches to your Sheet and starting the run, which is maybe 10 minutes. The scraping and parsing takes time to process, but you’re not babysitting it, and the results land in your emails tab ready to use.
Requirements
- n8n instance (try n8n Cloud free)
- Self-hosting option if you prefer (Hostinger works well)
- Google Sheets for storing searches and results.
- Google account credentials to allow n8n to write rows.
- Access to target websites (some sites block scraping).
Skill level: Intermediate. You’ll paste a Sheet ID, connect Google credentials, and be comfortable testing small batches first.
Need help implementing this? Talk to an automation expert (free 15-minute consultation).
The Workflow Flow
A chat trigger kicks things off. You start the run from n8n (the workflow uses a chat input trigger), which is handy when you want to test quickly without setting up extra scheduling right away.
Google Maps gets queried via HTTP. The workflow sends your search query to Google Maps, collects listing data, then uses a code step to pull out website links in a usable format.
Links get cleaned and processed in batches. Filters remove Google-owned URLs, duplicates are stripped out, and a split-in-batches loop controls how fast the workflow visits websites. Wait steps add delays so you don’t hammer sites and get blocked.
Websites are fetched, emails are extracted, and the sheet is updated. Another HTTP request downloads each website’s content, the email parsing code finds likely addresses, empty results are discarded, and the final deduplicated email list is appended to your Google Sheets “emails” tab.
You can easily modify the searches tab to target different cities or niches based on your needs. See the full implementation guide below for customization options.
Step-by-Step Implementation Guide
Step 1: Configure the Chat Input Trigger
Start the workflow with a chat-based trigger that captures the Maps search query.
- Add and open Chat Input Trigger.
- Keep default options or customize the chat experience in Options as needed.
- Connect Chat Input Trigger to Query Maps Search to pass the user’s
{{$json.chatInput}}.
Step 2: Build the Maps Search and Link Extraction Chain
Fetch Google Maps results, extract website links, and remove unwanted Google URLs.
- Open Query Maps Search and set URL to
=https://www.google.com/maps/search/{{ $json.chatInput }}. - In Query Maps Search, keep Response set to full response and leave Allow Unauthorized Certs enabled if present.
- Open Pull Web Links and paste the provided JavaScript Code that extracts URLs via regex.
- Configure Exclude Google Links with the four Not Contains conditions using
{{ $json.website }}againstschema,google,gg, andgstatic. - Send results to Deduplicate Links to eliminate duplicate websites.
Step 3: Configure Batching and Fetch Delays
Iterate through each website and space requests to avoid rate limiting.
- Open Iterate Records to split incoming URLs into batches using default options.
- Connect Iterate Records to Pause Before Fetch to throttle requests before filtering emails.
- Connect Iterate Records to Fetch Website Content to retrieve each site’s HTML content.
- In Fetch Website Content, set URL to
={{ $json.website }}. - Open Delay Between Sites and set Amount to
1to add a pause between site scrapes. - Ensure Fetch Website Content flows into Delay Between Sites, then to Parse Email Addresses.
Step 4: Extract, Clean, and Deduplicate Emails
Parse email addresses from page content, filter empty results, and flatten into individual records.
- Open Parse Email Addresses and keep the provided JavaScript Code with the email-matching regex.
- Connect Parse Email Addresses to Iterate Records to continue processing each batch.
- Configure Remove Empty Emails with the Array exists condition using
{{ $json.emails }}. - In Expand Email List, set Field to Split Out to
emails. - Send results to Deduplicate Emails to remove duplicates before saving.
{ emails: [...] } and not null.Step 5: Configure the Google Sheets Output
Append cleaned email addresses into your spreadsheet.
- Open Append to Spreadsheet and set Operation to
append. - Select your spreadsheet in Document ID and replace the placeholder
[YOUR_ID]with the correct file. - Set Sheet Name to the target tab (currently
gid=0, namedemails). - Under Columns, map emails to
={{ $json.emails }}. - Credential Required: Connect your googleSheetsOAuth2Api credentials.
Step 6: Test and Activate Your Workflow
Validate the full flow from chat input to spreadsheet output and then activate it for production use.
- Click Execute Workflow and provide a sample query in Chat Input Trigger (e.g.,
dentists in Austin). - Confirm Query Maps Search returns HTML, Pull Web Links extracts URLs, and Parse Email Addresses outputs a list of emails.
- Verify rows appear in your Google Sheet after Append to Spreadsheet runs.
- Toggle the workflow to Active to use it in production.
Watch Out For
- Google Sheets credentials can expire or need specific permissions. If things break, check the n8n credentials screen and your Google account access first.
- If you’re using Wait nodes or external fetching, processing times vary. Bump up the wait duration if downstream nodes fail on empty responses.
- HTTP Request scraping can get blocked by some websites. If you suddenly get blank content, check response codes in the HTTP nodes and consider slowing batches or adjusting headers.
Common Questions
About 1–2 hours the first time, mainly for setup and testing.
Yes, but you will need someone comfortable connecting Google Sheets and testing runs. No heavy coding, though the workflow includes JavaScript nodes you’ll usually leave as-is.
Yes. n8n has a free self-hosted option and a free trial on n8n Cloud. Cloud plans start at $20/month for higher volume. You’ll also need to factor in general hosting costs if you self-host (and occasional extra time handling blocks from websites).
Two options: n8n Cloud (managed, easiest setup) or self-hosting on a VPS. For self-hosting, Hostinger VPS is affordable and handles n8n well. Self-hosting gives you unlimited executions but requires basic server management.
You can swap the input method by replacing the Chat Input Trigger with a schedule or a manual webhook, depending on how you prefer to run jobs. Most customization happens in the Google Sheets setup (the searches tab) and the code steps that “Pull Web Links” and “Parse Email Addresses.” Common tweaks include adding extra filters for certain industries, changing the batch size in the split-in-batches loop, and adjusting what columns get appended to Google Sheets.
Usually it’s expired Google credentials or missing permissions for the target spreadsheet. Reconnect the Google Sheets credential in n8n, then confirm the Google Sheet document ID is correct in the workflow. If it still fails, check whether the sheet is owned by a different Google account or locked down by a Workspace admin.
If you self-host, capacity is mostly your server and how aggressively you scrape.
For this use case, usually yes, because the workflow relies on HTTP requests, looping, filters, and a few code steps that are awkward (or expensive) in Zapier and Make. n8n also lets you self-host, which matters when you’re running lots of executions and don’t want per-task pricing to explode. Zapier and Make are still fine for lightweight two-step automations, but scraping-style lead workflows tend to outgrow them quickly. Honestly, the bigger factor is reliability: with n8n you can add waits, retries, and logic branches without turning it into a fragile chain of zaps. Talk to an automation expert if you want help choosing the right stack.
Once this is running, list building stops being a dreaded project and turns into a repeatable system. The workflow handles the repetitive digging so you can focus on messaging and replies.
Need Help Setting This Up?
Our automation experts can build and customize this workflow for your specific needs. Free 15-minute consultation—no commitment required.