This workflow follows the Apifyn8N Nodes Apify → 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": "[VICTOR] Google Maps Extractor",
"nodes": [
{
"parameters": {
"formTitle": "Google Maps Scraper",
"formDescription": "Gere uma lista de leads a partir do Google Maps",
"formFields": {
"values": [
{
"fieldLabel": "Termo da Busca",
"placeholder": "dentista; petshop; ag\u00c3\u00aancia de marketing...",
"requiredField": true
},
{
"fieldLabel": "Cidade",
"requiredField": true
}
]
},
"options": {}
},
"type": "n8n-nodes-base.formTrigger",
"typeVersion": 2.2,
"position": [
-1504,
784
],
"id": "a819d1be-5ddd-4f10-8fb5-4aef65fe1d0a",
"name": "On form submission"
},
{
"parameters": {
"jsonSchemaExample": "{\n \"bairros\": [\n \"Batel\",\n \"Centro\",\n \"\u00c3gua Verde\",\n \"Santa Felicidade\",\n \"Cabral\"\n ]\n}"
},
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"typeVersion": 1.3,
"position": [
-1104,
1008
],
"id": "597cb649-4c64-43d0-8391-e4c0035bafc2",
"name": "Structured Output Parser"
},
{
"parameters": {
"model": {
"__rl": true,
"value": "chatgpt-4o-latest",
"mode": "list",
"cachedResultName": "chatgpt-4o-latest"
},
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"typeVersion": 1.2,
"position": [
-1360,
1024
],
"id": "460dc58e-c037-4988-8dc9-430660f2f347",
"name": "OpenAI Chat Model",
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "ebeb453d-bbaf-4e9e-b610-612337297b08",
"leftValue": "={{ $json.website }}",
"rightValue": "",
"operator": {
"type": "string",
"operation": "exists",
"singleValue": true
}
},
{
"id": "90d99c77-50b2-4d6f-90f5-8898313cb3c4",
"leftValue": "={{ $json.website }}",
"rightValue": "bit.ly",
"operator": {
"type": "string",
"operation": "notContains"
}
},
{
"id": "caf59970-6deb-4d13-a466-80faa63ad0a7",
"leftValue": "={{ $json.website }}",
"rightValue": "doctoralia",
"operator": {
"type": "string",
"operation": "notContains"
}
},
{
"id": "bfb3c998-981d-4ecb-b302-fc989e495780",
"leftValue": "={{ $json.website }}",
"rightValue": "whatsapp",
"operator": {
"type": "string",
"operation": "notContains"
}
},
{
"id": "8549d125-ff0a-404a-b27c-55fdcf95836d",
"leftValue": "={{ $json.website }}",
"rightValue": "instagram",
"operator": {
"type": "string",
"operation": "notContains"
}
},
{
"id": "5cdbd689-c1e6-4685-bee8-d44b54369eb5",
"leftValue": "={{ $json.website }}",
"rightValue": "facebook",
"operator": {
"type": "string",
"operation": "notContains"
}
},
{
"id": "6ec6a750-709b-474e-a98d-7263617e06fb",
"leftValue": "={{ $json.website }}",
"rightValue": "encurtador",
"operator": {
"type": "string",
"operation": "notContains"
}
},
{
"id": "c6befdb9-ba9c-4088-887f-f1473b3b9974",
"leftValue": "={{ $json.website }}",
"rightValue": "wa.me",
"operator": {
"type": "string",
"operation": "notContains"
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
-128,
720
],
"id": "c266fc07-b725-4320-b139-0cdc4ce8bebf",
"name": "Tem Website?"
},
{
"parameters": {
"method": "POST",
"url": "https://google.serper.dev/maps",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "X-API-KEY"
}
]
},
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "q",
"value": "={{ $('On form submission').item.json['Termo da Busca'] }} no {{ $json.bairro }} - {{ $('On form submission').item.json.Cidade }}"
},
{
"name": "hl",
"value": "pt-br"
}
]
},
"options": {
"redirect": {
"redirect": {}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-688,
784
],
"id": "7945230d-5d80-4277-9a84-da96eff3db5d",
"name": "Busca Google"
},
{
"parameters": {
"jsCode": "return items[0].json.output.bairros.map(bairro => {\n return { json: { bairro } };\n});"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-912,
784
],
"id": "8d3bfe19-7196-4fb6-83dc-b7157f4a207b",
"name": "Trata Dados"
},
{
"parameters": {
"options": {}
},
"type": "n8n-nodes-base.splitInBatches",
"typeVersion": 3,
"position": [
-480,
784
],
"id": "9820446e-418a-4d60-b629-d7f8ec70fce8",
"name": "Loop Over Items"
},
{
"parameters": {
"operation": "appendOrUpdate",
"documentId": {
"__rl": true,
"value": "SUA_PLANILHA_ID",
"mode": "list",
"cachedResultName": "Google Maps Scraper",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/SUA_PLANILHA_ID/edit?usp=drivesdk"
},
"sheetName": {
"__rl": true,
"value": "gid=0",
"mode": "list",
"cachedResultName": "P\u00c3\u00a1gina1",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/SUA_PLANILHA_ID/edit#gid=0"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"Telefone": "={{ \"'\" + $('Loop Over Items').item.json.phoneNumber }}",
"Nome": "={{ $('Loop Over Items').item.json.title }}",
"Bairro": "={{ $('Trata Dados').item.json.bairro }}",
"Cidade": "={{ $('On form submission').item.json.Cidade }}",
"Website": "={{ $('Loop Over Items').item.json.website }}",
"E-mail": "={{ $json.emails[0] }}",
"E-mail2": "={{ $json.emails[1] }}"
},
"matchingColumns": [
"Telefone"
],
"schema": [
{
"id": "Cidade",
"displayName": "Cidade",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "Bairro",
"displayName": "Bairro",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "Nome",
"displayName": "Nome",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "Telefone",
"displayName": "Telefone",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true,
"removed": false
},
{
"id": "Website",
"displayName": "Website",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "E-mail",
"displayName": "E-mail",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "E-mail2",
"displayName": "E-mail2",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {}
},
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.6,
"position": [
416,
480
],
"id": "76c3d1b8-78e8-48c6-833f-425814e8b939",
"name": "Add Row",
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const input = $json.data || \"\";\n\n// Regex b\u00c3\u00a1sica para capturar e-mails\nconst regex = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}/g;\nlet found = input.match(regex) || [];\n\n// Remove duplicados\nfound = [...new Set(found)];\n\n// Remove e-mails com extens\u00c3\u00b5es de imagem\nfound = found.filter(email => !email.match(/\\.(jpeg|jpg|png|gif|webp|svg)$/i));\n\n// Blacklist de dom\u00c3\u00adnios/termos \"fakes\"\nconst blacklist = [\n \"exemplo.com\", \"example.com\", \"test.com\", \"teste.com\", \"email.com\", \"oj.com\", \"emailteste.com\", \"dominio.com\", \"meudominio.com\", \"domain.com\"\n];\n\n// Fun\u00c3\u00a7\u00c3\u00a3o para checar se o e-mail \u00c3\u00a9 fake\nfunction isFakeEmail(email) {\n // Checa dom\u00c3\u00adnio na blacklist\n const domain = email.split(\"@\")[1] || \"\";\n return blacklist.some(bl => domain.toLowerCase().includes(bl))\n || email.toLowerCase().includes(\"exemplo\")\n || email.toLowerCase().includes(\"teste\")\n || email.toLowerCase().includes(\"test\")\n || email.toLowerCase().includes(\"sample\")\n || email.toLowerCase().includes(\"fake\");\n}\n\n// Filtra e-mails reais\nfound = found.filter(email => !isFakeEmail(email));\n\n// Limita a 2 resultados (ajuste conforme quiser)\nconst emails = found.slice(0, 2);\n\nreturn {\n json: {\n emails\n }\n};"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
816,
736
],
"id": "457db866-fa8c-4eca-8972-ba9a3fdf1b2e",
"name": "Extrai E-mails1",
"alwaysOutputData": true,
"onError": "continueRegularOutput"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "67a46d8d-b923-4cec-85e9-0ba1cc6a343e",
"leftValue": "={{ $json.error }}",
"rightValue": "",
"operator": {
"type": "object",
"operation": "empty",
"singleValue": true
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
624,
736
],
"id": "0e326d28-4cc8-4bfc-a232-6df1dc8694ec",
"name": "If Error Not Empty"
},
{
"parameters": {
"url": "={{ $json.website }}",
"options": {
"redirect": {
"redirect": {
"followRedirects": false
}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
448,
720
],
"id": "3ea9f5a1-0285-46c7-8545-49a77a0f69e3",
"name": "Scrape Site1",
"onError": "continueRegularOutput"
},
{
"parameters": {
"options": {}
},
"type": "n8n-nodes-base.splitInBatches",
"typeVersion": 3,
"position": [
240,
688
],
"id": "f0fc8a47-3a26-42be-91df-2a6be4f60407",
"name": "Loop Over Items1"
},
{
"parameters": {
"fieldToSplitOut": "places",
"options": {}
},
"type": "n8n-nodes-base.splitOut",
"typeVersion": 1,
"position": [
-224,
944
],
"id": "a61892e7-41d7-432e-b031-9d9aacf7d243",
"name": "Split Out"
},
{
"parameters": {
"url": "=https://exemplo.com.br/",
"options": {
"redirect": {
"redirect": {
"followRedirects": false
}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-1168,
96
],
"id": "25ead42d-f10a-4765-8a55-45c9fd1d5d22",
"name": "Scrape Site",
"onError": "continueRegularOutput"
},
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
-1424,
96
],
"id": "8c81ed27-8bd9-47b2-a5e7-c2a190396ab3",
"name": "When clicking \u00e2\u20ac\u02dcExecute workflow\u00e2\u20ac\u2122"
},
{
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const input = $json.data || \"\";\n\n// Regex b\u00c3\u00a1sica para capturar e-mails\nconst regex = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}/g;\nlet found = input.match(regex) || [];\n\n// Remove duplicados\nfound = [...new Set(found)];\n\n// Remove e-mails com extens\u00c3\u00b5es de imagem\nfound = found.filter(email => !email.match(/\\.(jpeg|jpg|png|gif|webp|svg)$/i));\n\n// Blacklist de dom\u00c3\u00adnios/termos \"fakes\"\nconst blacklist = [\n \"exemplo.com\", \"example.com\", \"test.com\", \"teste.com\", \"email.com\", \"oj.com\", \"emailteste.com\", \"dominio.com\", \"meudominio.com\", \"domain.com\"\n];\n\n// Fun\u00c3\u00a7\u00c3\u00a3o para checar se o e-mail \u00c3\u00a9 fake\nfunction isFakeEmail(email) {\n // Checa dom\u00c3\u00adnio na blacklist\n const domain = email.split(\"@\")[1] || \"\";\n return blacklist.some(bl => domain.toLowerCase().includes(bl))\n || email.toLowerCase().includes(\"exemplo\")\n || email.toLowerCase().includes(\"teste\")\n || email.toLowerCase().includes(\"test\")\n || email.toLowerCase().includes(\"sample\")\n || email.toLowerCase().includes(\"fake\");\n}\n\n// Filtra e-mails reais\nfound = found.filter(email => !isFakeEmail(email));\n\n// Limita a 2 resultados (ajuste conforme quiser)\nconst emails = found.slice(0, 2);\n\nreturn {\n json: {\n emails\n }\n};"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-896,
96
],
"id": "ed3fbb69-4756-48e3-93a6-5fc0b033240d",
"name": "Extrai E-mails2",
"alwaysOutputData": true,
"onError": "continueRegularOutput"
},
{
"parameters": {
"actorId": {
"__rl": true,
"mode": "list",
"value": ""
},
"timeout": {}
},
"type": "@apify/n8n-nodes-apify.apify",
"typeVersion": 1,
"position": [
-944,
-336
],
"id": "8b7d97e7-4c8d-4e39-91a7-8f9efe78b43d",
"name": "Run an Actor"
},
{
"parameters": {
"resource": "Default",
"operation": "Scrape A Url And Get Its Content",
"url": "https://www.exemplo.com.br/",
"formats": [
"markdown"
],
"requestOptions": {}
},
"type": "n8n-nodes-firecrawl.fireCrawl",
"typeVersion": 1,
"position": [
-1200,
-336
],
"id": "ad918ef8-9d79-4dd1-8261-164ca65774a9",
"name": "Scrape A Url And Get Its Content",
"credentials": {
"fireCrawlApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"promptType": "define",
"text": "=Cidade para buscar os bairros: {{ $json.Cidade }}",
"hasOutputParser": true,
"messages": {
"messageValues": [
{
"message": "=Sua especialidade \u00c3\u00a9 geografia do Brasil. Sua miss\u00c3\u00a3o \u00c3\u00a9 encontrar o nome de bairros em cidades do Brasil. \n\nO usu\u00c3\u00a1rio te dar\u00c3\u00a1 o nome de uma cidade e voc\u00c3\u00aa deve listar o nome dos 5 principais bairros daquela cidade. \n\n# Importante:\n- Nunca invente informa\u00c3\u00a7\u00c3\u00b5es. Nunca mesmo."
}
]
},
"batching": {}
},
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"typeVersion": 1.7,
"position": [
-1280,
784
],
"id": "644559d6-1cea-4c57-b145-3e9e498dd05b",
"name": "Gera Bairros"
},
{
"parameters": {
"content": "## N\u00c3\u00b3s da Comunidade\nEsses n\u00c3\u00b3s s\u00c3\u00a3o do Firecrawl e Apify. S\u00c3\u00b3 v\u00c3\u00a3o funcionar se voc\u00c3\u00aa instalar os comunity-nodes",
"height": 320,
"width": 752
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-1488,
-464
],
"id": "14e9fbf6-677c-4261-9194-2a536be5d79e",
"name": "Sticky Note"
},
{
"parameters": {
"content": "## Teste\nN\u00c3\u00b3s para testar scrape",
"height": 320,
"width": 816
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-1488,
-48
],
"id": "532244ce-0438-4819-9067-513086d3fb07",
"name": "Sticky Note1"
}
],
"connections": {
"On form submission": {
"main": [
[
{
"node": "Gera Bairros",
"type": "main",
"index": 0
}
]
]
},
"Structured Output Parser": {
"ai_outputParser": [
[
{
"node": "Gera Bairros",
"type": "ai_outputParser",
"index": 0
}
]
]
},
"OpenAI Chat Model": {
"ai_languageModel": [
[
{
"node": "Gera Bairros",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Tem Website?": {
"main": [
[
{
"node": "Loop Over Items1",
"type": "main",
"index": 0
}
],
[
{
"node": "Add Row",
"type": "main",
"index": 0
}
]
]
},
"Busca Google": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"Trata Dados": {
"main": [
[
{
"node": "Busca Google",
"type": "main",
"index": 0
}
]
]
},
"Loop Over Items": {
"main": [
[
{
"node": "Tem Website?",
"type": "main",
"index": 0
}
],
[
{
"node": "Split Out",
"type": "main",
"index": 0
}
]
]
},
"Extrai E-mails1": {
"main": [
[
{
"node": "Loop Over Items1",
"type": "main",
"index": 0
}
]
]
},
"If Error Not Empty": {
"main": [
[
{
"node": "Extrai E-mails1",
"type": "main",
"index": 0
}
],
[
{
"node": "Loop Over Items1",
"type": "main",
"index": 0
}
]
]
},
"Scrape Site1": {
"main": [
[
{
"node": "If Error Not Empty",
"type": "main",
"index": 0
}
]
]
},
"Loop Over Items1": {
"main": [
[
{
"node": "Add Row",
"type": "main",
"index": 0
}
],
[
{
"node": "Scrape Site1",
"type": "main",
"index": 0
}
]
]
},
"Add Row": {
"main": [
[]
]
},
"Split Out": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"Scrape Site": {
"main": [
[
{
"node": "Extrai E-mails2",
"type": "main",
"index": 0
}
]
]
},
"When clicking \u00e2\u20ac\u02dcExecute workflow\u00e2\u20ac\u2122": {
"main": [
[
{
"node": "Scrape Site",
"type": "main",
"index": 0
}
]
]
},
"Scrape A Url And Get Its Content": {
"main": [
[]
]
},
"Gera Bairros": {
"main": [
[
{
"node": "Trata Dados",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "VERSAO_ID",
"meta": {
"templateCredsSetupCompleted": true
},
"id": "ID_WORKFLOW",
"tags": [
{
"createdAt": "2025-06-18T22:14:11.679Z",
"updatedAt": "2025-06-18T22:14:11.679Z",
"id": "ID_TAG",
"name": "N8N Course"
}
]
}
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.
fireCrawlApigoogleSheetsOAuth2ApiopenAiApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
[VICTOR] Google Maps Extractor. Uses formTrigger, outputParserStructured, lmChatOpenAi, httpRequest. Event-driven trigger; 21 nodes.
Source: https://github.com/omoreiiraa/myn8n-workflows/blob/9b1508c27cf790e8ff9c8959a8f1d00485973fc0/scrapper.json — 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.
Community nodes are used in this workflow. B2B Sales Teams & SDRs Recruitment Agencies & Tech Recruiters Startup Founders Growth Marketing Teams Scrape Hiring Signals: The workflow starts by using an
viral-cat-video-creator. Uses formTrigger, chainLlm, lmChatMistralCloud, outputParserStructured. Event-driven trigger; 22 nodes.
Travel agencies, freelance travel planners, or anyone who wants to automate personalized trip planning by combining real-time hotel and flight data with AI-generated recommendations. Collects travel d
📚 Learners and educators who want a fast overview of a creator’s entire catalog. 🧩 Research, SEO, and content ops teams building an intelligence layer on top of YouTube channels.
The Recap AI - Nano Banana Static Ad Spinner. Uses formTrigger, @mendable/n8n-nodes-firecrawl, chainLlm, lmChatGoogleGemini. Event-driven trigger; 31 nodes.