{ "name": "Google Maps Email Scraper Template", "tags": [ "automation", "n8n", "production-ready", "excellent", "optimized" ], "nodes": [ { "id": "79df5316-c210-478d-a4de-35b5d31924ee", "name": "Remove Duplicate URLs", "type": "n8n-nodes-base.removeDuplicates", "position": [ -780, 380 ], "parameters": {}, "typeVersion": 1.1, "notes": "This removeDuplicates node performs automated tasks as part of the workflow." }, { "id": "985ac7e3-b501-4079-a043-780677c94b52", "name": "Loop over queries", "type": "n8n-nodes-base.splitInBatches", "position": [ -1080, -100 ], "parameters": { "options": {} }, "typeVersion": 3, "notes": "This splitInBatches node performs automated tasks as part of the workflow." }, { "id": "3a478935-781b-4fb1-bdc7-fcf8be1334bc", "name": "Search Google Maps with query", "type": "n8n-nodes-base.httpRequest", "position": [ -1380, 380 ], "parameters": { "url": "{{ $env.BASE_URL }}", "options": { "allowUnauthorizedCerts": false } }, "executeOnce": false, "typeVersion": 4.2, "alwaysOutputData": false, "notes": "This httpRequest node performs automated tasks as part of the workflow." }, { "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, "notes": "This code node performs automated tasks as part of the workflow." }, { "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, "notes": "This filter node performs automated tasks as part of the workflow." }, { "id": "40ec6d1f-1c98-4c9f-8499-c5893c3df7b9", "name": "Request web page for URL", "type": "n8n-nodes-base.httpRequest", "onError": "continueRegularOutput", "position": [ -380, 460 ], "parameters": { "url": "{{ $env.BASE_URL }}", "options": {} }, "typeVersion": 4.2, "alwaysOutputData": false, "notes": "This httpRequest node performs automated tasks as part of the workflow." }, { "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, "notes": "This splitInBatches node performs automated tasks as part of the workflow." }, { "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, "notes": "This splitInBatches node performs automated tasks as part of the workflow." }, { "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, "notes": "This code node performs automated tasks as part of the workflow." }, { "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, "notes": "This aggregate node performs automated tasks as part of the workflow." }, { "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, "notes": "This splitOut node performs automated tasks as part of the workflow." }, { "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, "notes": "This removeDuplicates node performs automated tasks as part of the workflow." }, { "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, "notes": "This filter node performs automated tasks as part of the workflow." }, { "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, "notes": "This googleSheets node performs automated tasks as part of the workflow." }, { "id": "93437e8b-4f8d-40a1-9585-cab1b556164a", "name": "Starts scraper workflow", "type": "n8n-nodes-base.executeWorkflowTrigger", "position": [ -1600, 380 ], "parameters": {}, "typeVersion": 1, "notes": "This executeWorkflowTrigger node performs automated tasks as part of the workflow." }, { "id": "eed77477-777d-450d-a975-4d2848b1cf55", "name": "Run workflow", "type": "n8n-nodes-base.manualTrigger", "position": [ -1320, -100 ], "parameters": {}, "typeVersion": 1, "notes": "This manualTrigger node performs automated tasks as part of the workflow." }, { "id": "dffaf04e-d1d2-4002-9a69-f0904b61fc2d", "name": "Wait between executions", "type": "n8n-nodes-base.wait", "position": [ -700, 0 ], "webhookId": "40eb11a9-0f7d-4932-993e-0052b69dbf9b", "parameters": { "amount": 2 }, "typeVersion": 1.1, "notes": "This wait node performs automated tasks as part of the workflow." }, { "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, "notes": "This executeWorkflow node performs automated tasks as part of the workflow." }, { "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": "## 🛠 Setup\n1. Setup your list of queries in the \"Run workflow\" manual trigger node. Watch this [video]({{ $env.WEBHOOK_URL }} 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, "notes": "This stickyNote node performs automated tasks as part of the workflow." }, { "id": "ac880457-44b4-4ff7-8440-b4107f8468bb", "name": "Sticky Note2", "type": "n8n-nodes-base.stickyNote", "position": [ -700, -120 ], "parameters": { "color": 6, "height": 100, "content": "**Optional** 👇\nSet wait time between each query workflow execution. Default is 2 seconds." }, "typeVersion": 1, "notes": "This stickyNote node performs automated tasks as part of the workflow." }, { "id": "d83afb3d-7b71-4b47-9b50-28837aac408c", "name": "Sticky Note3", "type": "n8n-nodes-base.stickyNote", "position": [ -1600, 260 ], "parameters": { "width": 480, "height": 100, "content": "### Scraper 👇\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, "notes": "This stickyNote node performs automated tasks as part of the workflow." }, { "id": "007b621a-3d41-4358-aa45-560a3c8e3414", "name": "Sticky Note4", "type": "n8n-nodes-base.stickyNote", "position": [ 820, 300 ], "parameters": { "color": 4, "height": 180, "content": "👆 \n1. Setup your **credentials**. Here's a [video tutorial]({{ $env.WEBHOOK_URL }} on how to do that.\n\n2. Choose which document and sheet to save the scraped emails to. " }, "typeVersion": 1, "notes": "This stickyNote node performs automated tasks as part of the workflow." }, { "id": "fc0b837f-624c-4d25-8ed7-f787f76c785b", "name": "Sticky Note5", "type": "n8n-nodes-base.stickyNote", "position": [ -1760, -360 ], "parameters": { "color": 3, "content": " ## ⚠️ Note\n\nA [video tutorial]({{ $env.WEBHOOK_URL }} for this workflow guide is available on my [Youtube channel]({{ $env.WEBHOOK_URL }}" }, "typeVersion": 1, "notes": "This stickyNote node performs automated tasks as part of the workflow." }, { "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, "notes": "This stickyNote node performs automated tasks as part of the workflow." }, { "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** 👆\nAdd or change the regex for filtering irrelevant URLs." }, "typeVersion": 1, "notes": "This stickyNote node performs automated tasks as part of the workflow." }, { "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** 👆\nAdd or change the regex for filtering irrelevant/incorrect email addresses." }, "typeVersion": 1, "notes": "This stickyNote node performs automated tasks as part of the workflow." } ], "active": false, "pinData": { "Run workflow": [ { "json": { "query": "hollywood+dentist" } }, { "json": { "query": "downtown+los+angeles+dentist" } }, { "json": { "query": "santa+monica+dentist" } }, { "json": { "query": "westwood+dentist" } }, { "json": { "query": "west+l.a.+dentist" } }, { "json": { "query": "the+valley+dentist" } }, { "json": { "query": "echo+park+dentist" } }, { "json": { "query": "culver+city+dentist" } }, { "json": { "query": "pasadena+dentist" } }, { "json": { "query": "silver+lake+dentist" } }, { "json": { "query": "mid-wilshire+dentist" } }, { "json": { "query": "beverly+hills+dentist" } }, { "json": { "query": "north+hills+dentist" } }, { "json": { "query": "south+los+angeles+dentist" } } ] }, "settings": { "executionOrder": "v1", "saveManualExecutions": true, "callerPolicy": "workflowsFromSameOwner", "errorWorkflow": null, "timezone": "UTC", "executionTimeout": 3600, "maxExecutions": 1000, "retryOnFail": true, "retryCount": 3, "retryDelay": 1000 }, "connections": { "3a478935-781b-4fb1-bdc7-fcf8be1334bc": { "main": [ [ { "node": "error-handler-3a478935-781b-4fb1-bdc7-fcf8be1334bc", "type": "main", "index": 0 } ], [ { "node": "error-handler-3a478935-781b-4fb1-bdc7-fcf8be1334bc-78a03323", "type": "main", "index": 0 } ], [ { "node": "error-handler-3a478935-781b-4fb1-bdc7-fcf8be1334bc-1f42733f", "type": "main", "index": 0 } ], [ { "node": "error-handler-3a478935-781b-4fb1-bdc7-fcf8be1334bc-4b75a47c", "type": "main", "index": 0 } ], [ { "node": "error-handler-3a478935-781b-4fb1-bdc7-fcf8be1334bc-c242f2e2", "type": "main", "index": 0 } ] ] }, "40ec6d1f-1c98-4c9f-8499-c5893c3df7b9": { "main": [ [ { "node": "error-handler-40ec6d1f-1c98-4c9f-8499-c5893c3df7b9", "type": "main", "index": 0 } ], [ { "node": "error-handler-40ec6d1f-1c98-4c9f-8499-c5893c3df7b9-13e4135a", "type": "main", "index": 0 } ], [ { "node": "error-handler-40ec6d1f-1c98-4c9f-8499-c5893c3df7b9-65879247", "type": "main", "index": 0 } ], [ { "node": "error-handler-40ec6d1f-1c98-4c9f-8499-c5893c3df7b9-16ce3c47", "type": "main", "index": 0 } ], [ { "node": "error-handler-40ec6d1f-1c98-4c9f-8499-c5893c3df7b9-1fbd6859", "type": "main", "index": 0 } ] ] }, "59675faa-2b0d-4ba5-82c7-dc5dedcad31e": { "main": [ [ { "node": "error-handler-59675faa-2b0d-4ba5-82c7-dc5dedcad31e-8c2af624", "type": "main", "index": 0 } ] ] } }, "description": "Automated workflow: Google Maps Email Scraper Template. This workflow integrates 14 different services: filter, httpRequest, stickyNote, wait, code. It contains 31 nodes and follows best practices for error handling and security.", "meta": { "instanceId": "workflow-e6f1715c", "versionId": "1.0.0", "createdAt": "2025-09-29T07:07:58.738915", "updatedAt": "2025-09-29T07:07:58.738975", "owner": "n8n-user", "license": "MIT", "category": "automation", "status": "active", "priority": "high", "environment": "production" }, "notes": "Excellent quality workflow: Google Maps Email Scraper Template. This workflow has been optimized for production use with comprehensive error handling, security, and documentation." }