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 simpleverifierQuickstart
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 simpleverifierQuickstart
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 AsyncSimpleVerifierUse 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.
| Status | Error class | When |
|---|---|---|
| 400 | BadRequestError | The email or phone parameter is missing. |
| 401 | AuthError | The API key is missing, wrong or revoked. |
| 402 | PaymentRequiredError | The key's subscription isn't active. |
| 429 | RateLimitError | More than 120 calls a minute. Retried automatically with backoff. |
| 503 | ServiceUnavailableError | The service is briefly unavailable. Retried automatically. |
| none | TimeoutError | No 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-addressDisposable check for Python
pip install is-disposable-email-addressimport { isDisposableEmail } from "is-disposable-email-address";
isDisposableEmail("someone@mailinator.com"); // truePackages 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.