This workflow corresponds to n8n.io template #13858 — 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": "Set Contact List",
"type": "n8n-nodes-base.set",
"position": [
-1750,
400
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "cfg-001",
"name": "contacts",
"type": "string",
"value": "[{\"first_name\":\"Jane\",\"last_name\":\"Smith\",\"domain\":\"example.com\"},{\"first_name\":\"John\",\"last_name\":\"Doe\",\"domain\":\"acme.com\"}]"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "a1000000-0000-0000-0000-000000000003",
"name": "Submit Email Finder Job",
"type": "n8n-nodes-base.httpRequest",
"position": [
-1500,
400
],
"parameters": {
"url": "https://scrapercity.com/api/v1/scrape/email-finder",
"method": "POST",
"options": {},
"jsonBody": "={\n \"contacts\": {{ $json.contacts }}\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": "cfg-002",
"name": "runId",
"type": "string",
"value": "={{ $json.runId }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "a1000000-0000-0000-0000-000000000005",
"name": "Wait Before First Poll",
"type": "n8n-nodes-base.wait",
"position": [
-1000,
400
],
"parameters": {
"amount": 30
},
"typeVersion": 1.1
},
{
"id": "a1000000-0000-0000-0000-000000000006",
"name": "Polling Loop",
"type": "n8n-nodes-base.splitInBatches",
"position": [
-750,
400
],
"parameters": {
"options": {
"reset": false
},
"batchSize": 1
},
"typeVersion": 3
},
{
"id": "a1000000-0000-0000-0000-000000000007",
"name": "Check Job Status",
"type": "n8n-nodes-base.httpRequest",
"position": [
-500,
400
],
"parameters": {
"url": "=https://scrapercity.com/api/v1/scrape/status/{{ $('Store Run ID').item.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 Job Complete?",
"type": "n8n-nodes-base.if",
"position": [
-250,
400
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "cond-001",
"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 Email Results",
"type": "n8n-nodes-base.httpRequest",
"position": [
0,
400
],
"parameters": {
"url": "=https://scrapercity.com/api/downloads/{{ $('Store Run ID').item.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 and Format Results",
"type": "n8n-nodes-base.code",
"position": [
250,
400
],
"parameters": {
"jsCode": "/**\n * Parse ScraperCity email-finder results.\n * Expects the response body to contain a JSON array of contact objects.\n * Returns one item per contact with clean, flat fields ready for Sheets.\n */\nconst raw = $input.first().json;\n\n// ScraperCity may return the data directly as an array or nested under a key\nconst rows = Array.isArray(raw) ? raw : (raw.data || raw.results || raw.contacts || []);\n\nconst output = [];\n\nfor (const row of rows) {\n output.push({\n json: {\n first_name: row.first_name || '',\n last_name: row.last_name || '',\n domain: row.domain || '',\n email: row.email || '',\n email_status: row.email_status || row.status || '',\n confidence: row.confidence !== undefined ? row.confidence : ''\n }\n });\n}\n\nif (output.length === 0) {\n return [{ json: { first_name: '', last_name: '', domain: '', email: '', email_status: 'no_results', confidence: '' } }];\n}\n\nreturn output;"
},
"typeVersion": 2
},
{
"id": "a1000000-0000-0000-0000-000000000012",
"name": "Filter Emails Found",
"type": "n8n-nodes-base.filter",
"position": [
500,
400
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"caseSensitive": false,
"typeValidation": "loose"
},
"combinator": "and",
"conditions": [
{
"id": "filt-001",
"operator": {
"type": "string",
"operation": "notEmpty",
"singleValue": true
},
"leftValue": "={{ $json.email }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "a1000000-0000-0000-0000-000000000013",
"name": "Write Results to Google Sheets",
"type": "n8n-nodes-base.googleSheets",
"position": [
750,
400
],
"parameters": {
"columns": {
"value": {
"email": "={{ $json.email }}",
"domain": "={{ $json.domain }}",
"last_name": "={{ $json.last_name }}",
"confidence": "={{ $json.confidence }}",
"first_name": "={{ $json.first_name }}",
"email_status": "={{ $json.email_status }}"
},
"schema": [
{
"id": "first_name",
"required": false,
"displayName": "first_name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "last_name",
"required": false,
"displayName": "last_name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "domain",
"required": false,
"displayName": "domain",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "email",
"required": false,
"displayName": "email",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "email_status",
"required": false,
"displayName": "email_status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "confidence",
"required": false,
"displayName": "confidence",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow"
},
"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": {
"color": 3,
"width": 500,
"height": 700,
"content": "## Find business emails from names and domains using ScraperCity\n\n**Who is this for**\n\nSales development reps, growth marketers, and recruiters who need to find verified business email addresses at scale from a contact list -- without manual lookups.\n\n**What it does**\n\nThis workflow submits a list of contacts (first name, last name, company domain) to the ScraperCity email-finder API, waits for the job to complete asynchronously, downloads the results, and writes found email addresses to Google Sheets.\n\n**How it works**\n\n1. Set Contact List -- define your contacts as JSON.\n2. Submit Email Finder Job -- POST contacts to ScraperCity.\n3. Store Run ID -- capture the job ID for polling.\n4. Polling Loop -- wait and check job status until SUCCEEDED.\n5. Download Email Results -- fetch the completed data.\n6. Parse and Format Results -- clean and structure each row.\n7. Filter Emails Found -- keep only contacts with a found email.\n8. Write Results to Google Sheets -- append clean rows to your sheet.\n\n**Setup**\n\n1. Create an HTTP Header Auth credential in n8n named `ScraperCity API Key`. Set the header name to `Authorization` and the value to `Bearer YOUR_SCRAPERCITY_KEY`.\n2. Set your Google Sheets document ID and sheet name in the Write Results node.\n3. Update the contacts in the Set Contact List node.\n4. Click Execute workflow."
},
"typeVersion": 1
},
{
"id": "a1000000-0000-0000-0000-000000000021",
"name": "Section: Contact Configuration",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2040,
-160
],
"parameters": {
"color": 5,
"width": 730,
"height": 330,
"content": "## Contact Configuration\n\nThe `Set Contact List` node is where you define the contacts to look up. Each contact needs a `first_name`, `last_name`, and `domain` (e.g. `acme.com`). The list is formatted as a JSON array string and passed directly to the ScraperCity API. Replace the sample values with your real contacts before running the workflow."
},
"typeVersion": 1
},
{
"id": "a1000000-0000-0000-0000-000000000022",
"name": "Section: Submit and Store Job",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1290,
-160
],
"parameters": {
"color": 6,
"width": 730,
"height": 330,
"content": "## Submit and Store Job\n\n`Submit Email Finder Job` sends a POST request to the ScraperCity email-finder API with your contact list and receives a `runId`. The `Store Run ID` node captures this ID and makes it available throughout the rest of the workflow via `$('Store Run ID').item.json.runId`."
},
"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\nScraperCity email-finder jobs run in the background and typically complete in 1-10 minutes depending on list size. This section waits 30 seconds on the first pass, then enters a loop: `Check Job Status` polls the status endpoint via GET, `Is Job Complete?` checks whether status equals `SUCCEEDED`. If not done, `Wait 60 Seconds Before Retry` pauses before looping back. Once complete, the TRUE branch continues to download."
},
"typeVersion": 1
},
{
"id": "a1000000-0000-0000-0000-000000000024",
"name": "Section: Download and Output",
"type": "n8n-nodes-base.stickyNote",
"position": [
210,
-160
],
"parameters": {
"color": 5,
"width": 730,
"height": 330,
"content": "## Download and Output\n\n`Download Email Results` fetches the completed results from ScraperCity using the stored `runId`. `Parse and Format Results` normalizes each contact row into flat fields. `Filter Emails Found` removes contacts where no email was returned. Finally, `Write Results to Google Sheets` appends all found emails to your sheet."
},
"typeVersion": 1
},
{
"id": "a1000000-0000-0000-0000-000000000025",
"name": "Add ScraperCity API key here",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1516,
288
],
"parameters": {
"color": 4,
"width": 280,
"height": 70,
"content": "Add your ScraperCity API key credential here"
},
"typeVersion": 1
},
{
"id": "a1000000-0000-0000-0000-000000000026",
"name": "Set your Google Sheets ID here",
"type": "n8n-nodes-base.stickyNote",
"position": [
734,
288
],
"parameters": {
"color": 4,
"width": 280,
"height": 70,
"content": "Set your Google Sheets document ID and sheet name here"
},
"typeVersion": 1
}
],
"settings": {
"executionOrder": "v1"
},
"connections": {
"Polling Loop": {
"main": [
[
{
"node": "Check Job Status",
"type": "main",
"index": 0
}
],
[]
]
},
"Store Run ID": {
"main": [
[
{
"node": "Wait Before First Poll",
"type": "main",
"index": 0
}
]
]
},
"Check Job Status": {
"main": [
[
{
"node": "Is Job Complete?",
"type": "main",
"index": 0
}
]
]
},
"Is Job Complete?": {
"main": [
[
{
"node": "Download Email Results",
"type": "main",
"index": 0
}
],
[
{
"node": "Wait 60 Seconds Before Retry",
"type": "main",
"index": 0
}
]
]
},
"Set Contact List": {
"main": [
[
{
"node": "Submit Email Finder Job",
"type": "main",
"index": 0
}
]
]
},
"Filter Emails Found": {
"main": [
[
{
"node": "Write Results to Google Sheets",
"type": "main",
"index": 0
}
]
]
},
"Download Email Results": {
"main": [
[
{
"node": "Parse and Format Results",
"type": "main",
"index": 0
}
]
]
},
"Wait Before First Poll": {
"main": [
[
{
"node": "Polling Loop",
"type": "main",
"index": 0
}
]
]
},
"Submit Email Finder Job": {
"main": [
[
{
"node": "Store Run ID",
"type": "main",
"index": 0
}
]
]
},
"Parse and Format Results": {
"main": [
[
{
"node": "Filter Emails Found",
"type": "main",
"index": 0
}
]
]
},
"Wait 60 Seconds Before Retry": {
"main": [
[
{
"node": "Polling Loop",
"type": "main",
"index": 0
}
]
]
},
"When clicking 'Execute workflow'": {
"main": [
[
{
"node": "Set Contact List",
"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
Sales development reps, growth marketers, and recruiters who need to find verified business email addresses at scale from a list of contacts -- without manual lookups or guesswork. A Set node holds your list of contacts (first name, last name, and company domain). An HTTP…
Source: https://n8n.io/workflows/13858/ — 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 template is ideal for solo store owners, eCommerce marketers, automation beginners, or anyone using Shopify and Gmail who wants to recover lost revenue without coding.
PCN. Uses googleSheets, httpRequest, @n-octo-n/n8n-nodes-json-database, itemLists. Event-driven trigger; 60 nodes.
The workflow automates the process of gathering extensive keyword data for a "Main Keyword." It starts by reading initial parameters from a Google Sheets template, creates a new dedicated Google Sheet
🔥 March Sale – n8n Community Members Get ideoGener8r for Just $27! (Reg. $47) Use Coupon Code: (Valid until 3/31/2025 for n8n community members)
📄 Documentation: Notion Guide