1. Home
  2. API docs
  3. Python

Verify an email address in Python

To verify an email address in Python, run a quick syntax check, then call https://simpleverifier.com/api/v1/verify with requests, passing the address as the email parameter and your key as a Bearer token. The response status is valid, risky or invalid. Set a timeout and treat errors as unknown, not invalid.

By SimpleVerifier Team

Before you start

  • Create a key on the API keys page. Keys start with sv_live_ and are shown once.
  • Export SIMPLEVERIFIER_KEY in your shell or process manager. The helper reads it from os.environ, and a missing key fails loudly with a KeyError.
  • API access is included in the Pro plan ($29.99/month) and the Email + Phone plan ($49.99/month). See pricing.

1. Add the helper

Install requests with pip install requests. The regex only rules out strings that can't be addresses; the API does the real checks.

simpleverifier.py
# simpleverifier.py — Python 3.10+, needs `requests`
import logging
import os
import re

import requests

API_URL = "https://simpleverifier.com/api/v1/verify"
EMAIL_SHAPE = re.compile(r"^[^@\s]+@[^@\s]+\.[^@\s]+$")
log = logging.getLogger(__name__)


def email_status(email: str) -> str | None:
    """Return "valid", "risky" or "invalid", or None if the API could not answer."""
    email = email.strip()
    if not EMAIL_SHAPE.match(email):
        return "invalid"  # fails the local syntax check, no API call made

    try:
        r = requests.get(
            API_URL,
            params={"email": email},
            headers={"Authorization": f"Bearer {os.environ['SIMPLEVERIFIER_KEY']}"},
            timeout=(5, 30),  # connect, read
        )
    except requests.RequestException as exc:
        log.warning("SimpleVerifier unreachable: %s", exc)
        return None

    if r.status_code != 200:
        log.warning("SimpleVerifier returned HTTP %s", r.status_code)
        return None  # 401, 402, 429, 503: fail open

    return r.json().get("status")

2. Act on the result

Four outcomes, and only one of them should block a person.

example.py
from simpleverifier import email_status

status = email_status("jane@company.com")

if status == "invalid":
    print("Rejected: this address cannot receive mail")
elif status == "risky":
    print("Accepted, but delivery is not confirmed (catch-all, role address or similar)")
elif status == "valid":
    print("Accepted: the mailbox exists")
else:
    print("API unavailable: accepted without a mailbox check")

3. Check a short list

Each key can make 120 calls a minute. For a handful of addresses a loop with a pause is fine; for thousands, upload a CSV in the dashboard instead.

bulk.py
import time

from simpleverifier import email_status


def verify_many(emails: list[str]) -> dict[str, str | None]:
    """Check a short list one address at a time, staying under 120 calls a minute."""
    results: dict[str, str | None] = {}
    for email in emails:
        results[email] = email_status(email)
        time.sleep(0.5)
    return results

What the API returns

GET or POST https://simpleverifier.com/api/v1/verify with email runs the syntax, domain, disposable-domain and live mailbox checks in one call and returns:

{
  "email": "jane@company.com",
  "status": "valid",
  "reason": "Mailbox exists",
  "mailbox_checked": true
}

Every snippet above follows the same rule: only a successful response with status set to invalid blocks a person.

ResultWhat it meansWhat to do
validThe mail server confirmed the mailbox exists.Accept.
riskyThe domain is real but the mailbox couldn't be confirmed: catch-all domains, role addresses like info@, providers that hide mailbox status.Accept on signup forms. Store the status and keep these out of cold campaigns.
invalidBad format, no mail server, a disposable domain, or the mailbox doesn't exist.Reject and ask the person to check the address.
timeout, 429 or 503The check didn't finish: a slow mail server, too many calls this minute, or a brief outage.Accept (fail open) and log it. Re-check later if it matters.
401 or 402The key is wrong or revoked, or the subscription isn't active.Accept, and alert yourself: every check is being skipped until it's fixed.

Errors return JSON with an error message. Each key can make 120 calls a minute; for thousands of addresses, upload a CSV in the dashboard instead.

Phone numbers and spreadsheets

The same key works with /api/v1/phone?phone=…&country=… to validate a phone number and normalise it to E.164, with live carrier lookups on the Email + Phone plan. The request and response are in the API reference. To check a column of addresses without code, use the Google Sheets add-on with the same key.

Common questions

Can I verify an email in Python without an API?
You can check syntax with a regex or the email-validator package, and look up MX records with dnspython. Checking that the mailbox exists means opening an SMTP conversation with the recipient's server, which many home and cloud networks block on port 25 and which gets your IP rate-limited if you do it at volume. The API runs that step from servers set up for it.
Is there an async version?
Use the same request with httpx.AsyncClient: pass params={"email": email}, the same Authorization header and timeout=30, and read response.json()["status"]. The endpoint and response are identical.
How much does the SimpleVerifier API cost?
API access is included in the paid plans: Pro at $29.99/month and Email + Phone at $49.99/month. There are no per-call credits. Each key can make 120 calls a minute.
Should I reject risky addresses?
Not on a signup or contact form. Risky means the mailbox couldn't be confirmed, which includes every address at a catch-all company domain. Accept it, store the status, and leave risky addresses out of cold outreach.
What if the API is slow or down?
Let the address through. A mailbox check can take several seconds when a mail server is slow, so cap the wait at about 30 seconds (less on a busy form) and treat a timeout, a 429 or a 503 as unknown rather than invalid.

Ready to clean your email and phone lists?

Start verifying emails and phone numbers today and boost your deliverability.

Get Started

Cancel anytime • No setup required