Scraperapi email verification with BillionVerify
ScraperAPI is a proxy-based web scraping platform that handles IP rotation, CAPTCHAs, and JavaScript rendering so developers can extract data reliably at scale. When email addresses are part of that extracted data, pairing ScraperAPI with BillionVerify ensures only deliverable contacts flow downstream.
Why verify before the send
Scraped email addresses come from pages that may not have been updated in months or years. Stale, role-based, and catch-all addresses inflate your list while driving up bounce rates. BillionVerify validates each address in real time so your sending reputation stays strong and your outreach reaches real inboxes.
Ready-to-use n8n workflow
Import this workflow into n8n β it verifies every address with BillionVerify before Scraperapi sends, so only deliverable contacts are emailed. Install the BillionVerify community node first, then add your API key. Adapted from this n8n template
{
"name": "Send daily price-drop digest emails for Amazon, Walmart and Google via ScraperAPI + BillionVerify",
"nodes": [
{
"id": "d18bd12f-e041-449a-8bca-a8906a2e71cd",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1696,
112
],
"parameters": {
"width": 480,
"height": 896,
"content": "## Email daily price-drop digests from Amazon, Walmart and Google via ScraperAPI\n\n### How it works\n\n1. Triggers the workflow every morning at 8 am or manually during setup.\n2. Initializes or reads product and price tables.\n3. Loops through each product to fetch current product data from various sources.\n4. Compares fetched data and updates product prices.\n5. Checks for price drops, compiles a digest, and sends an email.\n6. Provides an option to send Gmail digest emails.\n\n### Setup steps\n\n- [ ] Set up and verify scheduler trigger timing\n- [ ] Configure database credentials\n- [ ] Set API keys for Amazon, Walmart, Google Shopping\n- [ ] Link an email service provider or SMTP\n- [ ] Ensure that the Gmail module is authenticated\n\n### Customization\n\nYou can customize the schedule to a different time and modify data sources or email templates."
},
"typeVersion": 1
},
{
"id": "a4648c97-6bbd-4dec-a84b-808032d6e46d",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1136,
608
],
"parameters": {
"color": 7,
"width": 416,
"height": 304,
"content": "## Morning trigger setup\n\nTriggers the workflow every morning at 8 am."
},
"typeVersion": 1
},
{
"id": "fe082e45-1237-44e0-91e8-85d220940959",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
0,
0
],
"parameters": {
"color": 7,
"width": 1088,
"height": 272,
"content": "## Manual setup and table initialization\n\nManual trigger to set up product and price history tables."
},
"typeVersion": 1
},
{
"id": "f170729a-c66e-42cf-bb59-ced6db967535",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-688,
608
],
"parameters": {
"color": 7,
"width": 1536,
"height": 320,
"content": "## Fetch and iterate products\n\nFetches all products and prepares for individual product processing."
},
"typeVersion": 1
},
{
"id": "5a425a67-d3db-40d2-9b26-60e9efb40a30",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-464,
304
],
"parameters": {
"color": 7,
"width": 864,
"height": 272,
"content": "## Parse and fetch product data\n\nParses product URLs and fetches data from Amazon, Walmart, and Google Shopping APIs."
},
"typeVersion": 1
},
{
"id": "51e1d161-93c1-488b-b642-7309a7a9f949",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
432,
304
],
"parameters": {
"color": 7,
"width": 640,
"height": 272,
"content": "## Process and compare product data\n\nCompares fetched product data and updates the database with new prices."
},
"typeVersion": 1
},
{
"id": "bf40277a-85a9-4921-8e8d-c13f0f02d0b3",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
448,
1072
],
"parameters": {
"color": 7,
"width": 640,
"height": 272,
"content": "## Price drop analysis and email\n\nFetches today's price drops, creates a digest, and sends out an email notification."
},
"typeVersion": 1
},
{
"id": "b8bdcf9d-8b4f-47d0-9de6-5a2c780793ad",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
896,
1376
],
"parameters": {
"color": 7,
"height": 304,
"content": "## Standalone Gmail email\n\nHandles sending the digest email via Gmail independently."
},
"typeVersion": 1
},
{
"id": "daily-trigger",
"name": "Morning Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-1088,
720
],
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 8 * * *"
}
]
}
},
"typeVersion": 1.2
},
{
"id": "setup-trigger",
"name": "Manual Trigger Setup",
"type": "n8n-nodes-base.manualTrigger",
"position": [
48,
112
],
"parameters": {},
"typeVersion": 1
},
{
"id": "create-products-table",
"name": "Initialize Products Table",
"type": "n8n-nodes-base.dataTable",
"position": [
240,
112
],
"parameters": {
"columns": {
"column": [
{
"name": "name",
"type": "string"
},
{
"name": "amazon_url",
"type": "string"
},
{
"name": "walmart_url",
"type": "string"
},
{
"name": "track_google_shopping",
"type": "boolean"
},
{
"name": "target_price",
"type": "number"
},
{
"name": "last_amazon_price",
"type": "number"
},
{
"name": "last_walmart_price",
"type": "number"
},
{
"name": "last_google_min_price",
"type": "number"
}
]
},
"options": {
"createIfNotExists": true
},
"resource": "table",
"operation": "create",
"tableName": "products"
},
"typeVersion": 1.1
},
{
"id": "create-history-table",
"name": "Initialize History Table",
"type": "n8n-nodes-base.dataTable",
"position": [
416,
112
],
"parameters": {
"columns": {
"column": [
{
"name": "timestamp",
"type": "string"
},
{
"name": "product_name",
"type": "string"
},
{
"name": "platform",
"type": "string"
},
{
"name": "current_price",
"type": "number"
},
{
"name": "previous_price",
"type": "number"
},
{
"name": "dropped",
"type": "boolean"
},
{
"name": "pct_drop",
"type": "number"
},
{
"name": "error",
"type": "string"
}
]
},
"options": {
"createIfNotExists": true
},
"resource": "table",
"operation": "create",
"tableName": "price_history"
},
"typeVersion": 1.1
},
{
"id": "read-existing-products",
"name": "Read Existing Products",
"type": "n8n-nodes-base.dataTable",
"position": [
592,
112
],
"parameters": {
"filters": {
"conditions": []
},
"resource": "row",
"matchType": "anyCondition",
"operation": "get",
"returnAll": true,
"dataTableId": {
"__rl": true,
"mode": "name",
"value": "products"
}
},
"typeVersion": 1.1,
"alwaysOutputData": true
},
{
"id": "seed-sample-products",
"name": "Generate Sample Products",
"type": "n8n-nodes-base.code",
"position": [
768,
112
],
"parameters": {
"jsCode": "const existingNames = new Set(\n $input.all()\n .map(i => (i.json && i.json.name ? String(i.json.name).trim().toLowerCase() : ''))\n .filter(Boolean)\n);\n\nconst samples = [\n {\n name: 'Samsung Galaxy Watch Ultra',\n amazon_url: 'https://www.amazon.com/dp/B0F7Q4L81N?th=1',\n walmart_url: 'https://www.walmart.com/ip/Samsung-Galaxy-Watch-Ultra-47mm-2025-Edition-Bluetooth-Wi-Fi-4GLTE-Smart-Fitness-Watch-International-Version-Titanium-Blue/17452806183',\n track_google_shopping: true,\n target_price: null,\n last_amazon_price: null,\n last_walmart_price: null,\n last_google_min_price: null,\n },\n {\n name: 'Apple Watch Series 11',\n amazon_url: 'https://www.amazon.com/dp/B0FQFL8PZ5?th=1',\n walmart_url: 'https://www.walmart.com/ip/Apple-Watch-Series-11-GPS-Cellular-42mm-Gold-Titanium-Case-with-Gold-Milanese-Loop/17828855921',\n track_google_shopping: true,\n target_price: null,\n last_amazon_price: null,\n last_walmart_price: null,\n last_google_min_price: null,\n },\n {\n name: 'XIAOMI Redmi Watch 5',\n amazon_url: 'https://www.amazon.com/dp/B0DFZPR9Z4?th=1',\n walmart_url: 'https://www.walmart.com/ip/Redmi-Watch-5-Active-Midnight-Black-18-Day-Battery-Life-2-Inch-Display-5ATM-Waterproof-Bluetooth-Calling-Alexa-Built-In/15893513091',\n track_google_shopping: true,\n target_price: null,\n last_amazon_price: null,\n last_walmart_price: null,\n last_google_min_price: null,\n },\n];\n\nreturn samples\n .filter(s => !existingNames.has(s.name.toLowerCase()))\n .map(s => ({ json: s }));\n",
"language": "javaScript"
},
"typeVersion": 2
},
{
"id": "insert-sample-products",
"name": "Add Samples to Products Table",
"type": "n8n-nodes-base.dataTable",
"position": [
944,
112
],
"parameters": {
"columns": {
"value": {
"name": "={{ $json.name }}",
"amazon_url": "={{ $json.amazon_url }}",
"walmart_url": "={{ $json.walmart_url }}",
"target_price": "={{ $json.target_price }}",
"last_amazon_price": "={{ $json.last_amazon_price }}",
"last_walmart_price": "={{ $json.last_walmart_price }}",
"last_google_min_price": "={{ $json.last_google_min_price }}",
"track_google_shopping": "={{ $json.track_google_shopping }}"
},
"mappingMode": "defineBelow"
},
"options": {},
"resource": "row",
"operation": "insert",
"dataTableId": {
"__rl": true,
"mode": "name",
"value": "products"
}
},
"typeVersion": 1.1
},
{
"id": "read-products",
"name": "Fetch Products Data",
"type": "n8n-nodes-base.dataTable",
"position": [
-864,
720
],
"parameters": {
"filters": {
"conditions": []
},
"resource": "row",
"matchType": "anyCondition",
"operation": "get",
"returnAll": true,
"dataTableId": {
"__rl": true,
"mode": "name",
"value": "products"
}
},
"typeVersion": 1.1
},
{
"id": "per-product-loop",
"name": "Iterate Products Batch",
"type": "n8n-nodes-base.splitInBatches",
"position": [
-544,
720
],
"parameters": {
"options": {},
"batchSize": 1
},
"typeVersion": 3
},
{
"id": "parse-urls",
"name": "Extract Product URLs",
"type": "n8n-nodes-base.code",
"position": [
-416,
416
],
"parameters": {
"jsCode": "const row = $input.first().json;\n\nconst stripQs = (u) => (u || '').split(/[?#]/)[0];\nconst amazonUrl = stripQs(row.amazon_url);\nconst walmartUrl = stripQs(row.walmart_url);\n\nconst asinMatch = amazonUrl.match(/\\/(?:dp|gp\\/product)\\/([A-Z0-9]{10})/i);\nconst walmartMatch = walmartUrl.match(/walmart\\.com\\/ip\\/(?:[^/]+\\/)?(\\d+)/i);\n\nconst trackGoogle = row.track_google_shopping === true || row.track_google_shopping === 'true' || row.track_google_shopping === 1;\n\nreturn [{\n json: {\n id: row.id,\n name: row.name || '',\n amazon_asin: asinMatch ? asinMatch[1].toUpperCase() : '',\n walmart_product_id: walmartMatch ? walmartMatch[1] : '',\n google_query: trackGoogle ? (row.name || '') : '',\n target_price: row.target_price ?? null,\n last_amazon_price: row.last_amazon_price ?? null,\n last_walmart_price: row.last_walmart_price ?? null,\n last_google_min_price: row.last_google_min_price ?? null,\n },\n}];\n",
"language": "javaScript"
},
"typeVersion": 2
},
{
"id": "amazon-sde",
"name": "Scrape Amazon Data",
"type": "n8n-nodes-scraperapi-official.scraperApi",
"maxTries": 2,
"position": [
-192,
416
],
"parameters": {
"sdeAsin": "={{ $('Extract Product URLs').item.json.amazon_asin }}",
"resource": "sde",
"operation": "amazonProduct",
"sdePlatform": "amazon",
"sdeAmazonOptions": {}
},
"retryOnFail": true,
"typeVersion": 1,
"continueOnFail": true,
"waitBetweenTries": 2000
},
{
"id": "walmart-sde",
"name": "Scrape Walmart Data",
"type": "n8n-nodes-scraperapi-official.scraperApi",
"maxTries": 2,
"position": [
32,
416
],
"parameters": {
"resource": "sde",
"operation": "walmartProduct",
"sdePlatform": "walmart",
"sdeProductId": "={{ $('Extract Product URLs').item.json.walmart_product_id }}",
"sdeWalmartOptions": {}
},
"retryOnFail": true,
"typeVersion": 1,
"continueOnFail": true,
"waitBetweenTries": 2000
},
{
"id": "google-shopping-sde",
"name": "Scrape Google Shopping Data",
"type": "n8n-nodes-scraperapi-official.scraperApi",
"maxTries": 2,
"position": [
256,
416
],
"parameters": {
"resource": "sde",
"sdeQuery": "={{ $('Extract Product URLs').item.json.google_query }}",
"operation": "googleShopping",
"sdePlatform": "google",
"sdeGoogleOptions": {}
},
"retryOnFail": true,
"typeVersion": 1,
"continueOnFail": true,
"waitBetweenTries": 2000
},
{
"id": "compare-results",
"name": "Analyze Product Data",
"type": "n8n-nodes-base.code",
"position": [
480,
416
],
"parameters": {
"jsCode": "const parsed = $('Extract Product URLs').item.json;\n\nconst numOrNull = (v) => {\n if (v === null || v === undefined || v === '') return null;\n const s = typeof v === 'string' ? v.replace(/[^0-9.]/g, '') : v;\n const n = parseFloat(s);\n return Number.isFinite(n) ? n : null;\n};\n\nconst getBody = (item) => (item && item.response && item.response.body) || (item && item.body) || item;\n\nconst readPrice = (nodeName, paths) => {\n try {\n const item = $(nodeName).item.json;\n if (!item) return { price: null, error: null };\n if (item.error) {\n const msg = (item.error && (item.error.message || item.error.description)) || String(item.error);\n return { price: null, error: msg };\n }\n const body = getBody(item);\n for (const path of paths) {\n const parts = path.split('.');\n let cur = body;\n for (const p of parts) cur = cur == null ? cur : cur[p];\n const n = numOrNull(cur);\n if (n !== null) return { price: n, error: null };\n }\n return { price: null, error: null };\n } catch (e) {\n return { price: null, error: e.message };\n }\n};\n\nconst amazon = readPrice('Amazon Product', ['pricing', 'list_price', 'price']);\nconst walmart = readPrice('Walmart Product', ['price', 'current_price.price', 'pricing']);\n\nlet google = { price: null, error: null };\ntry {\n const g = $('Scrape Google Shopping Data').item.json;\n if (g && g.error) {\n google.error = (g.error && (g.error.message || g.error.description)) || String(g.error);\n } else if (g) {\n const body = getBody(g);\n const items = body.shopping_results || body.results || [];\n const prices = items\n .map(it => numOrNull(it && (it.extracted_price !== undefined ? it.extracted_price : it.price)))\n .filter(p => p !== null);\n google.price = prices.length ? Math.min(...prices) : null;\n }\n} catch (e) {\n google.error = e.message;\n}\n\nconst ts = new Date().toISOString();\nconst target = parsed.target_price;\n\nconst evaluate = (platform, current, previous, error) => {\n const dropped = current !== null && previous !== null && previous > 0 && current < previous;\n const pct_drop = dropped ? Number((((previous - current) / previous) * 100).toFixed(2)) : 0;\n const crossed_target = Number.isFinite(target) && Number.isFinite(current) && Number.isFinite(previous) && previous > target && current <= target;\n return {\n timestamp: ts,\n product_name: parsed.name,\n platform,\n current_price: current,\n previous_price: previous,\n dropped: dropped || crossed_target,\n pct_drop,\n error: error || '',\n };\n};\n\nconst results = [];\nif (parsed.amazon_asin) results.push(evaluate('amazon', amazon.price, parsed.last_amazon_price, amazon.error));\nif (parsed.walmart_product_id) results.push(evaluate('walmart', walmart.price, parsed.last_walmart_price, walmart.error));\nif (parsed.google_query) results.push(evaluate('google_shopping', google.price, parsed.last_google_min_price, google.error));\n\nconst update = {\n id: parsed.id,\n last_amazon_price: amazon.price !== null ? amazon.price : (parsed.last_amazon_price != null ? parsed.last_amazon_price : null),\n last_walmart_price: walmart.price !== null ? walmart.price : (parsed.last_walmart_price != null ? parsed.last_walmart_price : null),\n last_google_min_price: google.price !== null ? google.price : (parsed.last_google_min_price != null ? parsed.last_google_min_price : null),\n};\n\nreturn [{ json: { results, update } }];\n",
"language": "javaScript"
},
"typeVersion": 2
},
{
"id": "split-history",
"name": "Divide History Results",
"type": "n8n-nodes-base.splitOut",
"position": [
704,
416
],
"parameters": {
"include": "noOtherFields",
"options": {},
"fieldToSplitOut": "results"
},
"typeVersion": 1
},
{
"id": "append-history",
"name": "Add to Price History",
"type": "n8n-nodes-base.dataTable",
"position": [
928,
416
],
"parameters": {
"columns": {
"value": {
"error": "={{ $json.error }}",
"dropped": "={{ $json.dropped }}",
"pct_drop": "={{ $json.pct_drop }}",
"platform": "={{ $json.platform }}",
"timestamp": "={{ $json.timestamp }}",
"product_name": "={{ $json.product_name }}",
"current_price": "={{ $json.current_price }}",
"previous_price": "={{ $json.previous_price }}"
},
"mappingMode": "defineBelow"
},
"options": {},
"resource": "row",
"operation": "insert",
"dataTableId": {
"__rl": true,
"mode": "name",
"value": "price_history"
}
},
"typeVersion": 1.1
},
{
"id": "update-products",
"name": "Refresh Product Prices",
"type": "n8n-nodes-base.dataTable",
"position": [
608,
720
],
"parameters": {
"columns": {
"value": {
"last_amazon_price": "={{ $json.update.last_amazon_price }}",
"last_walmart_price": "={{ $json.update.last_walmart_price }}",
"last_google_min_price": "={{ $json.update.last_google_min_price }}"
},
"mappingMode": "defineBelow"
},
"filters": {
"conditions": [
{
"keyName": "id",
"keyValue": "={{ $json.update.id }}",
"condition": "eq"
}
]
},
"options": {},
"resource": "row",
"matchType": "allConditions",
"operation": "update",
"dataTableId": {
"__rl": true,
"mode": "name",
"value": "products"
}
},
"typeVersion": 1.1
},
{
"id": "read-todays-drops",
"name": "Retrieve Today's Price Drops",
"type": "n8n-nodes-base.dataTable",
"position": [
496,
1184
],
"parameters": {
"filters": {
"conditions": [
{
"keyName": "dropped",
"keyValue": "true",
"condition": "eq"
},
{
"keyName": "timestamp",
"keyValue": "={{ $now.startOf('day').toISO() }}",
"condition": "gte"
}
]
},
"resource": "row",
"matchType": "allConditions",
"operation": "get",
"returnAll": true,
"dataTableId": {
"__rl": true,
"mode": "name",
"value": "price_history"
}
},
"executeOnce": true,
"typeVersion": 1.1
},
{
"id": "build-digest",
"name": "Compile Price Drop Digest",
"type": "n8n-nodes-base.code",
"position": [
720,
1184
],
"parameters": {
"jsCode": "const drops = $input.all().map(i => i.json);\nif (drops.length === 0) return [];\n\ndrops.sort((a, b) => (b.pct_drop || 0) - (a.pct_drop || 0));\n\nconst esc = (s) => String(s == null ? '' : s).replace(/[&<>\"']/g, c => ({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));\nconst fmt = (n) => n == null || n === '' ? 'β' : '$' + Number(n).toFixed(2);\n\nconst rowsHtml = drops.map(d => `<tr>\n <td>${esc(d.product_name)}</td>\n <td>${esc(d.platform)}</td>\n <td style=\"text-align:right;\">${fmt(d.previous_price)}</td>\n <td style=\"text-align:right;color:#0a7d27;font-weight:600;\">${fmt(d.current_price)}</td>\n <td style=\"text-align:right;\">${d.pct_drop ? d.pct_drop + '%' : 'β'}</td>\n</tr>`).join('');\n\nconst subject = `Price drop alert β ${drops.length} product${drops.length === 1 ? '' : 's'} dropped today`;\nconst html = `<div style=\"font-family:-apple-system,Segoe UI,sans-serif;max-width:680px;\">\n <h2 style=\"margin:0 0 12px;\">${subject}</h2>\n <p style=\"color:#555;margin:0 0 16px;\">Fresh prices from Amazon, Walmart, and Google Shopping β collected on autopilot by ScraperAPI.</p>\n <table cellpadding=\"8\" cellspacing=\"0\" style=\"border-collapse:collapse;width:100%;font-size:14px;\">\n <thead><tr style=\"background:#f4f4f6;text-align:left;\">\n <th>Product</th><th>Marketplace</th><th style=\"text-align:right;\">Was</th><th style=\"text-align:right;\">Now</th><th style=\"text-align:right;\">Drop</th>\n </tr></thead>\n <tbody>${rowsHtml}</tbody>\n </table>\n</div>`;\n\nreturn [{ json: { count: drops.length, subject, html } }];\n",
"language": "javaScript"
},
"typeVersion": 2
},
{
"id": "send-email",
"name": "Email Price Drop Notice",
"type": "n8n-nodes-base.emailSend",
"position": [
944,
1184
],
"parameters": {
"html": "={{ $json.html }}",
"options": {},
"subject": "={{ $json.subject }}",
"toEmail": "",
"fromEmail": "",
"emailFormat": "html"
},
"typeVersion": 2.1
},
{
"id": "send-email-gmail",
"name": "Send Digest via Gmail",
"type": "n8n-nodes-base.gmail",
"position": [
944,
1504
],
"parameters": {
"sendTo": "",
"message": "={{ $json.html }}",
"options": {},
"subject": "={{ $json.subject }}",
"emailType": "html"
},
"typeVersion": 2.1
},
{
"parameters": {
"operation": "verify",
"email": "={{ $json.email || $json.Email }}",
"additionalOptions": {}
},
"type": "n8n-nodes-billionverify.billionVerify",
"typeVersion": 1,
"position": [
584,
1184
],
"name": "Verify Email (BillionVerify)",
"credentials": {
"billionVerifyApi": {
"id": "",
"name": "BillionVerify account"
}
}
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "loose"
},
"combinator": "and",
"conditions": [
{
"id": "is-deliverable",
"leftValue": "={{ $json.is_deliverable }}",
"rightValue": "",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
}
}
]
}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
764,
1184
],
"name": "IF deliverable"
}
],
"connections": {
"Scrape Amazon Data": {
"main": [
[
{
"node": "Scrape Walmart Data",
"type": "main",
"index": 0
}
]
]
},
"Fetch Products Data": {
"main": [
[
{
"node": "Iterate Products Batch",
"type": "main",
"index": 0
}
]
]
},
"Scrape Walmart Data": {
"main": [
[
{
"node": "Scrape Google Shopping Data",
"type": "main",
"index": 0
}
]
]
},
"Analyze Product Data": {
"main": [
[
{
"node": "Divide History Results",
"type": "main",
"index": 0
},
{
"node": "Refresh Product Prices",
"type": "main",
"index": 0
}
]
]
},
"Extract Product URLs": {
"main": [
[
{
"node": "Scrape Amazon Data",
"type": "main",
"index": 0
}
]
]
},
"Manual Trigger Setup": {
"main": [
[
{
"node": "Initialize Products Table",
"type": "main",
"index": 0
}
]
]
},
"Divide History Results": {
"main": [
[
{
"node": "Add to Price History",
"type": "main",
"index": 0
}
]
]
},
"Iterate Products Batch": {
"main": [
[
{
"node": "Retrieve Today's Price Drops",
"type": "main",
"index": 0
}
],
[
{
"node": "Extract Product URLs",
"type": "main",
"index": 0
}
]
]
},
"Read Existing Products": {
"main": [
[
{
"node": "Generate Sample Products",
"type": "main",
"index": 0
}
]
]
},
"Refresh Product Prices": {
"main": [
[
{
"node": "Iterate Products Batch",
"type": "main",
"index": 0
}
]
]
},
"Generate Sample Products": {
"main": [
[
{
"node": "Add Samples to Products Table",
"type": "main",
"index": 0
}
]
]
},
"Initialize History Table": {
"main": [
[
{
"node": "Read Existing Products",
"type": "main",
"index": 0
}
]
]
},
"Morning Schedule Trigger": {
"main": [
[
{
"node": "Fetch Products Data",
"type": "main",
"index": 0
}
]
]
},
"Compile Price Drop Digest": {
"main": [
[
{
"node": "Verify Email (BillionVerify)",
"type": "main",
"index": 0
}
]
]
},
"Initialize Products Table": {
"main": [
[
{
"node": "Initialize History Table",
"type": "main",
"index": 0
}
]
]
},
"Scrape Google Shopping Data": {
"main": [
[
{
"node": "Analyze Product Data",
"type": "main",
"index": 0
}
]
]
},
"Retrieve Today's Price Drops": {
"main": [
[
{
"node": "Compile Price Drop Digest",
"type": "main",
"index": 0
}
]
]
},
"Verify Email (BillionVerify)": {
"main": [
[
{
"node": "IF deliverable",
"type": "main",
"index": 0
}
]
]
},
"IF deliverable": {
"main": [
[
{
"node": "Email Price Drop Notice",
"type": "main",
"index": 0
}
],
[]
]
}
},
"settings": {}
}Workflow templates with Scraperapi
Ready-to-use workflows that verify emails before Scraperapi sends.
How it works
- 1
ScraperAPI fetches and parses web pages, returning structured data including email addresses.
- 2
Your automation layer (n8n with the BillionVerify node, or Integrately) intercepts each new email.
- 3
BillionVerify performs SMTP and syntax checks, disposable-domain lookups, and catch-all detection.
- 4
Each address is returned with a verification status: valid, invalid, risky, or unknown.
- 5
Downstream systems receive only addresses that pass your chosen quality threshold.
When to use this
Validate leads extracted from business directories
ScraperAPI can pull contact data from directories and company pages at scale. BillionVerify filters out role accounts, catch-all domains, and defunct mailboxes before the leads enter your sales workflow.
Keep enrichment pipelines clean
When ScraperAPI enriches existing records with freshly scraped emails, BillionVerify adds a verification step that prevents bad data from overwriting good records in your CRM.
Gate list uploads automatically
Trigger BillionVerify via n8n or Integrately whenever ScraperAPI delivers a new batch, so only verified addresses are written to your email platform or database.
FAQ
Does BillionVerify slow down my ScraperAPI pipeline?
Verification is fast β typically under a second per address. For high-volume batches, use the bulk API endpoint to verify thousands of emails asynchronously without blocking your pipeline.
How do I connect ScraperAPI output to BillionVerify?
The easiest path is an n8n workflow: a ScraperAPI node outputs emails, and the BillionVerify community node verifies them. Integrately offers a no-code 1-click alternative for simpler setups.
Should I verify emails before or after storing them?
Verifying before storage is best practice. It keeps your database clean from the start and avoids the cost of retroactively cleaning large lists later.
Does BillionVerify flag catch-all domains?
Yes. Catch-all domains accept any email address at the SMTP level, making it impossible to confirm individual mailboxes. BillionVerify identifies these and labels them so you can decide how to handle them.
Verify emails in Scraperapi
Create a free account, grab your API key, and stop bounces before they happen.
Get started free