Tutorial

How to Diagnose Apollo Bounce Rate with Search Enrichment

Fix high Apollo.io bounce rates by enriching leads with live search data. Verify domains, find current job titles, and validate emails before outreach.

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.

Python
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.

Python
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.

Python
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.

Python
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.

Python
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

Python
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

JavaScript
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

JSON
A lead enrichment pipeline that verifies Apollo contacts via live search, scores bounce risk, and exports clean leads for outreach with reduced bounce rates.

Related Tutorials

Frequently Asked Questions

Most developers complete this tutorial in 15 to 30 minutes. You will need a Scavio API key (free tier works) and a working Python or JavaScript environment.

Python 3.8+ installed. requests library installed. A Scavio API key from scavio.dev. An Apollo.io lead export (CSV). A Scavio API key gives you 250 free credits per month.

Yes. The free tier includes 250 credits per month, which is more than enough to complete this tutorial and prototype a working solution.

Scavio has a native LangChain package (langchain-scavio), an MCP server, and a plain REST API that works with any HTTP client. This tutorial uses the raw REST API, but you can adapt to your framework of choice.

Start Building

Fix high Apollo.io bounce rates by enriching leads with live search data. Verify domains, find current job titles, and validate emails before outreach.