This workflow corresponds to n8n.io template #4555 — we link there as the canonical source.
This workflow follows the Agent → Form Trigger 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 →
{
"id": "S3otujHorKo0cvaH",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Extract Google My Business Leads by Service and Location with Bright Data to Google Sheets",
"tags": [],
"nodes": [
{
"id": "6c9e04d8-1a25-47e7-a8ef-536744866ae4",
"name": "Form Submission Trigger",
"type": "n8n-nodes-base.formTrigger",
"position": [
-640,
-200
],
"parameters": {
"options": {},
"formTitle": "Extract Business Data Using Service Name and Location",
"formFields": {
"values": [
{
"fieldLabel": "Service",
"placeholder": "Laptop Store",
"requiredField": true
},
{
"fieldLabel": "State",
"placeholder": "Texas",
"requiredField": true
},
{
"fieldType": "dropdown",
"fieldLabel": "Country",
"fieldOptions": {
"values": [
{
"option": "US"
},
{
"option": "India"
}
]
},
"requiredField": true
}
]
},
"formDescription": "Fill details to extract business leads"
},
"typeVersion": 2.2
},
{
"id": "cfb9e212-c53a-4ecd-a342-572a1dd93bfb",
"name": "Workflow Description",
"type": "n8n-nodes-base.stickyNote",
"position": [
-740,
-420
],
"parameters": {
"width": 300,
"height": 180,
"content": "## Extract Google My Business Leads by Service and Location\n**Description:** \nExtract Google business listings by service type and geographic location using Bright Data's Google Maps dataset. Automatically processes cities, removes duplicates, and saves results to Google Sheets."
},
"typeVersion": 1
},
{
"id": "2f5231af-2e5d-49fe-8534-c87cb2083c19",
"name": "Scrape Business Data from Google Maps",
"type": "@brightdata/n8n-nodes-brightdata.brightData",
"position": [
900,
60
],
"parameters": {
"urls": "=[\n {\n \"url\": \"https://www.google.com/maps/search/{{ $json.name }}+in+{{ $json.city }} {{ $json.state }}\",\n \"category\": \"{{ $json.category }}\",\n \"country_name\": \"{{ $json.country }}\",\n \"sample\": false\n }\n]\n ",
"resource": "webScrapper",
"dataset_id": {
"__rl": true,
"mode": "list",
"value": "gd_lh0tnzlo2bie4uhdhr",
"cachedResultName": "Google Maps businesses"
},
"requestOptions": {
"proxy": ""
}
},
"credentials": {
"brightdataApi": {
"name": "<your credential>"
}
},
"typeVersion": 1,
"alwaysOutputData": true
},
{
"id": "50b74589-0c38-4e77-b599-af3dab056dd6",
"name": "Claude AI Model for Cities",
"type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
"position": [
-400,
40
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "claude-sonnet-4-20250514",
"cachedResultName": "Claude 4 Sonnet"
},
"options": {}
},
"credentials": {
"anthropicApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.3
},
{
"id": "cb07c9ad-9522-46f7-bf81-eb22689f4e27",
"name": "Separate Data by City",
"type": "n8n-nodes-base.code",
"position": [
380,
-200
],
"parameters": {
"jsCode": "// Get values from input expressions\nconst serviceName = $('Form Submission Trigger').first().json.Service;\nconst state = $('Form Submission Trigger').first().json.State;\nconst country = $('Form Submission Trigger').first().json.Country;\nconst citiesString = $('Generate City List').first().json.output;\n\n// Validate required fields\nif (!serviceName || !state || !country || !citiesString) {\n throw new Error(\"Missing required input data (Service, State, Country, or City list)\");\n}\n\n// Split cities string by newline and clean extra spaces\nconst cities = citiesString.split('\\n').map(city => city.trim()).filter(city => city.length > 0);\n\n// Generate output items dynamically for each city\nconst output = cities.map(city => ({\n json: {\n name: serviceName,\n country: country,\n state: state,\n city: city,\n category: serviceName\n }\n}));\n\nreturn output;\n"
},
"typeVersion": 2
},
{
"id": "44478ce4-fd08-4e9e-bf2a-4116b5d6084c",
"name": "Generate City List",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
-400,
-200
],
"parameters": {
"text": "=Provide a list of cities or sub areas located inside the Location of {{ $json.State }}, within the country {{ $json.Country }}. This data will be used to search on Google maps for businesses in that region.\nThe output should be a plain text list, without bullets, numbering, or any special characters.\nDo not include any introduction, explanation, or concluding text\u2014only the list of city names.",
"options": {},
"promptType": "define"
},
"typeVersion": 2
},
{
"id": "d4416202-1a71-4f6f-b363-9f7d64e1855b",
"name": "Claude AI Model for Categories",
"type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
"position": [
0,
40
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "claude-sonnet-4-20250514",
"cachedResultName": "Claude 4 Sonnet"
},
"options": {}
},
"credentials": {
"anthropicApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.3
},
{
"id": "74894c83-f855-49ed-b523-1521aa46e28d",
"name": "Categorize Service Type",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
-20,
-200
],
"parameters": {
"text": "=Determine the appropriate category based on the following input: \"{{ $('Form Submission Trigger').item.json.Service }}\"\n\nThe output must contain only the category name that best describes the given service.\nExamples of categories include but are not limited to: Electronics, Healthcare, Education, Food & Beverage, Automotive, Finance, Real Estate, etc.",
"options": {},
"promptType": "define"
},
"typeVersion": 2
},
{
"id": "d3efe732-94cf-4d6e-b55f-12b7c1bb2a5c",
"name": "City Processing Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
300,
-300
],
"parameters": {
"height": 80,
"content": "Separate each search by city name for comprehensive coverage"
},
"typeVersion": 1
},
{
"id": "be50e961-e293-4376-9f96-5a279d20a37f",
"name": "Process Cities in Batches",
"type": "n8n-nodes-base.splitInBatches",
"position": [
640,
-200
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "d1b3ff9c-4dfc-42d5-ab4b-7e87c2b3d3b4",
"name": "Get Existing Business Data",
"type": "n8n-nodes-base.googleSheets",
"position": [
940,
-500
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit#gid=0",
"cachedResultName": "Business Leads"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "YOUR_GOOGLE_SHEET_ID",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit",
"cachedResultName": "Business Leads Database"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.6
},
{
"id": "a7d336a6-cfb4-4c34-a39b-98ba5f4b8633",
"name": "Check for Duplicate Entries",
"type": "n8n-nodes-base.code",
"position": [
1120,
-500
],
"parameters": {
"jsCode": "const items = $input.all();\n\nconst seen = new Map();\nconst duplicates = [];\n\nfor (const item of items) {\n const businessName = String(item.json['Business Name'] || '').trim().toLowerCase();\n const phoneNumber = String(item.json['Phone Number'] || '').trim();\n const address = item.json['Address'];\n const mapsUrl = item.json['Google Maps URL'];\n\n if (!businessName) continue;\n\n const key = businessName;\n\n if (seen.has(key)) {\n const previous = seen.get(key);\n\n if (!phoneNumber || phoneNumber === previous.phoneNumber) {\n duplicates.push({\n json: {\n Address: address,\n 'Google Maps URL': mapsUrl\n }\n });\n }\n\n } else {\n seen.set(key, { phoneNumber });\n }\n}\n\nreturn duplicates;\n"
},
"typeVersion": 2
},
{
"id": "5d5c8d06-0e7b-403f-b020-b46e5ebe3581",
"name": "Find Duplicate Row Number",
"type": "n8n-nodes-base.googleSheets",
"position": [
1600,
-480
],
"parameters": {
"options": {
"returnFirstMatch": true
},
"filtersUI": {
"values": [
{
"lookupValue": "={{ $json.Address }}",
"lookupColumn": "Address"
},
{
"lookupValue": "={{ $json['Google Maps URL'] }}",
"lookupColumn": "Google Maps URL"
}
]
},
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit#gid=0",
"cachedResultName": "Business Leads"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "YOUR_GOOGLE_SHEET_ID",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit",
"cachedResultName": "Business Leads Database"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"executeOnce": true,
"typeVersion": 4.6
},
{
"id": "5480a6a6-597b-4e9f-9d8e-1654fe2adff7",
"name": "Check Scraping Status",
"type": "n8n-nodes-base.if",
"position": [
1100,
60
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "ae36c72f-a772-499f-a1d7-92cf8a8d640c",
"operator": {
"type": "string",
"operation": "exists",
"singleValue": true
},
"leftValue": "={{ $json.message }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "f9d3b3b2-b9c3-4f28-8e5b-9cb965122038",
"name": "Delete Duplicate Row",
"type": "n8n-nodes-base.googleSheets",
"position": [
1880,
-480
],
"parameters": {
"operation": "delete",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit#gid=0",
"cachedResultName": "Business Leads"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "YOUR_GOOGLE_SHEET_ID",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit",
"cachedResultName": "Business Leads Database"
},
"startIndex": "={{ $json.row_number }}"
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"executeOnce": true,
"typeVersion": 4.6
},
{
"id": "a6fe2f90-d5e5-48cf-ab05-1a0c2f584533",
"name": "Process Duplicates in Batches",
"type": "n8n-nodes-base.splitInBatches",
"position": [
1340,
-500
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "1ac3e5d6-f738-42be-ada4-002781ea68ed",
"name": "Save Business Data to Sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
2340,
80
],
"parameters": {
"columns": {
"value": {
"City": "={{ $('Separate Data by City').item.json.city }}",
"Address": "={{ $json.address }}",
"Country": "={{ $json.country }}",
"Category": "={{ $json.category }}",
"Reviews URL": "={{ $json.reviews }}",
"Website URL": "={{ $json.open_website }}",
"Phone Number": "={{ $json.phone_number }}",
"Business Name": "={{ $json.name }}",
"Google Rating": "={{ $json.rating }}",
"Total Reviews": "={{ $json.reviews_count }}",
"Google Maps URL": "={{ $json.url }}",
"Operating Hours": "={{ $json.open_hours }}"
},
"schema": [
{
"id": "Business Name",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Business Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Website URL",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Website URL",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Category",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Category",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Country",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Country",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "City",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "City",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Phone Number",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Phone Number",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Google Maps URL",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Google Maps URL",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Address",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Address",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Operating Hours",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Operating Hours",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Google Rating",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Google Rating",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Total Reviews",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Total Reviews",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Reviews URL",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Reviews URL",
"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/YOUR_GOOGLE_SHEET_ID/edit#gid=0",
"cachedResultName": "Business Leads"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "YOUR_GOOGLE_SHEET_ID",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit",
"cachedResultName": "Business Leads Database"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.6
},
{
"id": "fb085dbf-205d-442c-9fa3-bb858df76d5d",
"name": "Fetch Scraped Data",
"type": "n8n-nodes-base.httpRequest",
"position": [
2160,
-120
],
"parameters": {
"url": "=https://api.brightdata.com/datasets/v3/snapshot/{{ $json.snapshot_id }}",
"options": {},
"sendQuery": true,
"sendHeaders": true,
"queryParameters": {
"parameters": [
{
"name": "format",
"value": "json"
}
]
}
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "c6856520-d927-458c-8354-cf3ee7101183",
"name": "Check Data Collection Status",
"type": "n8n-nodes-base.httpRequest",
"position": [
1340,
-100
],
"parameters": {
"url": "=https://api.brightdata.com/datasets/v3/progress/{{ $json.snapshot_id }}",
"options": {},
"sendHeaders": true
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"typeVersion": 4.2,
"alwaysOutputData": true
},
{
"id": "d3c03942-cc00-4f13-9be2-cb4abf49ed5d",
"name": "Wait for Rate Limiting",
"type": "n8n-nodes-base.wait",
"position": [
1620,
-100
],
"parameters": {
"amount": 25
},
"typeVersion": 1.1
},
{
"id": "e2989c58-cb07-4643-820a-0b99f2daacd5",
"name": "Check if Data Ready",
"type": "n8n-nodes-base.if",
"position": [
1880,
-100
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "or",
"conditions": [
{
"id": "35ed620d-b5d5-4e97-bcc5-52b283d85616",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.status }}",
"rightValue": "ready"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "7ae091e8-1cd6-4b7d-9a49-9a3b7cfc5aa8",
"name": "Data Collection Notes",
"type": "n8n-nodes-base.stickyNote",
"position": [
1120,
-220
],
"parameters": {
"color": 6,
"width": 1500,
"height": 480,
"content": "## Data Collection Monitoring\n### Monitors Bright Data scraping progress and fetches results when ready\n### Polls the API until scraping completes, then retrieves the final dataset"
},
"typeVersion": 1
},
{
"id": "9842b5c4-046c-4223-97f7-c346fa77e38d",
"name": "Duplicate Removal Notes",
"type": "n8n-nodes-base.stickyNote",
"position": [
740,
-680
],
"parameters": {
"color": 6,
"width": 1500,
"height": 380,
"content": "## Duplicate Removal Process\n### Identifies and removes duplicate business entries\n### Compares business names and phone numbers to eliminate redundant data"
},
"typeVersion": 1
}
],
"active": true,
"settings": {
"executionOrder": "v1"
},
"versionId": "da879faa-05c7-4bda-b495-18ed50989277",
"connections": {
"Fetch Scraped Data": {
"main": [
[
{
"node": "Save Business Data to Sheet",
"type": "main",
"index": 0
}
]
]
},
"Generate City List": {
"main": [
[
{
"node": "Categorize Service Type",
"type": "main",
"index": 0
}
]
]
},
"Check if Data Ready": {
"main": [
[
{
"node": "Fetch Scraped Data",
"type": "main",
"index": 0
}
],
[
{
"node": "Check Data Collection Status",
"type": "main",
"index": 0
}
]
]
},
"Delete Duplicate Row": {
"main": [
[
{
"node": "Process Duplicates in Batches",
"type": "main",
"index": 0
}
]
]
},
"Check Scraping Status": {
"main": [
[
{
"node": "Check Data Collection Status",
"type": "main",
"index": 0
}
],
[
{
"node": "Save Business Data to Sheet",
"type": "main",
"index": 0
}
]
]
},
"Separate Data by City": {
"main": [
[
{
"node": "Process Cities in Batches",
"type": "main",
"index": 0
}
]
]
},
"Wait for Rate Limiting": {
"main": [
[
{
"node": "Check if Data Ready",
"type": "main",
"index": 0
}
]
]
},
"Categorize Service Type": {
"main": [
[
{
"node": "Separate Data by City",
"type": "main",
"index": 0
}
]
]
},
"Form Submission Trigger": {
"main": [
[
{
"node": "Generate City List",
"type": "main",
"index": 0
}
]
]
},
"Find Duplicate Row Number": {
"main": [
[
{
"node": "Delete Duplicate Row",
"type": "main",
"index": 0
}
]
]
},
"Process Cities in Batches": {
"main": [
[
{
"node": "Get Existing Business Data",
"type": "main",
"index": 0
}
],
[
{
"node": "Scrape Business Data from Google Maps",
"type": "main",
"index": 0
}
]
]
},
"Claude AI Model for Cities": {
"ai_languageModel": [
[
{
"node": "Generate City List",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Get Existing Business Data": {
"main": [
[
{
"node": "Check for Duplicate Entries",
"type": "main",
"index": 0
}
]
]
},
"Check for Duplicate Entries": {
"main": [
[
{
"node": "Process Duplicates in Batches",
"type": "main",
"index": 0
}
]
]
},
"Save Business Data to Sheet": {
"main": [
[
{
"node": "Process Cities in Batches",
"type": "main",
"index": 0
}
]
]
},
"Check Data Collection Status": {
"main": [
[
{
"node": "Wait for Rate Limiting",
"type": "main",
"index": 0
}
]
]
},
"Process Duplicates in Batches": {
"main": [
[],
[
{
"node": "Find Duplicate Row Number",
"type": "main",
"index": 0
}
]
]
},
"Claude AI Model for Categories": {
"ai_languageModel": [
[
{
"node": "Categorize Service Type",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Scrape Business Data from Google Maps": {
"main": [
[
{
"node": "Check Scraping Status",
"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.
anthropicApibrightdataApigoogleSheetsOAuth2ApihttpHeaderAuth
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This template requires a self-hosted n8n instance to run.
Source: https://n8n.io/workflows/4555/ — 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.
This workflow contains community nodes that are only compatible with the self-hosted version of n8n.
Content creators, marketers, and social media managers who want to turn high-performing YouTube videos into viral X (Twitter) threads using keywords (without manual research). Perfect for anyone looki
A complete n8n automation that discovers TikTok influencers using Bright Data, evaluates their fit using Claude AI, and sends personalized outreach emails. Designed for marketing teams and brands that
Automatically scrape YouTube videos by keyword, generate SEO blog posts with Claude AI, and publish to Blogger with tracking.
Content creators, marketers, and video editors who want to automatically extract highlight clips from YouTube videos using natural language descriptions—no manual timestamp hunting required.