Diagnose and reduce Apollo.io bounce rates by enriching each lead with live search data before sending. High bounce rates usually stem from stale data: people change jobs, companies rebrand, and domains expire. By running a search query against each lead's name and company before outreach, you can verify the person still works there, confirm the domain resolves, and find updated contact information. This enrichment step typically takes under a second per lead and can cut bounce rates significantly.
Prerequisites
- Python 3.8+ installed
- requests library installed
- A Scavio API key from scavio.dev
- An Apollo.io lead export (CSV)
Walkthrough
Step 1: Load Apollo leads from CSV
Read exported Apollo leads and extract the fields needed for enrichment.
import os, csv, requests, json
API_KEY = os.environ['SCAVIO_API_KEY']
def load_leads(csv_path: str) -> list:
leads = []
with open(csv_path) as f:
reader = csv.DictReader(f)
for row in reader:
leads.append({
'name': row.get('First Name', '') + ' ' + row.get('Last Name', ''),
'company': row.get('Company', ''),
'email': row.get('Email', ''),
'title': row.get('Title', ''),
'domain': row.get('Website', ''),
})
return leads
leads = load_leads('apollo_export.csv')
print(f'Loaded {len(leads)} leads')Step 2: Enrich each lead via search
Search for each lead by name and company to verify their current position.
def enrich_lead(lead: dict) -> dict:
query = f"{lead['name']} {lead['company']} LinkedIn"
resp = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': API_KEY},
json={'platform': 'google', 'query': query}, timeout=15)
results = resp.json().get('organic_results', [])
enriched = {**lead, 'verified': False, 'search_results': []}
for r in results[:3]:
title = r.get('title', '').lower()
snippet = r.get('snippet', '').lower()
enriched['search_results'].append(r.get('title', ''))
if lead['company'].lower() in title or lead['company'].lower() in snippet:
enriched['verified'] = True
break
return enriched
sample = enrich_lead(leads[0]) if leads else {}
print(f"Verified: {sample.get('verified')}")Step 3: Validate domain is active
Check that the company domain still resolves by searching for it directly.
def check_domain(domain: str) -> bool:
if not domain:
return False
resp = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': API_KEY},
json={'platform': 'google', 'query': f'site:{domain}'}, timeout=15)
results = resp.json().get('organic_results', [])
return len(results) > 0
def enrich_with_domain(lead: dict) -> dict:
lead['domain_active'] = check_domain(lead.get('domain', ''))
return lead
for lead in leads[:3]:
lead = enrich_with_domain(lead)
print(f"{lead['company']}: domain active = {lead['domain_active']}")Step 4: Score bounce risk
Assign a risk score to each lead based on enrichment signals.
def bounce_risk(lead: dict) -> str:
score = 0
if not lead.get('verified'):
score += 2
if not lead.get('domain_active'):
score += 3
if not lead.get('email'):
score += 3
if score >= 5:
return 'high'
elif score >= 2:
return 'medium'
return 'low'
def score_leads(leads: list) -> list:
for lead in leads:
enriched = enrich_lead(lead)
enriched = enrich_with_domain(enriched)
enriched['bounce_risk'] = bounce_risk(enriched)
lead.update(enriched)
return leads
scored = score_leads(leads[:5])
for lead in scored:
print(f"{lead['name']} ({lead['company']}): {lead['bounce_risk']} risk")Step 5: Export clean leads
Write verified, low-risk leads to a new CSV for outreach.
def export_clean(leads: list, output_path: str):
clean = [l for l in leads if l.get('bounce_risk') != 'high']
if not clean:
print('No clean leads found')
return
keys = ['name', 'company', 'email', 'title', 'domain', 'verified', 'domain_active', 'bounce_risk']
with open(output_path, 'w', newline='') as f:
writer = csv.DictWriter(f, fieldnames=keys, extrasaction='ignore')
writer.writeheader()
writer.writerows(clean)
print(f'Exported {len(clean)} clean leads (removed {len(leads) - len(clean)} high-risk)')
export_clean(scored, 'apollo_clean.csv')Python Example
import requests, os
H = {'x-api-key': os.environ['SCAVIO_API_KEY']}
def verify_lead(name, company):
data = requests.post('https://api.scavio.dev/api/v1/search', headers=H,
json={'platform': 'google', 'query': f'{name} {company} LinkedIn'}).json()
for r in data.get('organic_results', [])[:3]:
if company.lower() in (r.get('title', '') + r.get('snippet', '')).lower():
return True
return False
print(verify_lead('Jane Doe', 'Acme Corp'))JavaScript Example
const H = {'x-api-key': process.env.SCAVIO_API_KEY, 'Content-Type': 'application/json'};
async function verifyLead(name, company) {
const r = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST', headers: H,
body: JSON.stringify({platform: 'google', query: `${name} ${company} LinkedIn`})
});
const results = (await r.json()).organic_results || [];
return results.slice(0, 3).some(r =>
((r.title || '') + (r.snippet || '')).toLowerCase().includes(company.toLowerCase()));
}
verifyLead('Jane Doe', 'Acme Corp').then(console.log);Expected Output
A lead enrichment pipeline that verifies Apollo contacts via live search, scores bounce risk, and exports clean leads for outreach with reduced bounce rates.