AutomationFlowsMarketing & Ads › Extract Business Emails From Google Maps Listings for Lead Generation

Extract Business Emails From Google Maps Listings for Lead Generation

ByJose Castillo @j4ssn3o on n8n.io

This workflow scrapes Google Maps business listings (e.g., carpenters in Tarragona) to extract websites and email addresses — perfect for lead generation, local business prospecting, or agency outreach.

Event trigger★★★★☆ complexity20 nodesHTTP RequestGoogle Sheets
Marketing & Ads Trigger: Event Nodes: 20 Complexity: ★★★★☆ Added:

This workflow corresponds to n8n.io template #10074 — we link there as the canonical source.

This workflow follows the Google Sheets → HTTP Request 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 →

Download .json
{
  "nodes": [
    {
      "id": "f892006c-8856-4a24-8ad5-71fb19c57011",
      "name": "When clicking \u2018Test workflow\u2019",
      "type": "n8n-nodes-base.manualTrigger",
      "notes": "Entry point \u2014 manually start the workflow via the Test button.",
      "position": [
        -2400,
        384
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "202d221b-a899-455b-884f-1661496a9866",
      "name": "Scrape Google Maps",
      "type": "n8n-nodes-base.httpRequest",
      "notes": "Fetches the Google Maps search results page for 'calgary dentists'.",
      "position": [
        -2176,
        384
      ],
      "parameters": {
        "url": "https://www.google.YOUR_AWS_SECRET_KEY_HERE/@41.1402229,1.0832014,56063m/data=!3m1!1e3?entry=ttu&g_ep=EgoyMDI1MTAwMS4wIKXMDSoASAFQAw%3D%3D",
        "options": {
          "response": {
            "response": {
              "fullResponse": true
            }
          },
          "allowUnauthorizedCerts": true
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "50bc0bec-b364-41cb-84bd-9c26f1b92b86",
      "name": "Extract URLs",
      "type": "n8n-nodes-base.code",
      "notes": "Extracts all URLs from the HTML response and returns one item per URL.",
      "position": [
        -1952,
        384
      ],
      "parameters": {
        "jsCode": "const input = $input.first().json.data\nconst regex = /https?:\\/\\/[^\\/\\s\"'>]+/g\nconst websites = input?.match?.(regex) || []\nreturn websites.map(website => ({ json: { website } }))"
      },
      "typeVersion": 2
    },
    {
      "id": "65bbd225-9663-4853-82be-18ec96cd52b8",
      "name": "Filter Google URLs",
      "type": "n8n-nodes-base.filter",
      "notes": "Removes unwanted Google-related or tracking URLs.",
      "position": [
        -1728,
        384
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "bf0a5053-9660-457c-9581-964793bb6d7d",
              "operator": {
                "type": "string",
                "operation": "notContains"
              },
              "leftValue": "={{ $json.website }}",
              "rightValue": "schema"
            },
            {
              "id": "9110b9e0-12aa-45cc-bde0-9eda8c10970e",
              "operator": {
                "type": "string",
                "operation": "notContains"
              },
              "leftValue": "={{ $json.website }}",
              "rightValue": "google"
            },
            {
              "id": "fb9b6ed6-96a5-4560-ab10-b8a4b9a61a2b",
              "operator": {
                "type": "string",
                "operation": "notContains"
              },
              "leftValue": "={{ $json.website }}",
              "rightValue": "gg"
            },
            {
              "id": "10500c0b-cdbd-4816-aba3-df60d69845dc",
              "operator": {
                "type": "string",
                "operation": "notContains"
              },
              "leftValue": "={{ $json.website }}",
              "rightValue": "gstatic"
            },
            {
              "id": "c0f78219-b32c-4483-8596-22628a28acf7",
              "operator": {
                "type": "string",
                "operation": "notContains"
              },
              "leftValue": "={{ $json.website }}",
              "rightValue": "sentry.wixpress.com"
            },
            {
              "id": "d162a4cf-02f3-492e-adb7-333bf6cd152b",
              "operator": {
                "type": "string",
                "operation": "notContains"
              },
              "leftValue": "={{ $json.website }}",
              "rightValue": "sentry.io"
            },
            {
              "id": "1e88aa52-44e3-459e-bcec-e18bd3de3d2a",
              "operator": {
                "type": "string",
                "operation": "notContains"
              },
              "leftValue": "={{ $json.website }}",
              "rightValue": "sentry-next.wixpress.com"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "a6c87588-44f9-44f3-8b61-95e27d1e4442",
      "name": "Remove Duplicates",
      "type": "n8n-nodes-base.removeDuplicates",
      "notes": "Removes duplicate website URLs.",
      "position": [
        -1504,
        384
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 2
    },
    {
      "id": "902fc9fa-4908-460a-b3d5-e8396917b2fc",
      "name": "Limit",
      "type": "n8n-nodes-base.limit",
      "notes": "Limits the number of websites processed per run to 10.",
      "position": [
        -1280,
        384
      ],
      "parameters": {
        "maxItems": 100
      },
      "typeVersion": 1
    },
    {
      "id": "5b49547e-f87b-4e7f-97f8-ba4e4976fb90",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "notes": "Processes websites one at a time (batch processing).",
      "position": [
        -1056,
        384
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "86312345-b2e2-46cf-80bc-4836f58b9e44",
      "name": "Wait1",
      "type": "n8n-nodes-base.wait",
      "notes": "Adds a delay between requests to avoid server blocking.",
      "position": [
        -832,
        192
      ],
      "parameters": {},
      "typeVersion": 1.1
    },
    {
      "id": "eae01ed2-f39b-443f-91a5-39a6e8d98b91",
      "name": "Scrape Site",
      "type": "n8n-nodes-base.httpRequest",
      "notes": "Fetches the website HTML (does not follow redirects).",
      "onError": "continueRegularOutput",
      "position": [
        -832,
        384
      ],
      "parameters": {
        "url": "={{ $json.website }}",
        "options": {
          "redirect": {
            "redirect": {
              "followRedirects": false
            }
          }
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "b7f7a122-c882-4a58-9a80-9c94ad58b600",
      "name": "Wait",
      "type": "n8n-nodes-base.wait",
      "notes": "Short wait before parsing to prevent hitting rate limits.",
      "position": [
        -608,
        384
      ],
      "parameters": {
        "amount": 1
      },
      "typeVersion": 1.1
    },
    {
      "id": "dbe428f8-7a47-4438-a869-9813db4d1a4e",
      "name": "Extract Emails",
      "type": "n8n-nodes-base.code",
      "notes": "Extracts email addresses from the website HTML.",
      "onError": "continueRegularOutput",
      "position": [
        -384,
        464
      ],
      "parameters": {
        "jsCode": "const input = $input.first().json.data\nconst regex = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.(?!jpeg|jpg|png|gif|webp|svg)[a-zA-Z]{2,}/g\nconst emails = input?.match?.(regex) || []\nreturn { json: { emails } }"
      },
      "typeVersion": 2,
      "alwaysOutputData": true
    },
    {
      "id": "c25386cf-cfd0-4546-ae30-d79c628b0415",
      "name": "Filter Out Empties",
      "type": "n8n-nodes-base.filter",
      "notes": "Passes through only items where 'emails' exists and is not empty.",
      "position": [
        -608,
        192
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "a6786c58-424a-409a-b87f-8a7592cb7944",
              "operator": {
                "type": "array",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.emails }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "6367d624-1559-40ee-8f90-9293c0ce8847",
      "name": "Split Out",
      "type": "n8n-nodes-base.splitOut",
      "notes": "Splits multiple emails into separate items (one per row).",
      "position": [
        -384,
        192
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "emails"
      },
      "typeVersion": 1
    },
    {
      "id": "5b81ce13-0e56-4aac-aaa3-91be7d9103aa",
      "name": "Remove Duplicates (2)",
      "type": "n8n-nodes-base.removeDuplicates",
      "notes": "Removes duplicate emails before saving.",
      "position": [
        -160,
        192
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 2
    },
    {
      "id": "7fd76480-d159-4566-9f2c-12ee0e5797c2",
      "name": "Add to Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "notes": "Appends the extracted emails into the specified Google Sheet.",
      "position": [
        64,
        192
      ],
      "parameters": {
        "columns": {
          "value": {},
          "schema": [
            {
              "id": "T\u00edtulo",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "T\u00edtulo",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Texto",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Texto",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "HECHO",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "HECHO",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "TIKTOK",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "TIKTOK",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "SHORTS",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "SHORTS",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Fecha",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Fecha",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1mlBYMLXdNNp3yTVJHpt3nKgVmTUR4fi09dBpp3k41r8/edit#gid=0",
          "cachedResultName": "Hoja 1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1mlBYMLXdNNp3yTVJHpt3nKgVmTUR4fi09dBpp3k41r8",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1mlBYMLXdNNp3yTVJHpt3nKgVmTUR4fi09dBpp3k41r8/edit?usp=drivesdk",
          "cachedResultName": "ideas"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "b69e82bf-71b9-4fca-a086-53efd0c52ad7",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2512,
        592
      ],
      "parameters": {
        "width": 272,
        "height": 192,
        "content": "## Manual Trigger\nStarts the workflow when you click \u201cTest Workflow\u201d.\nUse this to manually run the scraper whenever you need fresh results."
      },
      "typeVersion": 1
    },
    {
      "id": "159c0f17-46b0-4ad1-8563-2e0bf506a164",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2128,
        576
      ],
      "parameters": {
        "width": 304,
        "height": 192,
        "content": "## Scrape Google Maps + Extract URLs\nFetches the HTML from your chosen Google Maps search, then extracts all website links from the page."
      },
      "typeVersion": 1
    },
    {
      "id": "5aaf7168-dc3b-4b49-a916-5e60de270f34",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1648,
        176
      ],
      "parameters": {
        "width": 448,
        "content": "## Filter Google URLs + Remove Duplicates + Limit\nRemoves unwanted Google/tracking links, keeps only unique websites, and limits total results to 100 for safe execution."
      },
      "typeVersion": 1
    },
    {
      "id": "c71740e9-a8d2-4cb2-955b-bae9f52db2ab",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -880,
        688
      ],
      "parameters": {
        "width": 384,
        "height": 112,
        "content": "## Scrape Site + Extract Emails\nVisits each website, extracts visible email addresses, and prepares them for export."
      },
      "typeVersion": 1
    },
    {
      "id": "164cbf16-1491-427e-b449-8921b90f78d9",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        0,
        0
      ],
      "parameters": {
        "width": 288,
        "content": "## Add to Google Sheet\nSaves all extracted emails directly into your Google Sheet (optional step)."
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Wait": {
      "main": [
        [
          {
            "node": "Extract Emails",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Limit": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait1": {
      "main": [
        [
          {
            "node": "Filter Out Empties",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Out": {
      "main": [
        [
          {
            "node": "Remove Duplicates (2)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Scrape Site": {
      "main": [
        [
          {
            "node": "Wait",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract URLs": {
      "main": [
        [
          {
            "node": "Filter Google URLs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Emails": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [
          {
            "node": "Wait1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Scrape Site",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Remove Duplicates": {
      "main": [
        [
          {
            "node": "Limit",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Google URLs": {
      "main": [
        [
          {
            "node": "Remove Duplicates",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Out Empties": {
      "main": [
        [
          {
            "node": "Split Out",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Scrape Google Maps": {
      "main": [
        [
          {
            "node": "Extract URLs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Remove Duplicates (2)": {
      "main": [
        [
          {
            "node": "Add to Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking \u2018Test workflow\u2019": {
      "main": [
        [
          {
            "node": "Scrape Google Maps",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

This workflow scrapes Google Maps business listings (e.g., carpenters in Tarragona) to extract websites and email addresses — perfect for lead generation, local business prospecting, or agency outreach.

Source: https://n8n.io/workflows/10074/ — original creator credit. Request a take-down →

More Marketing & Ads workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Marketing & Ads

Categories: Lead Generation, Web Scraping, Business Automation

HTTP Request, Google Sheets
Marketing & Ads

This template finds businesses on Google Maps → writes to Google Sheets → enriches + verifies email contact so your outreach stays clean and deliverable. It includes Sticky Notes** to explain the flow

HTTP Request, Google Sheets, @Verificaremails/N8N Nodes Verificaremails +1
Marketing & Ads

Description:

Google Sheets Trigger, Google Sheets, HTTP Request
Marketing & Ads

Description:

Google Sheets Trigger, Google Sheets, HTTP Request
Marketing & Ads

Edit Image. Uses executeWorkflowTrigger, httpRequest, convertToFile, googleSheets. Event-driven trigger; 12 nodes.

Execute Workflow Trigger, HTTP Request, Google Sheets +2