This workflow corresponds to n8n.io template #15344 — 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 →
{
"id": "6LQaqMZpjmf0H401",
"name": "Bulk Email Validator - Google Sheets",
"tags": [],
"nodes": [
{
"id": "f0ea44c0-4d28-4c2b-b187-6c6494d12808",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
0,
0
],
"parameters": {
"width": 480,
"height": 736,
"content": "## Bulk Email Validator - Google Sheets\n\n### How it works\n\n1. Triggers the workflow with manual, schedule, or webhook trigger.\n2. Reads email data from a Google Sheet.\n3. Parses and splits the email data into manageable batches.\n4. Verifies each batch of emails via an API call.\n5. Updates the Google Sheet with the verification results.\n\n### Setup steps\n\n- [ ] Set up Google Sheets API credentials.\n- [ ] Configure the [email verification](https://verify-email.app) API endpoint and key.\n- [ ] Set scheduled trigger time or URL for the webhook.\n\n### Customization\n\nYou can customize the verification API endpoint or adapt the script to handle different data formats."
},
"typeVersion": 1
},
{
"id": "efad1fad-25b8-4398-bb6c-ca297fceebe8",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
560,
0
],
"parameters": {
"color": 7,
"height": 720,
"content": "## Initial triggers\n\nHandles workflow initiation."
},
"typeVersion": 1
},
{
"id": "baa72527-0330-4ce1-a2c3-bd52e4c7b10d",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
1040,
224
],
"parameters": {
"color": 7,
"width": 496,
"height": 272,
"content": "## Fetch and parse data\n\nReads and prepares data from Google Sheets."
},
"typeVersion": 1
},
{
"id": "cd012071-d3cd-47f7-bdee-83b43482d4ef",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
1632,
224
],
"parameters": {
"color": 7,
"width": 352,
"height": 512,
"content": "## Batch processing control\n\nManages the processing of data batches."
},
"typeVersion": 1
},
{
"id": "a8065045-627a-484b-82d4-2d468664852a",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
2048,
464
],
"parameters": {
"color": 7,
"width": 432,
"height": 272,
"content": "## Verify and parse results\n\nHandles API call and parsing the returned data."
},
"typeVersion": 1
},
{
"id": "4f403bfa-9310-49fc-9820-9e66ebdadfc5",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
2544,
176
],
"parameters": {
"color": 7,
"height": 320,
"content": "## Update results\n\nUpdates Google Sheets with email verification results."
},
"typeVersion": 1
},
{
"id": "d16808b0-71ce-4932-8ed2-86d5a735e8fe",
"name": "Every Monday at 8am",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
624,
336
],
"parameters": {
"rule": {
"interval": [
{
"field": "weeks",
"triggerAtDay": [
1
],
"triggerAtHour": 8
}
]
}
},
"typeVersion": 1.2
},
{
"id": "5fe216aa-374e-46f8-a302-16cea58e1727",
"name": "Read Emails from Sheets",
"type": "n8n-nodes-base.googleSheets",
"position": [
1088,
336
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "name",
"value": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "1OlLamFW9r42Ag0V4cSdxLbOUcKkSosoXJI7VFUUyd14"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.5
},
{
"id": "0a1f3d74-a154-45fb-86ba-1b9ddf238b2c",
"name": "Parse Email Data for Batches",
"type": "n8n-nodes-base.code",
"position": [
1392,
336
],
"parameters": {
"jsCode": "const allItems = $input.all();\nconst emailData = [];\n\nallItems.forEach((row, index) => {\n const email = row.json?.Email?.trim?.();\n if (!email) return;\n \n const status = row.json?.Status?.trim?.();\n \n if (status && status !== 'empty') {\n return;\n }\n \n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n if (!emailRegex.test(email)) return;\n \n emailData.push({\n email: email.toLowerCase(),\n row: row.json?.row_number || 0\n });\n});\n\nif (emailData.length === 0) {\n return [];\n}\n\nconst BATCH_SIZE = 100;\nconst batches = [];\n\nfor (let i = 0; i < emailData.length; i += BATCH_SIZE) {\n const batch = emailData.slice(i, i + BATCH_SIZE);\n batches.push({\n emails: batch.map(e => e.email),\n emailData: batch\n });\n}\n\nreturn batches.map(batch => ({ json: batch }));"
},
"typeVersion": 2
},
{
"id": "bb1f8064-4656-433c-9d06-bffb663f4172",
"name": "Process in Batches of 10",
"type": "n8n-nodes-base.splitInBatches",
"position": [
1680,
336
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "2229d4c6-192f-4dab-9e05-f572bb8c71b3",
"name": "Post Email Batch to Verify API",
"type": "n8n-nodes-base.httpRequest",
"position": [
2096,
576
],
"parameters": {
"url": "https://api.verify-email.app/v1/verify/batch",
"method": "POST",
"options": {
"timeout": 60000
},
"jsonBody": "={{ JSON.stringify({ inputs: $json.emails }) }}\n",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"credentials": {
"httpBearerAuth": {
"name": "<your credential>"
},
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "972d97e4-d3d0-4459-bcc1-87875bf6baa5",
"name": "Parse Verification Results",
"type": "n8n-nodes-base.code",
"position": [
2336,
576
],
"parameters": {
"jsCode": "let apiResults = [];\n\ntry {\n const response = $input.item.json;\n apiResults = Array.isArray(response) ? response : response?.results || [];\n \n if (!Array.isArray(apiResults) || apiResults.length === 0) {\n throw new Error('API returned empty response');\n }\n} catch (e) {\n throw new Error('API Error: ' + e.message);\n}\n\nconst currentBatch = $('Parse Email Data for Batches').item.json;\nconst emailData = currentBatch.emailData || [];\nconst emailToRow = {};\n\nemailData.forEach(e => {\n emailToRow[e.email] = e;\n});\n\nconst results = apiResults.map(result => {\n const originalData = emailToRow[result.email_address] || {};\n const shouldBlock = result.block === true || result.valid === false;\n \n const reasons = [];\n if (result.valid === false) reasons.push('Invalid');\n if (result.block === true) reasons.push('Blacklisted');\n if (result.disposable === true) reasons.push('Disposable');\n \n return {\n Email: result.email_address,\n Status: shouldBlock ? 'Block' : 'Valid',\n Reason: reasons.join(' + ') || '-'\n };\n});\n\nreturn results.map(r => ({ json: r }));"
},
"typeVersion": 2
},
{
"id": "2974cdb5-6b14-4b77-8e00-3c452dd4d32c",
"name": "Update Results in Sheets",
"type": "n8n-nodes-base.googleSheets",
"position": [
2592,
336
],
"parameters": {
"columns": {
"value": {
"Email": "{{ $json.Email }}",
"Reason": "{{ $json.Reason }}",
"Status": "{{ $json.Status }}"
},
"schema": [
{
"id": "Email",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Status",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Reason",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Reason",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "row_number",
"type": "number",
"display": true,
"removed": true,
"readOnly": true,
"required": false,
"displayName": "row_number",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "autoMapInputData",
"matchingColumns": [
"Email"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "update",
"sheetName": {
"__rl": true,
"mode": "name",
"value": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "1OlLamFW9r42Ag0V4cSdxLbOUcKkSosoXJI7VFUUyd14"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.5
},
{
"id": "981aacac-6035-425a-924f-710e796a9324",
"name": "Manual Trigger",
"type": "n8n-nodes-base.manualTrigger",
"position": [
608,
128
],
"parameters": {},
"typeVersion": 1
},
{
"id": "55867ac0-eae7-4359-a427-1d82ef832c7b",
"name": "Webhook Trigger",
"type": "n8n-nodes-base.webhook",
"disabled": true,
"position": [
608,
544
],
"parameters": {
"path": "de5d1108-d424-4b89-9d85-41fae5885211",
"options": {}
},
"typeVersion": 2.1
},
{
"id": "8ab6c697-e471-4236-8148-156407893bf5",
"name": "Check Emails Exist",
"type": "n8n-nodes-base.if",
"position": [
1840,
576
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "f41aa9f7-df89-4b6c-a36f-175876fb8be1",
"operator": {
"type": "number",
"operation": "gt"
},
"leftValue": "={{ $json.emails.length }}",
"rightValue": 0
}
]
}
},
"typeVersion": 2.3
}
],
"active": false,
"settings": {
"binaryMode": "separate",
"executionOrder": "v1"
},
"versionId": "9c8d1f57-87d1-49be-908d-e05c764c716f",
"connections": {
"Webhook Trigger": {
"main": [
[
{
"node": "Read Emails from Sheets",
"type": "main",
"index": 0
}
]
]
},
"Check Emails Exist": {
"main": [
[
{
"node": "Post Email Batch to Verify API",
"type": "main",
"index": 0
}
]
]
},
"Every Monday at 8am": {
"main": [
[
{
"node": "Read Emails from Sheets",
"type": "main",
"index": 0
}
]
]
},
"Read Emails from Sheets": {
"main": [
[
{
"node": "Parse Email Data for Batches",
"type": "main",
"index": 0
}
]
]
},
"Process in Batches of 10": {
"main": [
[
{
"node": "Update Results in Sheets",
"type": "main",
"index": 0
}
],
[
{
"node": "Check Emails Exist",
"type": "main",
"index": 0
}
]
]
},
"Parse Verification Results": {
"main": [
[
{
"node": "Process in Batches of 10",
"type": "main",
"index": 0
}
]
]
},
"Parse Email Data for Batches": {
"main": [
[
{
"node": "Process in Batches of 10",
"type": "main",
"index": 0
}
]
]
},
"Post Email Batch to Verify API": {
"main": [
[
{
"node": "Parse Verification Results",
"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.
googleSheetsOAuth2ApihttpBearerAuthhttpHeaderAuth
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Automatically validate email addresses in Google Sheets using Verify Email
Source: https://n8n.io/workflows/15344/ — 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.
YOUR_ID 4. Uses gmail, googleDrive, googleSheets, httpRequest. Scheduled trigger; 53 nodes.
Looking for a way to track GitHub bounty issues automatically and get notified in real time? This GitHub Bounty Tracker workflow monitors repositories for issues labeled 💎 Bounty, logs them in Google
This workflow automatically sends a beautifully designed HTML newsletter every Sunday at 8 AM, featuring products currently on sale from your Algolia-powered e-commerce store.
This n8n template demonstrates how to build a Auto Lead Gen & Outreach System for Local Businesses specifically designed to help businesses that don’t have a website yet.
I created this workflow with care for marketing professionals and agencies who manage multiple Meta Ads (Facebook) accounts and want to track ad account balances automatically — no more logging in eve