This workflow follows the Execute Workflow Trigger → Google Sheets recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "Google Maps Email Scraper Template",
"tags": [],
"nodes": [
{
"id": "79df5316-c210-478d-a4de-35b5d31924ee",
"name": "Remove Duplicate URLs",
"type": "n8n-nodes-base.removeDuplicates",
"position": [
-780,
380
],
"parameters": {},
"typeVersion": 1.1
},
{
"id": "985ac7e3-b501-4079-a043-780677c94b52",
"name": "Loop over queries",
"type": "n8n-nodes-base.splitInBatches",
"position": [
-1080,
-100
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "3a478935-781b-4fb1-bdc7-fcf8be1334bc",
"name": "Search Google Maps with query",
"type": "n8n-nodes-base.httpRequest",
"position": [
-1380,
380
],
"parameters": {
"url": "=https://www.google.com/maps/search/{{ $json.query }}",
"options": {
"allowUnauthorizedCerts": false
}
},
"executeOnce": false,
"typeVersion": 4.2,
"alwaysOutputData": false
},
{
"id": "477e7d55-b7d6-4b20-ac44-dd1f443e270a",
"name": "Scrape URLs from results",
"type": "n8n-nodes-base.code",
"position": [
-1180,
380
],
"parameters": {
"jsCode": "const data = $input.first().json.data\n\nconst regex = /https?:\\/\\/[^\\/]+/g\n\nconst urls = data.match(regex)\n\nreturn urls.map(url => ({json: {url: url}}))"
},
"typeVersion": 2
},
{
"id": "a5b67e45-a3f6-41d2-aa58-c26a441c41b2",
"name": "Filter irrelevant URLs",
"type": "n8n-nodes-base.filter",
"position": [
-980,
380
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "041797f2-2fe2-41dc-902a-d34050b9b304",
"operator": {
"type": "string",
"operation": "notRegex"
},
"leftValue": "={{ $json.url }}",
"rightValue": "=(google|gstatic|ggpht|schema\\.org|example\\.com|sentry-next\\.wixpress\\.com|imli\\.com|sentry\\.wixpress\\.com|ingest\\.sentry\\.io)"
},
{
"id": "eb499a7e-17bc-453c-be08-a47286f726dd",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "40ec6d1f-1c98-4c9f-8499-c5893c3df7b9",
"name": "Request web page for URL",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueRegularOutput",
"position": [
-380,
460
],
"parameters": {
"url": "={{ $json.url }}",
"options": {}
},
"typeVersion": 4.2,
"alwaysOutputData": false
},
{
"id": "12f662a8-c55f-409a-b381-f37ab6dd3794",
"name": "Loop over URLs",
"type": "n8n-nodes-base.splitInBatches",
"onError": "continueErrorOutput",
"position": [
-580,
380
],
"parameters": {
"options": {
"reset": false
}
},
"typeVersion": 3
},
{
"id": "e6957d05-3533-48ae-9cc1-ee4ac026a2a6",
"name": "Loop over pages",
"type": "n8n-nodes-base.splitInBatches",
"onError": "continueErrorOutput",
"position": [
-360,
120
],
"parameters": {
"options": {}
},
"typeVersion": 3,
"alwaysOutputData": false
},
{
"id": "018621c0-0ea9-4865-b110-b6d0727f0588",
"name": "Scrape emails from page",
"type": "n8n-nodes-base.code",
"onError": "continueRegularOutput",
"position": [
-200,
220
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const data = $json.data\n\nconst emailRegex = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.(?!png|jpg|gif|jpeg)[a-zA-Z]{2,}/g\n\nconst emails = data.match(emailRegex)\n\nreturn {json: {emails: emails}}"
},
"typeVersion": 2
},
{
"id": "5509b8e2-a6fc-4fbe-bbc5-1bc1d5de1c98",
"name": "Aggregate arrays of emails",
"type": "n8n-nodes-base.aggregate",
"position": [
-40,
100
],
"parameters": {
"options": {
"mergeLists": true
},
"fieldsToAggregate": {
"fieldToAggregate": [
{
"fieldToAggregate": "emails"
}
]
}
},
"typeVersion": 1
},
{
"id": "f1f01f03-b62e-453f-b938-ffe4f9b3f4de",
"name": "Split out into default data structure",
"type": "n8n-nodes-base.splitOut",
"position": [
180,
100
],
"parameters": {
"options": {},
"fieldToSplitOut": "emails"
},
"typeVersion": 1
},
{
"id": "ec27d665-d9c1-4f10-9c52-0d5ea89cbf77",
"name": "Remove duplicate emails",
"type": "n8n-nodes-base.removeDuplicates",
"position": [
400,
100
],
"parameters": {
"compare": "selectedFields",
"options": {},
"fieldsToCompare": "emails"
},
"typeVersion": 1.1
},
{
"id": "4a071bf0-23ad-455b-b231-bafd3b32e4f8",
"name": "Filter irrelevant emails",
"type": "n8n-nodes-base.filter",
"position": [
600,
100
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "041797f2-2fe2-41dc-902a-d34050b9b304",
"operator": {
"type": "string",
"operation": "notRegex"
},
"leftValue": "={{ $json.emails }}",
"rightValue": "=(google|gstatic|ggpht|schema\\.org|example\\.com|sentry\\.wixpress\\.com|sentry-next\\.wixpress\\.com|ingest\\.sentry\\.io|sentry\\.io|imli\\.com)"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "59675faa-2b0d-4ba5-82c7-dc5dedcad31e",
"name": "Save emails to Google Sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
800,
100
],
"parameters": {
"columns": {
"value": {
"Emails": "={{ $json.emails }}"
},
"schema": [
{
"id": "Emails",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Emails",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"Emails"
]
},
"options": {},
"operation": "append"
},
"typeVersion": 4.5
},
{
"id": "93437e8b-4f8d-40a1-9585-cab1b556164a",
"name": "Starts scraper workflow",
"type": "n8n-nodes-base.executeWorkflowTrigger",
"position": [
-1600,
380
],
"parameters": {},
"typeVersion": 1
},
{
"id": "eed77477-777d-450d-a975-4d2848b1cf55",
"name": "Run workflow",
"type": "n8n-nodes-base.manualTrigger",
"position": [
-1320,
-100
],
"parameters": {},
"typeVersion": 1
},
{
"id": "dffaf04e-d1d2-4002-9a69-f0904b61fc2d",
"name": "Wait between executions",
"type": "n8n-nodes-base.wait",
"position": [
-700,
0
],
"parameters": {
"amount": 2
},
"typeVersion": 1.1
},
{
"id": "18787007-1d11-41b9-89c3-d5f69756eda7",
"name": "Execute scraper for query",
"type": "n8n-nodes-base.executeWorkflow",
"position": [
-880,
0
],
"parameters": {
"mode": "each",
"options": {
"waitForSubWorkflow": false
},
"workflowId": {
"__rl": true,
"mode": "id",
"value": "={{ $workflow.id }}"
}
},
"typeVersion": 1.1
},
{
"id": "67fcde25-05e4-437c-b799-4448baea7891",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2280,
-140
],
"parameters": {
"color": 5,
"width": 740,
"height": 180,
"content": "## \ud83d\udee0 Setup\n1. Setup your list of queries in the \"Run workflow\" manual trigger node. Watch this [video](https://youtu.be/HaiO-UeiKBA) on how to generate the queries with ChatGPT.\n3. Choose a sheet to populate with data in the **Google Sheets node**\n4. Run the workflow and start getting leads into your Google Sheets document"
},
"typeVersion": 1
},
{
"id": "ac880457-44b4-4ff7-8440-b4107f8468bb",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-700,
-120
],
"parameters": {
"color": 6,
"height": 100,
"content": "**Optional** \ud83d\udc47\nSet wait time between each query workflow execution. Default is 2 seconds."
},
"typeVersion": 1
},
{
"id": "d83afb3d-7b71-4b47-9b50-28837aac408c",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1600,
260
],
"parameters": {
"width": 480,
"height": 100,
"content": "### Scraper \ud83d\udc47\nThis workflow will be executed in the background for each query. Click the **All executions** tab in the left sidebar to see the executions running."
},
"typeVersion": 1
},
{
"id": "007b621a-3d41-4358-aa45-560a3c8e3414",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
820,
300
],
"parameters": {
"color": 4,
"height": 180,
"content": "\ud83d\udc46 \n1. Setup your **credentials**. Here's a [video tutorial](https://youtu.be/O5RnWDM27M8) on how to do that.\n\n2. Choose which document and sheet to save the scraped emails to. "
},
"typeVersion": 1
},
{
"id": "fc0b837f-624c-4d25-8ed7-f787f76c785b",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1760,
-360
],
"parameters": {
"color": 3,
"content": " ## \u26a0\ufe0f Note\n\nA [video tutorial](https://youtu.be/HaiO-UeiKBA) for this workflow guide is available on my [Youtube channel](https://www.youtube.com/channel/UCn8xmUBunez1SsDVRfZDUGA)"
},
"typeVersion": 1
},
{
"id": "2f8665d5-2890-4f7d-908b-9c09a66b6c93",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2280,
-360
],
"parameters": {
"color": 7,
"width": 480,
"height": 140,
"content": "## Google Maps Automatic Email Scraper\n\nThis workflow automatically scrapes emails from businesses on Google Maps based on a list of queries that you provide."
},
"typeVersion": 1
},
{
"id": "7414b2ed-259d-47da-bbd1-d9ce0d64d43c",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1000,
540
],
"parameters": {
"color": 6,
"width": 160,
"height": 100,
"content": "**Optional** \ud83d\udc46\nAdd or change the regex for filtering irrelevant URLs."
},
"typeVersion": 1
},
{
"id": "789c9a02-e6e7-4ea6-a7a2-acc7715b377a",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
580,
260
],
"parameters": {
"color": 6,
"width": 200,
"height": 100,
"content": "**Optional** \ud83d\udc46\nAdd or change the regex for filtering irrelevant/incorrect email addresses."
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"connections": {
"Run workflow": {
"main": [
[
{
"node": "Loop over queries",
"type": "main",
"index": 0
}
]
]
},
"Loop over URLs": {
"main": [
[
{
"node": "Loop over pages",
"type": "main",
"index": 0
}
],
[
{
"node": "Request web page for URL",
"type": "main",
"index": 0
}
]
]
},
"Loop over pages": {
"main": [
[
{
"node": "Aggregate arrays of emails",
"type": "main",
"index": 0
}
],
[
{
"node": "Scrape emails from page",
"type": "main",
"index": 0
}
]
]
},
"Loop over queries": {
"main": [
[],
[
{
"node": "Execute scraper for query",
"type": "main",
"index": 0
}
]
]
},
"Remove Duplicate URLs": {
"main": [
[
{
"node": "Loop over URLs",
"type": "main",
"index": 0
}
]
]
},
"Filter irrelevant URLs": {
"main": [
[
{
"node": "Remove Duplicate URLs",
"type": "main",
"index": 0
}
]
]
},
"Remove duplicate emails": {
"main": [
[
{
"node": "Filter irrelevant emails",
"type": "main",
"index": 0
}
]
]
},
"Scrape emails from page": {
"main": [
[
{
"node": "Loop over pages",
"type": "main",
"index": 0
}
]
]
},
"Starts scraper workflow": {
"main": [
[
{
"node": "Search Google Maps with query",
"type": "main",
"index": 0
}
]
]
},
"Wait between executions": {
"main": [
[
{
"node": "Loop over queries",
"type": "main",
"index": 0
}
]
]
},
"Filter irrelevant emails": {
"main": [
[
{
"node": "Save emails to Google Sheet",
"type": "main",
"index": 0
}
]
]
},
"Request web page for URL": {
"main": [
[
{
"node": "Loop over URLs",
"type": "main",
"index": 0
}
]
]
},
"Scrape URLs from results": {
"main": [
[
{
"node": "Filter irrelevant URLs",
"type": "main",
"index": 0
}
]
]
},
"Execute scraper for query": {
"main": [
[
{
"node": "Wait between executions",
"type": "main",
"index": 0
}
]
]
},
"Aggregate arrays of emails": {
"main": [
[
{
"node": "Split out into default data structure",
"type": "main",
"index": 0
}
]
]
},
"Search Google Maps with query": {
"main": [
[
{
"node": "Scrape URLs from results",
"type": "main",
"index": 0
}
]
]
},
"Split out into default data structure": {
"main": [
[
{
"node": "Remove duplicate emails",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
How this works
Efficiently extract email addresses from businesses listed on Google Maps to build targeted contact lists without manual searching, saving hours of tedious work for marketers and sales teams. This workflow automates scraping emails from search results using HTTP requests to query Google Maps and fetch web pages, then processes the data for clean outputs. The key step involves looping through search queries in batches to handle multiple locations systematically, integrating seamlessly with Google Sheets for storing results.
Use this template when you need to gather emails for outreach campaigns based on specific Google Maps searches, such as local service providers in a city. Avoid it for high-volume scraping that might trigger rate limits or violate terms of service; instead, opt for official APIs where available. Common variations include adding email validation nodes or exporting directly to CRM tools like HubSpot for immediate follow-up.
About this workflow
Google Maps Email Scraper Template. Uses removeDuplicates, splitInBatches, httpRequest, splitOut. Event-driven trigger; 26 nodes.
Source: https://github.com/Zie619/n8n-workflows — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Email Scapper. Uses httpRequest, googleSheets, executeWorkflowTrigger. Event-driven trigger; 26 nodes.
ITHome比賽進程. Uses httpRequest, googleSheets, executeWorkflowTrigger, n8n. Event-driven trigger; 25 nodes.
25-scrape-business-emails-from-google-maps-without-the-use-of-any-third-party-apis. Uses httpRequest, googleSheets, executeWorkflowTrigger. Event-driven trigger; 23 nodes.
Intelligent URL Validation - Validates PDF URLs before attempting download, extracting filenames from URLs and generating fallback names when needed, preventing wasted processing time Binary File Hand
LINE Image Handler. Uses executeWorkflowTrigger, googleSheets, httpRequest, googleDrive. Event-driven trigger; 17 nodes.