Email Verification API Python 2026 - Integration Guide with Code Examples | BounceZero
Blog›Developer Guides

Email Verification API Python 2026
Integration Guide with Code Examples

This guide covers how to integrate BounceZero’s email verification API in Python - from a simple synchronous requests call to async batch verification with httpx, Flask/Django integration patterns, and error handling for production use.

By BounceZero Team |July 2026 |8 min read

1. Basic Synchronous Verification (requests)

pip install requests
import requests

API_KEY = "YOUR_BOUNCEZERO_API_KEY"
BASE_URL = "https://api.bouncezero.io/api/v1"

def verify_email(email: str) -> dict:
    """Verify a single email address and return the full result."""
    response = requests.post(
        f"{BASE_URL}/verify",
        json={"email": email},
        headers={"X-API-Key": API_KEY},
        timeout=10
    )
    response.raise_for_status()
    return response.json()

def is_safe_to_send(email: str) -> bool:
    """Return True only if the email is valid and not an unresolved catch-all."""
    result = verify_email(email)
    if result["classification"] != "valid":
        return False  # invalid, disposable, spamtrap, risky or unverifiable
    meta = result.get("metadata") or {}
    # Unresolved catch-all is reported valid: keep only high-confidence ones
    if meta.get("catch_all_unresolved") and result.get("score", 0) < 70:
        return False
    return True

# Usage
if is_safe_to_send("[email protected]"):
    print("Safe to send")
else:
    print("Suppress this email")

The classification field is binary: valid or invalid. The detailed verdict (verified, likely_valid, catch_all, invalid, disposable, risky, unknown) is in metadata.internal_classification; metadata.catch_all_unresolved marks catch-all addresses reported as valid, and metadata.refunded marks addresses that could not be verified (credit auto-refunded). The score field (0-100) rates confidence - 70+ is safe to send for catch-all domains.

2. Async Batch Verification (httpx + asyncio)

pip install httpx
import asyncio
import httpx

API_KEY = "YOUR_BOUNCEZERO_API_KEY"
BASE_URL = "https://api.bouncezero.io/api/v1"
CONCURRENCY = 10  # max concurrent requests (respect rate limits)

async def verify_email_async(client: httpx.AsyncClient, email: str) -> dict:
    response = await client.post(
        f"{BASE_URL}/verify",
        json={"email": email},
        headers={"X-API-Key": API_KEY},
    )
    response.raise_for_status()
    data = response.json()
    return {"email": email, **data}

async def verify_batch(emails: list[str]) -> list[dict]:
    sem = asyncio.Semaphore(CONCURRENCY)

    async def bounded_verify(client, email):
        async with sem:
            try:
                return await verify_email_async(client, email)
            except Exception as e:
                return {"email": email, "classification": "error", "error": str(e)}

    async with httpx.AsyncClient(timeout=15) as client:
        tasks = [bounded_verify(client, email) for email in emails]
        return await asyncio.gather(*tasks)

# Usage
emails = ["[email protected]", "[email protected]", "[email protected]"]
results = asyncio.run(verify_batch(emails))

for r in results:
    status = r.get("classification", "error")
    print(f"{r['email']}: {status}")

The semaphore limits concurrency to 10 requests at a time. For lists over 500 emails, the bulk upload endpoint (section 3) is faster and more efficient.

3. CSV Batch Verification

import csv
import asyncio
import httpx

API_KEY = "YOUR_BOUNCEZERO_API_KEY"

async def verify_csv(input_path: str, output_path: str):
    # Read emails from CSV
    emails = []
    with open(input_path, newline="") as f:
        reader = csv.DictReader(f)
        fieldnames = reader.fieldnames or []
        rows = list(reader)
        for row in rows:
            emails.append(row.get("email", ""))

    # Verify all emails
    from verify_email_async import verify_batch  # import from section 2
    results = await verify_batch(emails)
    result_map = {r["email"]: r for r in results}

    # Write enriched CSV
    out_fields = list(fieldnames) + ["bz_result", "bz_score", "bz_internal"]
    with open(output_path, "w", newline="") as f:
        writer = csv.DictWriter(f, fieldnames=out_fields)
        writer.writeheader()
        for row in rows:
            email = row.get("email", "")
            res = result_map.get(email, {})
            row["bz_result"] = res.get("classification", "")
            row["bz_score"] = res.get("score", "")
            row["bz_internal"] = (res.get("metadata") or {}).get("internal_classification", "")
            writer.writerow(row)

    print(f"Written {len(rows)} rows to {output_path}")

asyncio.run(verify_csv("leads.csv", "leads_verified.csv"))

This appends three columns to the existing CSV: bz_result, bz_score, and bz_internal. Filter rows where bz_result == "invalid" before loading to your sequencer.

4. Django / Flask Integration Pattern

Flask - validate at signup
from flask import Flask, request, jsonify
import requests, os

app = Flask(__name__)
API_KEY = os.environ["BOUNCEZERO_API_KEY"]

@app.route("/register", methods=["POST"])
def register():
    email = request.json.get("email", "").strip()

    # Verify email before creating account
    try:
        res = requests.post(
            "https://api.bouncezero.io/api/v1/verify",
            json={"email": email},
            headers={"X-API-Key": API_KEY},
            timeout=5
        ).json()
    except Exception:
        # Fail open: allow registration if API is unavailable
        res = {}

    internal = (res.get("metadata") or {}).get("internal_classification")
    if internal == "disposable":
        return jsonify({"error": "Disposable emails are not allowed."}), 422
    if res.get("classification") == "invalid" and not (res.get("metadata") or {}).get("refunded"):
        return jsonify({"error": "Invalid email address."}), 422
    # metadata.refunded = could not be verified: fail open like a timeout

    # Create user account...
    return jsonify({"status": "ok"}), 201

Note the fail open pattern: if the API call fails (timeout, network error), registration proceeds. This prevents the verification API from becoming a hard dependency that breaks signup. Log failures for monitoring.

API Response Fields

Field Type Description
classification string Binary verdict: valid | invalid
score int 0-100 Confidence score - especially useful for catch-all decisions
is_deliverable boolean True when classification is valid
risk_level string low | medium | high
checks object syntax, domain_valid, not_disposable, not_catch_all, mailbox_verified
metadata.internal_classification string Detailed verdict: verified | likely_valid | catch_all | invalid | disposable | risky | unknown | spamtrap | error
metadata.refunded boolean True when the address could not be verified (credit auto-refunded)

New to verification? Start with the complete email verification guide.

Frequently Asked Questions

How do I verify email addresses in Python?

Use the BounceZero API with Python’s requests library: response = requests.post(‘https://api.bouncezero.io/api/v1/verify’, json={‘email’: email}, headers={‘X-API-Key’: ‘YOUR_KEY’}). The result contains ‘classification’ (valid or invalid), ‘score’, ‘is_deliverable’, ‘checks’, and ‘metadata.internal_classification’ with the detailed verdict (verified, catch_all, disposable, unknown and so on). For async code, use httpx.AsyncClient.

How do I verify emails in bulk with Python?

For lists under 500 emails, use asyncio + httpx with a semaphore (CONCURRENCY = 10) to make concurrent API calls. For 1,000+ emails, use the bulk upload API endpoint - upload CSV, poll for completion, download enriched results.

What Python libraries do I need for email verification?

For synchronous verification: requests (pip install requests). For async: httpx (pip install httpx) and asyncio (standard library). For CSV handling: pandas or the built-in csv module. No other dependencies needed for BounceZero API integration.

Get your API key. Start verifying in minutes.

100 free credits on every account. No credit card required. Full API docs available after signup.

AL

Written by

Ayoub Lebda

Founder, BounceZero - Email-infrastructure engineer

Ayoub built BounceZero's 5-stage validation pipeline, its dedicated BGP-announced IP infrastructure, and the Patroni HA PostgreSQL cluster behind every verification. Previously built high-volume email delivery infrastructure. Trained at 1337 Benguerir (École 42 network, 2019). Open-source: bgp_analyzer.

Build with the BounceZero API

Endpoints, code samples, and language guides