Disposable email check API
Bewary's email API tells you whether an address is disposable, a free provider or a shared role mailbox such as support@example.com, and whether its domain has a mail server, together with the domain's age and lookalike signals. It returns a verdict too: a throwaway address answers suspicious. It sends no email and does not probe the mailbox. A call costs 1 credit, a free key gets 1,000 credits a month, no card, and it answers in median 211 ms.
- Endpoint
- GET
https://api.bewary.app/v1/email/{address} - Price
- 1 credit
- Free key
- 1,000 credits a month, no card
- Speed
- Median 211 ms, measured
- Returns
- verdict, p_scam, entities with typed facts, reason codes
- MCP tool
lookup_email
Try it
Free from this page: 10 lookups a dayCall it
curl "https://api.bewary.app/v1/email/signup%40mailinator.com" import requests
r = requests.get("https://api.bewary.app/v1/email/signup%40mailinator.com", timeout=10)
result = r.json()
print(result["verdict"], result["p_scam"], result["reason_codes"]) const res = await fetch("https://api.bewary.app/v1/email/signup%40mailinator.com")
const result = await res.json()
console.log(result.verdict, result.p_scam, result.reason_codes) Act on the result
Copy-paste code that turns the answer into a decision. It runs with or without BEWARY_API_KEY. TypeScript uses bewary.d.ts.
import os, requests
from urllib.parse import quote
def accept_signup_email(address):
key = os.environ["BEWARY_API_KEY"] # a free key: bewary.app/account
headers = {"Authorization": f"Bearer {key}"}
try:
r = requests.get("https://api.bewary.app/v1/email/" + quote(address, safe=""),
headers=headers, timeout=10)
r.raise_for_status()
except requests.RequestException:
return True # never block a real customer on our outage
result = r.json()
facts = result["entities"][0]["facts"]
if facts["disposable"] or facts["mx"] is False or result["verdict"] == "scam":
return False
return True
print(accept_signup_email("signup@mailinator.com")) # False import type { Envelope } from "./bewary"
export async function acceptSignupEmail(address: string): Promise<boolean> {
const key = process.env.BEWARY_API_KEY! // a free key: bewary.app/account
const headers: Record<string, string> = { Authorization: `Bearer ${key}` }
const res = await fetch("https://api.bewary.app/v1/email/" + encodeURIComponent(address),
{ headers, signal: AbortSignal.timeout(10_000) })
if (!res.ok) return true // do not block sign-ups on our outage
const r: Envelope = await res.json()
const e = r.entities[0]
if (e.type !== "email") return true
return !(e.facts.disposable || e.facts.mx === false || r.verdict === "scam")
} Response
The fields you will use
entities[0].facts.disposable- A throwaway provider such as mailinator.com.
entities[0].facts.mx- The domain has a mail server.
entities[0].facts.free_provider- Gmail, Outlook, Yahoo and the like.
entities[0].facts.role_account- A shared role mailbox, such as support@example.com or billing@example.com.
entities[1].facts- The domain: age, lookalike, scam list.
{ "schema_version": "1.7.0", "request_id": "req_01M69WHTR4Y1J09ZPHR73E5MR0", "checked_at": "2026-10-31T21:06:21Z", "engine": "bewary-engine/3.0.0", "models": { "calibration": "interim-band-v0" }, "input": { "kind": "lookup", "channel": "unknown", "language": null, "region": null }, "verdict": "suspicious", "p_scam": 0.5, "risk_score": 50, "confidence": 1, "classification": null, "reason_codes": [ "EMAIL_DISPOSABLE" ], "entities": [ { "id": "e1", "type": "email", "value": "signup@mailinator.com", "normalized": "signup@mailinator.com", "role": "mentioned", "verdict": "suspicious", "p_scam": 0.5, "risk_score": 50, "reason_codes": [ "EMAIL_DISPOSABLE" ], "facts": { "domain": "e2", "mx": true, "disposable": true, "free_provider": false, "role_account": false, "disposable_status": "unknown", "disposable_checked_at": null }, "related": [ "e2" ], "datasets": [ { "dataset": "email_providers", "coverage": "WW", "in_coverage": true }, { "dataset": "dns", "coverage": "WW", "in_coverage": true }, { "dataset": "registration", "coverage": "WW", "in_coverage": true }, { "dataset": "breaches", "coverage": "WW", "in_coverage": true }, { "dataset": "community_reports", "coverage": "WW", "in_coverage": true } ] }, { "id": "e2", "type": "domain", "value": "mailinator.com", "normalized": "mailinator.com", "role": "mentioned", "verdict": "safe", "p_scam": 0.0013, "risk_score": 0, "reason_codes": [ "DOMAIN_AGE_GT_1Y" ], "facts": { "registrable_domain": "mailinator.com", "registered_domain": "mailinator.com", "tld": "com", "tld_abuse": "low", "registered_at": "2003-07-02T13:50:53Z", "expires_at": "2028-07-02T13:50:53Z", "age_days": 8521, "age_bucket": "gt_1y", "registrar": "GoDaddy.com, LLC", "dns": { "resolves": true, "a": [ "104.20.46.162", "172.66.146.138" ], "mx": null, "ns": [ "betty.ns.cloudflare.com", "james.ns.cloudflare.com" ] }, "status": "live", "cert_first_seen": null, "lookalike": null, "platform": "none", "allowlisted": false, "listed": false, "seen_in_checks_7d": null, "country": null, "target_countries": null, "list_count": null, "site": null, "platform_status": null, "registry_status": [ "client_delete_prohibited", "client_renew_prohibited", "client_transfer_prohibited", "client_update_prohibited" ], "hold": "none", "registered": true, "registration_checked_at": "2026-10-30T19:19:20Z", "archive": { "checked_at": "2026-10-30T19:20:44Z", "captured": true, "first_capture_at": "2003-07-24T11:42:16Z", "last_capture_at": "2026-10-18T15:10:53Z", "captured_before_registration": false, "months_before_registration": null, "last_capture_before_registration_at": null }, "first_seen_by_bewary": null, "first_listed_publicly": null }, "related": [], "datasets": [ { "dataset": "registration", "coverage": "WW", "in_coverage": true }, { "dataset": "dns", "coverage": "WW", "in_coverage": true }, { "dataset": "certificates", "coverage": "WW", "in_coverage": true }, { "dataset": "web_archive", "coverage": "WW", "in_coverage": true }, { "dataset": "threat_feeds", "coverage": "WW", "in_coverage": true }, { "dataset": "threat_aggregates", "coverage": "WW", "in_coverage": true }, { "dataset": "brand_registry", "coverage": "WW", "in_coverage": true }, { "dataset": "platform_pages", "coverage": "WW", "in_coverage": true }, { "dataset": "community_reports", "coverage": "WW", "in_coverage": true } ] } ], "signals": [ { "code": "EMAIL_DISPOSABLE", "entity": "e1", "severity": "high", "weight": 50, "source_class": "heuristic", "p": null, "dataset": "email_providers", "coverage": "WW", "evidence": { "domain": "mailinator.com" } }, { "code": "DOMAIN_AGE_GT_1Y", "entity": "e2", "severity": "info", "weight": -45, "source_class": "first_party", "p": null, "dataset": "registration", "coverage": "WW", "evidence": { "age_days": 8521 } } ], "degraded": false, "degraded_reasons": [], "cached": false, "explanation": null} { "schema_version": "1.7.0", "request_id": "req_01M69WJ2WTE964XED78MEPPYY1", "checked_at": "2026-10-31T21:06:28Z", "engine": "bewary-engine/3.0.0", "models": { "calibration": "interim-band-v0" }, "input": { "kind": "lookup", "channel": "unknown", "language": null, "region": null }, "verdict": "unknown", "p_scam": 0.2, "risk_score": 20, "confidence": 0, "classification": null, "reason_codes": [], "entities": [ { "id": "e1", "type": "email", "value": "someone@gmail.com", "normalized": "someone@gmail.com", "role": "mentioned", "verdict": "unknown", "p_scam": 0.2, "risk_score": 20, "reason_codes": [], "facts": { "domain": "e2", "mx": true, "disposable": false, "free_provider": true, "role_account": false, "disposable_status": null, "disposable_checked_at": null }, "related": [ "e2" ], "datasets": [ { "dataset": "email_providers", "coverage": "WW", "in_coverage": true }, { "dataset": "dns", "coverage": "WW", "in_coverage": true }, { "dataset": "registration", "coverage": "WW", "in_coverage": true }, { "dataset": "breaches", "coverage": "WW", "in_coverage": true }, { "dataset": "community_reports", "coverage": "WW", "in_coverage": true } ] }, { "id": "e2", "type": "domain", "value": "gmail.com", "normalized": "gmail.com", "role": "mentioned", "verdict": "safe", "p_scam": 0, "risk_score": 0, "reason_codes": [ "DOMAIN_ALLOWLISTED" ], "facts": { "registrable_domain": "gmail.com", "registered_domain": "gmail.com", "tld": "com", "tld_abuse": "low", "registered_at": "1995-08-13T04:00:00Z", "expires_at": "2027-08-12T04:00:00Z", "age_days": 11401, "age_bucket": "gt_1y", "registrar": "MarkMonitor Inc.", "dns": { "resolves": true, "a": [ "142.251.142.5" ], "mx": null, "ns": [ "ns1.google.com", "ns2.google.com", "ns3.google.com", "ns4.google.com" ] }, "status": "live", "cert_first_seen": null, "lookalike": null, "platform": "none", "allowlisted": true, "listed": false, "seen_in_checks_7d": null, "country": null, "target_countries": null, "list_count": null, "site": null, "platform_status": null, "registry_status": [ "client_delete_prohibited", "client_transfer_prohibited", "client_update_prohibited", "server_delete_prohibited", "server_transfer_prohibited", "server_update_prohibited" ], "hold": "none", "registered": true, "registration_checked_at": "2026-10-30T19:19:57Z", "archive": null, "first_seen_by_bewary": null, "first_listed_publicly": null }, "related": [], "datasets": [ { "dataset": "registration", "coverage": "WW", "in_coverage": true }, { "dataset": "dns", "coverage": "WW", "in_coverage": true }, { "dataset": "certificates", "coverage": "WW", "in_coverage": true }, { "dataset": "web_archive", "coverage": "WW", "in_coverage": true }, { "dataset": "threat_feeds", "coverage": "WW", "in_coverage": true }, { "dataset": "threat_aggregates", "coverage": "WW", "in_coverage": true }, { "dataset": "brand_registry", "coverage": "WW", "in_coverage": true }, { "dataset": "platform_pages", "coverage": "WW", "in_coverage": true }, { "dataset": "community_reports", "coverage": "WW", "in_coverage": true } ] } ], "signals": [ { "code": "EMAIL_FREE_PROVIDER", "entity": "e1", "severity": "medium", "weight": 0, "source_class": "heuristic", "p": null, "dataset": "email_providers", "coverage": "WW", "evidence": { "domain": "gmail.com" } }, { "code": "DOMAIN_ALLOWLISTED", "entity": "e2", "severity": "info", "weight": -60, "source_class": "first_party", "p": null, "dataset": "brand_registry", "coverage": "WW", "evidence": {} } ], "degraded": false, "degraded_reasons": [], "cached": false, "explanation": null} { "schema_version": "1.7.0", "request_id": "req_01M69WHY5F6FQXMBZH7W6QYW88", "checked_at": "2026-10-31T21:06:24Z", "engine": "bewary-engine/3.0.0", "models": { "calibration": "interim-band-v0" }, "input": { "kind": "lookup", "channel": "unknown", "language": null, "region": null }, "verdict": "unknown", "p_scam": 0.2, "risk_score": 20, "confidence": 0, "classification": null, "reason_codes": [], "entities": [ { "id": "e1", "type": "email", "value": "info@stripe.com", "normalized": "info@stripe.com", "role": "mentioned", "verdict": "unknown", "p_scam": 0.2, "risk_score": 20, "reason_codes": [], "facts": { "domain": "e2", "mx": true, "disposable": false, "free_provider": false, "role_account": true, "disposable_status": null, "disposable_checked_at": null }, "related": [ "e2" ], "datasets": [ { "dataset": "email_providers", "coverage": "WW", "in_coverage": true }, { "dataset": "dns", "coverage": "WW", "in_coverage": true }, { "dataset": "registration", "coverage": "WW", "in_coverage": true }, { "dataset": "breaches", "coverage": "WW", "in_coverage": true }, { "dataset": "community_reports", "coverage": "WW", "in_coverage": true } ] }, { "id": "e2", "type": "domain", "value": "stripe.com", "normalized": "stripe.com", "role": "mentioned", "verdict": "safe", "p_scam": 0, "risk_score": 0, "reason_codes": [ "DOMAIN_ALLOWLISTED" ], "facts": { "registrable_domain": "stripe.com", "registered_domain": "stripe.com", "tld": "com", "tld_abuse": "low", "registered_at": "1995-09-12T04:00:00Z", "expires_at": "2027-09-11T04:00:00Z", "age_days": 11371, "age_bucket": "gt_1y", "registrar": "SafeNames Ltd.", "dns": { "resolves": true, "a": [ "18.202.131.124", "52.30.58.64", "52.49.17.168" ], "mx": null, "ns": [ "ns-1087.awsdns-07.org", "ns-1882.awsdns-43.co.uk", "ns-423.awsdns-52.com", "ns-705.awsdns-24.net" ] }, "status": "live", "cert_first_seen": null, "lookalike": null, "platform": "none", "allowlisted": true, "listed": false, "seen_in_checks_7d": null, "country": null, "target_countries": null, "list_count": null, "site": null, "platform_status": null, "registry_status": [ "client_delete_prohibited", "client_transfer_prohibited", "client_update_prohibited", "server_delete_prohibited", "server_transfer_prohibited", "server_update_prohibited" ], "hold": "none", "registered": true, "registration_checked_at": "2026-10-30T19:19:23Z", "archive": { "checked_at": "2026-10-30T19:20:56Z", "captured": true, "first_capture_at": "1996-12-18T23:42:05Z", "last_capture_at": "2026-10-27T18:27:47Z", "captured_before_registration": false, "months_before_registration": null, "last_capture_before_registration_at": null }, "first_seen_by_bewary": null, "first_listed_publicly": null }, "related": [], "datasets": [ { "dataset": "registration", "coverage": "WW", "in_coverage": true }, { "dataset": "dns", "coverage": "WW", "in_coverage": true }, { "dataset": "certificates", "coverage": "WW", "in_coverage": true }, { "dataset": "web_archive", "coverage": "WW", "in_coverage": true }, { "dataset": "threat_feeds", "coverage": "WW", "in_coverage": true }, { "dataset": "threat_aggregates", "coverage": "WW", "in_coverage": true }, { "dataset": "brand_registry", "coverage": "WW", "in_coverage": true }, { "dataset": "platform_pages", "coverage": "WW", "in_coverage": true }, { "dataset": "community_reports", "coverage": "WW", "in_coverage": true } ] } ], "signals": [ { "code": "DOMAIN_ALLOWLISTED", "entity": "e2", "severity": "info", "weight": -60, "source_class": "first_party", "p": null, "dataset": "brand_registry", "coverage": "WW", "evidence": {} } ], "degraded": false, "degraded_reasons": [], "cached": false, "explanation": null} Real responses, captured from the live API on 2026-10-31. Every response has this shape: see Response format.
Email address facts
Every key is in every response, null when unknown. A key marked Coming stays null until its source ships, so you can code against it now.
| Key | Type | Meaning |
|---|---|---|
domain | entity id or null | The domain entity, with its own facts. |
mx | boolean or null | The domain has a mail server. |
disposable | boolean or null | A throwaway email provider. |
free_provider | boolean or null | Gmail, Outlook, Yahoo and the like. |
role_account | boolean or null | A shared role mailbox, such as support@example.com or billing@example.com. |
disposable_status | receiving | dead | unknown or null | For a throwaway provider: whether it still takes mail. |
disposable_checked_at | timestamp or null | When the throwaway domain was last re-checked. |
Parameters
| Name | Type | Description |
|---|---|---|
addresspath, required | string | The email address, URL-encoded. |
Questions
How do I detect disposable email addresses with an API?
GET /v1/email/{address}. facts.disposable is true for throwaway providers such as mailinator.com. The same answer says whether the address is a free provider or a role mailbox and whether the domain has a mail server.
Does it check that the mailbox exists?
No. It checks the domain's mail server, not the mailbox. It sends no email and makes no SMTP probe.
What verdict does a Gmail or Outlook address get?
unknown: Bewary cannot vouch for a personal address at a free provider, and nothing about it is suspicious either. For a sign-up form, decide on the facts (disposable, mx), not the verdict. A throwaway address answers suspicious.
Does a role address like support@example.com count against it?
role_account is a fact for your own rules. It does not change the verdict.
How fast is it?
Measured median 211 ms for an address seen for the first time.
Used for
- Sign-up forms rejecting throwaway addresses.
- Checking the sender of a suspicious email.
- Lead scoring that discounts role and free addresses.
Reason codes it can return
| Code | Meaning | Severity |
|---|---|---|
LISTED_BLOCKLIST | On scam blocklist | Critical |
DOMAIN_ALLOWLISTED | Established domain (allowlist) | Info |
DOMAIN_AGE_GT_1Y | Established domain | Info |
DOMAIN_AGE_90D_1Y | Established domain (<1y) | Info |
DOMAIN_AGE_30_90D | Recently-registered domain | Medium |
DOMAIN_AGE_LT_30D | Brand-new domain | Medium |
DOMAIN_MULTITENANT_PLATFORM | Hosted on a public platform | Info |
DOMAIN_AGE_UNKNOWN | Domain age unknown | Info |
DOMAIN_LOOKALIKE_BRAND_WORD | Lookalike domain | Medium |
DOMAIN_MIXED_SCRIPT | Fake domain (mixed alphabets) | High |
DOMAIN_HOMOGLYPH_BRAND | Fake domain (homoglyph) | High |
DOMAIN_BRAND_ON_ABUSED_TLD | Fake domain (brand + suspicious TLD) | High |
DOMAIN_TYPO_BRAND | Possible fake domain (typo) | Medium |
DOMAIN_BRAND_SCAM_WORD | Possible fake domain (brand + scam word) | Medium |
TLD_HIGH_ABUSE | Risky domain | Medium |
EMAIL_DISPOSABLE | Disposable email | High |
EMAIL_SENDER_DOMAIN_FORGED | Forged sender domain | High |
EMAIL_DOMAIN_NO_MX | Domain can't receive email | Medium |
EMAIL_FREE_PROVIDER | Free email address | Medium |
EMAIL_HIGH_RISK | High-risk sender | High |
EMAIL_RISKY | Risky sender | Medium |
DOMAIN_DECEPTIVE_STRUCTURE | A brand name placed before an @ so the real host hides after it | High |
DOMAIN_CERT_LT_48H | First TLS certificate issued in the last 48 hours | Medium |
LISTED_CAUTION | On a broad threat list that also holds spam and malware hosts | Medium |
PROTECTIVE_DNS_BLOCKED | Blocked by public protective DNS resolvers | Medium |
PLATFORM_TAKEDOWN | The hosting platform took it down | High |
PLATFORM_WARNING | The platform shows a phishing or malware warning in front of it | High |
DOMAIN_REGISTRY_HOLD | The registry holds the domain out of the DNS | High |
DOMAIN_REGISTRAR_HOLD | The registrar suspended the domain | Medium |
Reserved codes are in the contract, not emitted yet. All reason codes
Updated · This page as Markdown · Changelog