This workflow corresponds to n8n.io template #13929 — 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 →
{
"meta": {
"templateCredsSetupCompleted": false
},
"nodes": [
{
"id": "a1000000-0000-0000-0000-000000000001",
"name": "When clicking 'Execute workflow'",
"type": "n8n-nodes-base.manualTrigger",
"position": [
-2000,
400
],
"parameters": {},
"typeVersion": 1
},
{
"id": "a1000000-0000-0000-0000-000000000002",
"name": "Configure Search Inputs",
"type": "n8n-nodes-base.set",
"position": [
-1750,
400
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "b1000001",
"name": "searchName",
"type": "string",
"value": "Jane Doe"
},
{
"id": "b1000002",
"name": "searchPhone",
"type": "string",
"value": ""
},
{
"id": "b1000003",
"name": "searchEmail",
"type": "string",
"value": ""
},
{
"id": "b1000004",
"name": "maxResults",
"type": "number",
"value": 3
}
]
}
},
"typeVersion": 3.4
},
{
"id": "a1000000-0000-0000-0000-000000000003",
"name": "Start People Finder Scrape",
"type": "n8n-nodes-base.httpRequest",
"position": [
-1500,
400
],
"parameters": {
"url": "https://app.scrapercity.com/api/v1/scrape/people-finder",
"method": "POST",
"options": {},
"jsonBody": "={\n \"name\": {{ $json.searchName ? '[\"' + $json.searchName + '\"]' : '[]' }},\n \"email\": {{ $json.searchEmail ? '[\"' + $json.searchEmail + '\"]' : '[]' }},\n \"phone_number\": {{ $json.searchPhone ? '[\"' + $json.searchPhone + '\"]' : '[]' }},\n \"street_citystatezip\": [],\n \"max_results\": {{ $json.maxResults }}\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth"
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "a1000000-0000-0000-0000-000000000004",
"name": "Store Run ID",
"type": "n8n-nodes-base.set",
"position": [
-1250,
400
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "b2000001",
"name": "runId",
"type": "string",
"value": "={{ $json.runId }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "a1000000-0000-0000-0000-000000000005",
"name": "Wait Before First Status Check",
"type": "n8n-nodes-base.wait",
"position": [
-1000,
400
],
"parameters": {
"amount": 30
},
"typeVersion": 1.1
},
{
"id": "a1000000-0000-0000-0000-000000000006",
"name": "Poll Loop",
"type": "n8n-nodes-base.splitInBatches",
"position": [
-750,
400
],
"parameters": {
"options": {
"maxIterations": 30
}
},
"typeVersion": 3
},
{
"id": "a1000000-0000-0000-0000-000000000007",
"name": "Check Scrape Status",
"type": "n8n-nodes-base.httpRequest",
"position": [
-500,
400
],
"parameters": {
"url": "=https://app.scrapercity.com/api/v1/scrape/status/{{ $json.runId }}",
"method": "GET",
"options": {},
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth"
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "a1000000-0000-0000-0000-000000000008",
"name": "Is Scrape Complete?",
"type": "n8n-nodes-base.if",
"position": [
-250,
400
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "c1000001",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.status }}",
"rightValue": "SUCCEEDED"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "a1000000-0000-0000-0000-000000000009",
"name": "Wait 60 Seconds Before Retry",
"type": "n8n-nodes-base.wait",
"position": [
-250,
592
],
"parameters": {
"amount": 60
},
"typeVersion": 1.1
},
{
"id": "a1000000-0000-0000-0000-000000000010",
"name": "Download Results",
"type": "n8n-nodes-base.httpRequest",
"position": [
0,
400
],
"parameters": {
"url": "=https://app.scrapercity.com/api/downloads/{{ $json.runId }}",
"method": "GET",
"options": {},
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth"
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "a1000000-0000-0000-0000-000000000011",
"name": "Parse CSV Results",
"type": "n8n-nodes-base.code",
"position": [
250,
400
],
"parameters": {
"jsCode": "// Parse CSV text returned from ScraperCity download endpoint\n// Handles quoted fields and normalises rows into key/value objects\n\nconst raw = items[0].json.data ?? items[0].json.body ?? items[0].json;\nconst csvText = typeof raw === 'string' ? raw : JSON.stringify(raw);\n\nif (!csvText || csvText.trim() === '') {\n return [{ json: { error: 'No CSV data returned' } }];\n}\n\nconst lines = csvText.trim().split('\\n');\nif (lines.length < 2) {\n return [{ json: { error: 'CSV has no data rows' } }];\n}\n\nfunction parseCsvLine(line) {\n const result = [];\n let current = '';\n let inQuotes = false;\n for (let i = 0; i < line.length; i++) {\n const ch = line[i];\n if (ch === '\"') {\n if (inQuotes && line[i + 1] === '\"') {\n current += '\"';\n i++;\n } else {\n inQuotes = !inQuotes;\n }\n } else if (ch === ',' && !inQuotes) {\n result.push(current.trim());\n current = '';\n } else {\n current += ch;\n }\n }\n result.push(current.trim());\n return result;\n}\n\nconst headers = parseCsvLine(lines[0]);\nconst output = [];\n\nfor (let i = 1; i < lines.length; i++) {\n if (!lines[i].trim()) continue;\n const values = parseCsvLine(lines[i]);\n const row = {};\n headers.forEach((h, idx) => {\n row[h] = values[idx] ?? '';\n });\n output.push({ json: row });\n}\n\nreturn output;"
},
"typeVersion": 2
},
{
"id": "a1000000-0000-0000-0000-000000000012",
"name": "Remove Duplicate Contacts",
"type": "n8n-nodes-base.removeDuplicates",
"position": [
500,
400
],
"parameters": {
"options": {},
"fieldsToCompare": {
"fields": [
{
"fieldName": "full_name"
},
{
"fieldName": "address"
}
]
}
},
"typeVersion": 2
},
{
"id": "a1000000-0000-0000-0000-000000000013",
"name": "Save Results to Google Sheets",
"type": "n8n-nodes-base.googleSheets",
"position": [
750,
400
],
"parameters": {
"columns": {
"value": {},
"mappingMode": "autoMapInputData"
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "id",
"value": "="
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "="
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.6
},
{
"id": "a1000000-0000-0000-0000-000000000020",
"name": "Overview",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2600,
100
],
"parameters": {
"width": 450,
"height": 580,
"content": "## How it works\n1. Enter a name, phone, or email in the Configure Search Inputs node.\n2. The workflow submits a people-finder job to the ScraperCity API.\n3. It polls for completion every 60 seconds (jobs take 2-20 min).\n4. Results are downloaded, parsed from CSV, deduped, and saved to Google Sheets.\n\n## Setup steps\n1. Create a Header Auth credential named **ScraperCity API Key** -- set header to `Authorization`, value to `Bearer YOUR_KEY`.\n2. Connect a Google Sheets OAuth2 credential.\n3. Edit **Configure Search Inputs** with your target person.\n4. Set your Google Sheet ID in **Save Results to Google Sheets**.\n5. Click Execute workflow."
},
"typeVersion": 1
},
{
"id": "a1000000-0000-0000-0000-000000000021",
"name": "Section - Configuration",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2040,
-160
],
"parameters": {
"color": 7,
"width": 730,
"height": 330,
"content": "## Configuration\nSet your search target in **Configure Search Inputs** -- name, phone, or email. Add your ScraperCity API key credential to the HTTP nodes."
},
"typeVersion": 1
},
{
"id": "a1000000-0000-0000-0000-000000000022",
"name": "Section - Submit and Store",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1290,
-160
],
"parameters": {
"color": 7,
"width": 730,
"height": 330,
"content": "## Submit Scrape Job\n**Start People Finder Scrape** POSTs to the API and returns a job ID. **Store Run ID** saves it for polling and download references."
},
"typeVersion": 1
},
{
"id": "a1000000-0000-0000-0000-000000000023",
"name": "Section - Async Polling Loop",
"type": "n8n-nodes-base.stickyNote",
"position": [
-540,
-160
],
"parameters": {
"color": 7,
"width": 730,
"height": 530,
"content": "## Async Polling Loop\n**Check Scrape Status** queries the job. **Is Scrape Complete?** routes to download on success. Otherwise **Wait 60 Seconds Before Retry** loops back through the poll."
},
"typeVersion": 1
},
{
"id": "a1000000-0000-0000-0000-000000000024",
"name": "Section - Parse and Save",
"type": "n8n-nodes-base.stickyNote",
"position": [
210,
-160
],
"parameters": {
"color": 7,
"width": 730,
"height": 330,
"content": "## Parse and Save Results\n**Download Results** fetches the CSV. **Parse CSV Results** converts to JSON records. **Remove Duplicate Contacts** dedupes. **Save Results to Google Sheets** writes each row."
},
"typeVersion": 1
}
],
"settings": {
"executionOrder": "v1"
},
"connections": {
"Poll Loop": {
"main": [
[
{
"node": "Check Scrape Status",
"type": "main",
"index": 0
}
],
[]
]
},
"Store Run ID": {
"main": [
[
{
"node": "Wait Before First Status Check",
"type": "main",
"index": 0
}
]
]
},
"Download Results": {
"main": [
[
{
"node": "Parse CSV Results",
"type": "main",
"index": 0
}
]
]
},
"Parse CSV Results": {
"main": [
[
{
"node": "Remove Duplicate Contacts",
"type": "main",
"index": 0
}
]
]
},
"Check Scrape Status": {
"main": [
[
{
"node": "Is Scrape Complete?",
"type": "main",
"index": 0
}
]
]
},
"Is Scrape Complete?": {
"main": [
[
{
"node": "Download Results",
"type": "main",
"index": 0
}
],
[
{
"node": "Wait 60 Seconds Before Retry",
"type": "main",
"index": 0
}
]
]
},
"Configure Search Inputs": {
"main": [
[
{
"node": "Start People Finder Scrape",
"type": "main",
"index": 0
}
]
]
},
"Remove Duplicate Contacts": {
"main": [
[
{
"node": "Save Results to Google Sheets",
"type": "main",
"index": 0
}
]
]
},
"Start People Finder Scrape": {
"main": [
[
{
"node": "Store Run ID",
"type": "main",
"index": 0
}
]
]
},
"Wait 60 Seconds Before Retry": {
"main": [
[
{
"node": "Poll Loop",
"type": "main",
"index": 0
}
]
]
},
"Wait Before First Status Check": {
"main": [
[
{
"node": "Poll Loop",
"type": "main",
"index": 0
}
]
]
},
"When clicking 'Execute workflow'": {
"main": [
[
{
"node": "Configure Search Inputs",
"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.
googleSheetsOAuth2ApihttpHeaderAuth
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This template is for investigators, real estate professionals, recruiters, and sales teams who need to skip trace individuals -- finding current addresses, phone numbers, and emails from a name, phone, or email address. It is ideal for anyone who needs to enrich a list of…
Source: https://n8n.io/workflows/13929/ — 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.
Splitout Code. Uses manualTrigger, httpRequest, stickyNote, splitOut. Event-driven trigger; 46 nodes.
Automate CSV imports into HubSpot without the mess. Powered by n8n. Supercharged by Pollup AI.
AICARE Email Blast System. Uses googleDrive, httpRequest, googleSheets, gmail. Event-driven trigger; 39 nodes.
Get notified if the actual data release is positive or negative for the relevant currency. Use the Telegram chat message about the news release as a trigger to open a trading position in MetaTrader 4.
Automatically processes new orders added to Google Sheets. Small orders are approved instantly; large orders trigger an HTML email with one-click Approve / Reject links — each handled by an independen