1. Home
  2. API docs
  3. SDKs

SDKs for Node.js and Python

The official SimpleVerifier clients verify an email address or validate a phone number in a few lines: verifyEmail, verifyPhone and a bulk verifyEmails helper that stays under the 120 calls a minute limit. Errors are typed, and rate limits are retried with backoff. Both wrap the same REST API.

Node.js

TypeScript types included, zero runtime dependencies, ESM and CommonJS. Uses the built-in fetch, so it needs Node 18 or later.

InstallPackages publishing soon

npm install simpleverifier

Quickstart

import { SimpleVerifier } from "simpleverifier";

const sv = new SimpleVerifier({ apiKey: process.env.SIMPLEVERIFIER_KEY });

const result = await sv.verifyEmail("jane@company.com");
// { email: "jane@company.com", status: "valid", reason: "Mailbox exists", mailbox_checked: true }

const phone = await sv.verifyPhone("07911 123456", { country: "GB" });
// { phone_status: "valid", phone_e164: "+447911123456", phone_type: "mobile", ... }

const items = await sv.verifyEmails(emails, { concurrency: 5 });
const valid = items.filter((i) => i.ok && i.result.status === "valid");

Python

Sync and asyncio clients with the same methods. Python 3.9 or later, one dependency (httpx), fully typed.

InstallPackages publishing soon

pip install simpleverifier

Quickstart

from simpleverifier import SimpleVerifier

sv = SimpleVerifier()  # reads SIMPLEVERIFIER_KEY

result = sv.verify_email("jane@company.com")
# {"email": "jane@company.com", "status": "valid", "reason": "Mailbox exists", "mailbox_checked": True}

phone = sv.verify_phone("07911 123456", country="GB")

items = sv.verify_emails(emails, concurrency=5)
valid = [i.email for i in items if i.ok and i.result["status"] == "valid"]

# asyncio: from simpleverifier import AsyncSimpleVerifier

Use it today without a package

Until the packages are on npm and PyPI, paste one of these into your project. They call the same endpoints with a 30-second timeout and retry 429 and 503 responses, and the function names match the SDKs, so switching later is a one-line import change.

Node.js

// simpleverifier.mjs — Node 18+, no dependencies
const BASE = "https://simpleverifier.com/api/v1";

export class SimpleVerifierError extends Error {
  constructor(message, status) {
    super(message);
    this.status = status;
  }
}

async function call(path, body, retries = 2) {
  const res = await fetch(`${BASE}/${path}`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.SIMPLEVERIFIER_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(body),
    signal: AbortSignal.timeout(30_000),
  });
  if ((res.status === 429 || res.status === 503) && retries > 0) {
    await new Promise((resolve) => setTimeout(resolve, (3 - retries) * 1000));
    return call(path, body, retries - 1);
  }
  const data = await res.json().catch(() => ({}));
  if (!res.ok) throw new SimpleVerifierError(data.error ?? res.statusText, res.status);
  return data;
}

export const verifyEmail = (email) => call("verify", { email });
export const verifyPhone = (phone, { country, live } = {}) => call("phone", { phone, country, live });

Python

# simpleverifier_client.py — Python 3.9+, standard library only
import json, os, time, urllib.error, urllib.request

def _call(path, body, retries=2):
    request = urllib.request.Request(
        f"https://simpleverifier.com/api/v1/{path}",
        data=json.dumps(body).encode(),
        headers={
            "Authorization": f"Bearer {os.environ['SIMPLEVERIFIER_KEY']}",
            "Content-Type": "application/json",
        },
    )
    try:
        with urllib.request.urlopen(request, timeout=30) as response:
            return json.load(response)
    except urllib.error.HTTPError as error:
        if error.code in (429, 503) and retries > 0:
            time.sleep(3 - retries)
            return _call(path, body, retries - 1)
        message = json.loads(error.read() or b"{}").get("error", error.reason)
        raise RuntimeError(f"SimpleVerifier {error.code}: {message}") from error

def verify_email(email):
    return _call("verify", {"email": email})

def verify_phone(phone, country=None, live=None):
    body = {"phone": phone}
    if country:
        body["country"] = country
    if live is not None:
        body["live"] = live
    return _call("phone", body)

Errors

Every error the SDKs raise extends SimpleVerifierError, which carries the HTTP status and the JSON error body. Auth and payment errors are never retried.

StatusError classWhen
400BadRequestErrorThe email or phone parameter is missing.
401AuthErrorThe API key is missing, wrong or revoked.
402PaymentRequiredErrorThe key's subscription isn't active.
429RateLimitErrorMore than 120 calls a minute. Retried automatically with backoff.
503ServiceUnavailableErrorThe service is briefly unavailable. Retried automatically.
noneTimeoutErrorNo response within the timeout (30 seconds by default).

Open-source disposable email domain list

The 8,740 disposable domains SimpleVerifier blocks are being published as a public CC0 list (domains.txt, domains.json, and curated notes on well-known providers in services.json), with tiny zero-dependency lookup packages. They check the domain only; to confirm the mailbox itself exists, use the API.

Disposable check for Node.js

npm install is-disposable-email-address

Disposable check for Python

pip install is-disposable-email-address
import { isDisposableEmail } from "is-disposable-email-address";

isDisposableEmail("someone@mailinator.com"); // true

Packages publishing soon Until then, look up any domain with the free disposable email checker or browse the disposable domain index.

Pricing

The SDKs are free. API access is included in every SimpleVerifier plan at a flat monthly price, with no per-call credits. See pricing.

Common questions

Is there an official SimpleVerifier SDK?
Yes: simpleverifier on npm for Node.js and simpleverifier on PyPI for Python. Both cover email verification, phone validation and bulk verification, with typed errors and automatic retries on rate limits. Both are being published now; until then, the copy-paste clients on this page call the same API.
Do the SDKs respect the 120 calls a minute limit?
Yes. Each client paces its own requests to 120 a minute by default, and retries a 429 or 503 response with exponential backoff, honouring the Retry-After header when the server sends one. The bulk helper verifies a list with bounded concurrency and reports each address's result or error without stopping the run.
Can I use the SDK in the browser?
No. Keep your API key on your server. Anyone who can read a key from your page can use your plan. Call SimpleVerifier from your backend and pass the verdict to your form.
Is the disposable email domain list open source?
It is being published as a public CC0 list with small lookup packages for npm and PyPI. Until then you can look up any domain with the free disposable email checker.

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