DEV Community

shahil shaikh
shahil shaikh

Posted on

Email-Validation API

Overview

This Email Validator API goes beyond basic syntax checking. Most email validators only check if the format looks correct. This API actually connects to the mail server via SMTP and confirms the address exists — catching fake signups, disposable addresses, and dead mailboxes that simple checks completely miss.

Imagine someone signs up on your website with a throwaway email. They pollute your database and never become a real user. This API catches those bad emails at the point of entry — before they ever reach your system.

Unlike other validators that always run every check regardless of what you need, this API lets you specify exactly which checks to run using the fields parameter. Only the checks you request actually execute — so a disposable-only check responds instantly, while a full SMTP probe only fires when you explicitly ask for it. You get responses as fast as the check you need, nothing more.

What Gets Checked — 11 Fields

Field What It Does
syntax Checks email format against RFC 5321/5322 rules
mx DNS MX lookup — confirms the domain is set up to receive email
smtp Live SMTP probe — confirms the mailbox exists on the server
disposable Detects throwaway emails — 769,000+ domains, live-updated from community blocklists
role Detects shared inboxes: admin@, noreply@, support@, sales@, and 100+ variants (two-layer: exact match + fuzzy pattern)
subaddress Detects plus-tag addressing like user+tag@gmail.com
provider Detects free email providers — Gmail, Yahoo, Outlook, and 30+ more (two-layer: exact match + MX fingerprint)
spamtrap Detects spam trap patterns like honeypot@, trap@, abuse@, blacklist@
intelligence Domain entropy scoring + risky TLD detection (53+ TLDs hardcoded, live-updated from community list)
auth Checks SPF, DMARC, and DKIM DNS records
typo Detects common domain typos and suggests corrections (two-layer: dictionary + Levenshtein fuzzy matching)

All 11 fields run when no fields param is provided. Pass fields= to run only what you need.

Quick Start

Step 1 — Subscribe to any plan including free and copy your RapidAPI key from the dashboard.

Step 2 — Make your first request. Replace YOUR_API_KEY_HERE with your actual key.

JavaScript

const response = await fetch(
  'https://email-validator-rjwr.onrender.com/v1/validate?email=test@gmail.com',
  {
    headers: {
      'x-rapidapi-key': 'YOUR_API_KEY_HERE',
      'x-rapidapi-host': 'email-validator-rjwr.onrender.com'
    }
  }
);
const data = await response.json();
console.log(data);
Enter fullscreen mode Exit fullscreen mode

Python

import requests

url = "https://email-validator-rjwr.onrender.com/v1/validate"
headers = {
    "x-rapidapi-key": "YOUR_API_KEY_HERE",
    "x-rapidapi-host": "email-validator-rjwr.onrender.com"
}
response = requests.get(url, params={"email": "test@gmail.com"}, headers=headers)
print(response.json())
Enter fullscreen mode Exit fullscreen mode

PHP

$curl = curl_init();
curl_setopt_array($curl, [
    CURLOPT_URL => "https://email-validator-rjwr.onrender.com/v1/validate?email=test@gmail.com",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        "x-rapidapi-key: YOUR_API_KEY_HERE",
        "x-rapidapi-host: email-validator-rjwr.onrender.com"
    ],
]);
$response = json_decode(curl_exec($curl));
curl_close($curl);
print_r($response);
Enter fullscreen mode Exit fullscreen mode

cURL

curl -X GET \
  "https://email-validator-rjwr.onrender.com/v1/validate?email=test@gmail.com" \
  -H "x-rapidapi-key: YOUR_API_KEY_HERE" \
  -H "x-rapidapi-host: email-validator-rjwr.onrender.com"
Enter fullscreen mode Exit fullscreen mode

The fields Parameter — Run Only What You Need

This is the most important feature in v5.0. By default, all 11 fields run. If you pass fields=, only those specific checks execute — the rest never run. Response time depends entirely on which checks you request.

fields=syntax,role,provider,spamtrap    →  ~0ms    (zero network I/O)
fields=disposable                       →  ~0ms    (in-memory lookup)
fields=typo                             →  ~5ms    (dictionary lookup)
fields=mx                               →  ~200ms  (one DNS query)
fields=auth                             →  ~300ms  (3 DNS TXT queries)
fields=mx,disposable,role               →  ~200ms  (MX + disposable in parallel)
fields=smtp                             →  ~1-3s   (TCP + SMTP handshake)
no fields param / fields=all            →  ~2-3s   (all 11 fields)
Enter fullscreen mode Exit fullscreen mode

Available field names:

Field What Runs Speed Returns
syntax RFC 5321/5322 format check instant syntax_valid
mx DNS MX record lookup ~200ms mx_found, mx_records
smtp Live SMTP mailbox probe ~1-3s smtp_verified, smtp_catch_all, smtp_greylisted, smtp_skipped
disposable 769,000+ domain blocklist, live-updated instant is_disposable, disposable_method
role Role-based prefix detection instant is_role_based
subaddress Plus-tag detection instant is_sub_address
provider Free provider detection instant is_free_provider
spamtrap Spam trap pattern matching instant spam_trap_suspected
intelligence Domain entropy + TLD risk instant risky_tld, domain_entropy, intelligence
auth SPF, DMARC, DKIM DNS records ~300ms email_auth
typo Common domain typo detection instant suggestions

The response only includes fields for the checks that actually ran. Fields you did not request are simply absent — the response is clean and minimal.

Example — signup form, fast, no SMTP:

GET /v1/validate?email=user@example.com&fields=mx,disposable,role
Enter fullscreen mode Exit fullscreen mode

Example — typo correction only, near-zero latency:

GET /v1/validate?email=user@gmial.com&fields=typo
Enter fullscreen mode Exit fullscreen mode

Example — security audit only:

GET /v1/validate?email=user@example.com&fields=auth,intelligence
Enter fullscreen mode Exit fullscreen mode

Pass fields=all or omit the parameter to run all checks. Unknown field names are ignored and reported back in _unknown_fields so you can catch typos in your integration.

Endpoints

1. Validate Single Email

GET /v1/validate

Parameter Type Required Description
email string Yes The email address you want to validate
fields string No Comma-separated list of checks to run. Omit for all 11 fields.
quick boolean No Set to true to skip SMTP. Ignored if smtp is not in your fields list.

Full Response — Valid Email

{
  "email": "shahilshaikh5718@gmail.com",
  "result": "VALID",
  "reason": "All checks passed",
  "score": 100,
  "score_label": "Excellent",
  "checks": {
    "syntax_valid": true,
    "mx_found": true,
    "mx_records": [
      "gmail-smtp-in.l.google.com",
      "alt1.gmail-smtp-in.l.google.com",
      "alt2.gmail-smtp-in.l.google.com",
      "alt3.gmail-smtp-in.l.google.com",
      "alt4.gmail-smtp-in.l.google.com"
    ],
    "smtp_verified": null,
    "smtp_catch_all": false,
    "smtp_greylisted": false,
    "smtp_skipped": true,
    "is_disposable": false,
    "disposable_method": null,
    "is_role_based": false,
    "is_sub_address": false,
    "is_free_provider": true,
    "spam_trap_suspected": false,
    "risky_tld": false,
    "domain_entropy": 25,
    "email_auth": {
      "spf": true,
      "spf_policy": "neutral",
      "dmarc": true,
      "dmarc_policy": "none",
      "dkim": false
    }
  },
  "intelligence": null,
  "suggestions": null,
  "latency_ms": 2536
}
Enter fullscreen mode Exit fullscreen mode

Response — Disposable Email Rejected

{
  "email": "temp123@tempmail.com",
  "result": "REJECT",
  "reason": "Disposable email detected via domain_list",
  "score": 2,
  "score_label": "Very Poor",
  "checks": {
    "syntax_valid": true,
    "mx_found": true,
    "mx_records": ["mx.tempmail.com"],
    "smtp_verified": null,
    "smtp_catch_all": false,
    "smtp_greylisted": false,
    "smtp_skipped": false,
    "is_disposable": true,
    "disposable_method": "domain_list",
    "is_role_based": false,
    "is_sub_address": false,
    "is_free_provider": true,
    "spam_trap_suspected": false,
    "risky_tld": false,
    "domain_entropy": 12,
    "email_auth": {
      "spf": false,
      "spf_policy": null,
      "dmarc": false,
      "dmarc_policy": null,
      "dkim": false
    }
  },
  "intelligence": {
    "risk_score": 85,
    "flags": [
      "Domain registered only 12 days ago",
      "MX IP shared by 620 domains — disposable infrastructure",
      "No web presence detected"
    ]
  },
  "suggestions": null,
  "latency_ms": 891
}
Enter fullscreen mode Exit fullscreen mode

Response — Selective fields (fields=mx,disposable,role)

When you pass a fields parameter, only those checks run and only those fields are returned.
The response is clean — no null placeholders for checks that did not run.

{
  "email": "admin@mailinator.com",
  "result": "REJECT",
  "reason": "Disposable email detected via domain_list",
  "score": 25,
  "score_label": "Poor",
  "checks": {
    "syntax_valid": true,
    "mx_found": true,
    "mx_records": ["mail.mailinator.com"],
    "is_disposable": true,
    "disposable_method": "domain_list",
    "is_role_based": true
  },
  "latency_ms": 203
}
Enter fullscreen mode Exit fullscreen mode

Notice: no smtp fields, no email_auth, no intelligence, no suggestions — because none of those checks were requested. The response time is 203ms instead of 2-3 seconds.


Understanding Every Field

Top Level Fields

Field What It Means
email The email address you submitted
result The final verdict. See the Result Values table below.
reason A plain English explanation of why this result was given
score A number from 0 to 100 showing how trustworthy this email is
score_label A label for the score — Excellent, Good, Fair, Poor, or Very Poor
intelligence Extra analysis for suspicious unknown domains. Only present if intelligence was requested.
suggestions If the domain looks like a typo this shows the corrected version. Only present if typo was requested.
latency_ms How long the validation took in milliseconds
_unknown_fields Only present if you passed unrecognised field names. Lists them so you can fix your integration.

Result Values

Result What It Means What To Do
VALID Email passed all checks Accept it
REJECT Email definitively failed — fake, disposable, or non-existent Reject it
RISKY Email passed basic checks but has suspicious signals Flag for review or require email confirmation
UNKNOWN SMTP was inconclusive — server blocked the probe Allow but send a confirmation email

Score Guide

Score Label What To Do
80 to 100 Excellent Accept with confidence
60 to 79 Good Accept — minor concerns only
40 to 59 Fair Consider requiring email confirmation
20 to 39 Poor Flag for manual review
0 to 19 Very Poor Reject

The checks object — every field explained

syntax_valid — true means the email format is correct. false means it is not a properly formatted email at all — for example missing the @ symbol or having illegal characters. If this is false everything else is skipped.

mx_found — true means the domain is set up to receive emails. false means even if the email looks correct it can never receive any messages because the domain has no mail servers.

mx_records — The list of mail servers responsible for delivering email to this domain.
Multiple entries are normal — they are fallback servers listed in order of priority.
You do not need to act on this directly.

smtp_verified — The result of the live SMTP check. true means the mailbox was confirmed to exist on the mail server. false means it was confirmed to not exist. null means the check was skipped or the server blocked the probe — see smtp_skipped for why.

smtp_catch_all — true means the mail server accepts every email address regardless of whether the mailbox actually exists. This makes individual verification impossible for this domain. Do not outright reject these — flag them for manual review instead.

smtp_greylisted — true means the server temporarily rejected the SMTP probe using a technique called greylisting. The API automatically waits and retries when this happens.
If it is still true after retry it means the server is being cautious — not that the email is invalid.

smtp_skipped — true means SMTP verification was not performed. This happens for two reasons: either you used quick=true mode, or the domain belongs to a major provider like Gmail or Yahoo that blocks automated SMTP probing. When skipped the result is based on the other 11 checks.

is_disposable — true means this is a known throwaway email address. People use these to sign up without giving their real email. You should reject these.

disposable_method — How the disposable email was detected. Can be domain_list
(matched against 769,000+ known domains updated live from community blocklists),
keyword_match (domain contains a known disposable keyword), or mx_fingerprint
(mail server is known disposable infrastructure). null if the email is not disposable.

is_role_based — true means this is a shared inbox address like admin@, info@, support@, noreply@, sales@, or similar. Detection uses two layers: an exact match against 50+ known role prefixes, then fuzzy segment matching to catch variants like noreply2@, admin.team@, or support_dept@. For consumer apps and newsletters you should reject these. For B2B tools and contact forms they are perfectly legitimate.

is_sub_address — true means the email uses plus addressing like user+tag@gmail.com. This is a real technique used by legitimate users but also sometimes used to bypass duplicate email checks. The base address without the tag is the real mailbox.

is_free_provider — true means this is from a free email provider like Gmail, Yahoo, Hotmail, or Outlook. Detection uses two layers: a hardcoded list of 30+ known free providers, then MX fingerprinting to catch custom domains that route through the same infrastructure (e.g. a Google Workspace or O365 domain). Useful if your application requires a business email address. Has no impact on validity — Gmail addresses are
perfectly valid.

spam_trap_suspected — true means the email address matches known spam trap patterns like spamtrap@, honeypot@, or abuse@. These addresses are set up specifically to catch spammers. If you are seeing this on real user emails it means someone is entering fake data — reject it.

risky_tld — true means the domain uses a top-level domain statistically associated with spam and disposable email services. The check uses 53+ hardcoded TLDs (.xyz, .top, .click, .loan, etc.) plus a live-updated community list fetched at server startup. A risky TLD alone does not mean the email is invalid but it lowers the trust
score.

domain_entropy — A score from 0 to 100 measuring how pronounceable and human-like the domain name is. Higher is better. A score below 25 suggests the domain name may be randomly generated — a common characteristic of disposable email services. 25 or above is normal. You do not need to act on this field directly — it feeds into the overall score automatically.


The email_auth object

spf — true means the domain has an SPF record published. SPF lets domain owners declare which mail servers are allowed to send email on their behalf. Legitimate domains almost always have this configured.

spf_policy — How strictly SPF is enforced. strict means hard fail — unauthorized senders are rejected. softfail means soft fail — unauthorized senders are flagged but not necessarily rejected. neutral means no policy preference. null means no SPF record.

dmarc — true means the domain has a DMARC record. DMARC builds on SPF and tells receiving mail servers what to do with emails that fail authentication.

dmarc_policy — How the domain handles authentication failures. none means monitoring only — no action taken. quarantine means send suspicious emails to spam. reject means block them completely. null means no DMARC record exists.

dkim — true means the domain has DKIM signing keys published. DKIM is a digital signature system that proves an email actually came from the domain it claims to be from. false does not automatically mean the email is bad — many legitimate domains do not publish DKIM selectors publicly, including Gmail which manages DKIM internally.


The intelligence object

The intelligence engine runs additional analysis on domains that are not in the known disposable list. It checks domain age, how many other domains share the same mail server IP, the hosting provider reputation, and whether the domain has a real website. This catches brand new disposable email services before they appear in any blocklist.

intelligence.risk_score — A number from 0 to 100 representing how suspicious the domain appears based on infrastructure signals. Above 60 is flagged as likely disposable. 30 to 60 is considered risky.

intelligence.flags — A list of human readable reasons for the risk score. Examples are "Domain registered only 3 days ago", "MX IP shared by 800 domains — disposable infrastructure", or "No web presence detected". null means no red flags were found.

When intelligence is null it means the domain passed all infrastructure checks cleanly and no red flags were detected.


The suggestions object

suggestions.did_you_mean — If the domain looks like a common typo this field shows the corrected version. Uses two layers: a dictionary of known typos (e.g. gmial.comgmail.com), then Levenshtein fuzzy matching for variants not in the dictionary. For example user@gmial.com suggests user@gmail.com. null means no typo detected.


2. Validate Single Email via POST

POST /v1/validate

Identical to the GET endpoint but accepts the email in the request body.
Useful when you do not want the email address to appear in server logs or URLs.

Request Body:

{
  "email": "user@example.com",
  "fields": "mx,disposable,role",
  "quick": false
}
Enter fullscreen mode Exit fullscreen mode
Field Type Required Description
email string Yes The email address to validate
fields string No Comma-separated checks to run. Omit for all.
quick boolean No Skip SMTP if true

Response format is identical to the GET endpoint.


3. Bulk Validate Emails

POST /v1/validate/bulk

Validate multiple emails in one request. Much faster and more efficient than calling the single endpoint repeatedly. Ideal for cleaning existing email lists before sending campaigns.

Request Body:

{
  "emails": [
    "user@gmail.com",
    "fake@tempmail.com",
    "admin@example.com"
  ],
  "fields": "disposable,role",
  "quick": false
}
Enter fullscreen mode Exit fullscreen mode
Field Type Required Description
emails array Yes Array of email addresses to validate
fields string No Comma-separated checks to run. Omit for all.
quick boolean No Skip SMTP if true

Plan limits:

Plan Max emails per bulk call
BASIC (free) 5
PRO 50
ULTRA 100
MEGA 500

Response:

{
  "count": 3,
  "results": [
    {
      "email": "user@gmail.com",
      "result": "VALID",
      "reason": "All checks passed",
      "score": 100,
      "score_label": "Excellent",
      "checks": { "..." },
      "intelligence": null,
      "suggestions": null,
      "latency_ms": 1243
    },
    {
      "email": "fake@tempmail.com",
      "result": "REJECT",
      "reason": "Disposable email detected via domain_list",
      "score": 2,
      "score_label": "Very Poor",
      "checks": { "..." },
      "intelligence": { "risk_score": 85, "flags": ["..."] },
      "suggestions": null,
      "latency_ms": 312
    },
    {
      "email": "admin@example.com",
      "result": "RISKY",
      "reason": "Role-based address — low engagement, high spam risk",
      "score": 65,
      "score_label": "Good",
      "checks": { "..." },
      "intelligence": null,
      "suggestions": null,
      "latency_ms": 890
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode
Field What It Means
count How many emails were processed in this request
results An array with one full result per email in the same order you sent them

Each entry in results is the same response object as the single validate endpoint. If you passed a fields parameter, each result only contains the checks you requested.


4. List Available Fields

GET /v1/fields

Returns the complete list of all available field names with their speed estimates and what they return. Useful for building dynamic integrations or confirming field names.

No parameters needed.

{
  "available_fields": [
    { "field": "syntax",       "speed": "instant", "returns": ["checks.syntax_valid"] },
    { "field": "mx",           "speed": "~200ms",  "returns": ["mx_found", "mx_records"] },
    { "field": "smtp",         "speed": "~1-3s",   "returns": ["smtp_verified", "smtp_catch_all", "smtp_greylisted", "smtp_skipped"] },
    { "field": "disposable",   "speed": "instant", "returns": ["is_disposable", "disposable_method"] },
    { "field": "role",         "speed": "instant", "returns": ["is_role_based"] },
    { "field": "subaddress",   "speed": "instant", "returns": ["is_sub_address"] },
    { "field": "provider",     "speed": "instant", "returns": ["is_free_provider"] },
    { "field": "spamtrap",     "speed": "instant", "returns": ["spam_trap_suspected"] },
    { "field": "intelligence", "speed": "instant", "returns": ["risky_tld", "domain_entropy", "intelligence (top-level)"] },
    { "field": "auth",         "speed": "~300ms",  "returns": ["email_auth (spf, spf_policy, dmarc, dmarc_policy, dkim)"] },
    { "field": "typo",         "speed": "instant", "returns": ["suggestions (top-level)"] }
  ],
  "always_returned": ["email", "result", "reason", "score", "score_label", "latency_ms", "checks.syntax_valid"],
  "usage": "Pass ?fields=mx,disposable,auth — only those checks run. Omit for full validation."
}
Enter fullscreen mode Exit fullscreen mode

5. Health Check

GET /health

Check if the API is online. No parameters needed. Use this before making
bulk requests to confirm the service is running.

{
  "status": "ok",
  "version": "5.0.0",
  "ts": 1741267200000
}
Enter fullscreen mode Exit fullscreen mode
Field What It Means
status ok means everything is working normally
version The current version of the API
ts Current server timestamp in milliseconds

Quick Mode vs Full Mode vs Selective Fields

Mode How To Use Speed Best For
Full mode No params ~2-3s Maximum accuracy — all 11 fields run
Quick mode quick=true ~300ms Skip SMTP only, all other checks run
Selective fields fields=mx,disposable Depends on fields Run only what you need — fastest option
Selective + quick fields=smtp&quick=true ~300ms Selective without SMTP

The fields parameter is more powerful than quick=true alone. With fields you control exactly which checks execute. With quick=true you only skip SMTP — everything else still runs.

For real-time typing validation, fields=syntax,typo gives you instant feedback with near-zero latency. Then run fields=mx,disposable,role on submit for a thorough but fast check. Only use fields=smtp for high-value signups where confirming the mailbox is worth the extra 1-3 seconds.

How To Use The Results In Your Code

Simple accept or reject based on result:

const res = await fetch('/v1/validate?email=' + email, { headers });
const data = await res.json();

if (data.result === "VALID") {
  proceedWithSignup(email);
} else if (data.result === "RISKY" || data.result === "UNKNOWN") {
  sendConfirmationEmail(email); // allow but verify
} else {
  showError("Please enter a valid email address");
}
Enter fullscreen mode Exit fullscreen mode

Use the score for more nuanced decisions:

if (data.score >= 80) {
  acceptDirectly(email);
} else if (data.score >= 50) {
  requireEmailConfirmation(email);
} else {
  rejectSignup(email);
}
Enter fullscreen mode Exit fullscreen mode

Handle catch-all domains separately:

if (data.checks.smtp_catch_all) {
  // Cannot verify individual mailbox — allow but flag
  flagForManualReview(email);
} else if (data.result === "REJECT") {
  rejectSignup(email);
}
Enter fullscreen mode Exit fullscreen mode

Help users fix typos:

if (data.suggestions?.did_you_mean) {
  showMessage(`Did you mean ${data.suggestions.did_you_mean}?`);
}
Enter fullscreen mode Exit fullscreen mode

Require business email only:

if (data.checks.is_free_provider) {
  showError("Please use your business email address");
}
Enter fullscreen mode Exit fullscreen mode

Use selective fields for a fast signup form:

// Only run mx + disposable + role — responds in ~200ms
const res = await fetch(
  '/v1/validate?email=' + email + '&fields=mx,disposable,role',
  { headers }
);
const data = await res.json();
if (data.checks.is_disposable) showError("Disposable emails not allowed");
if (data.checks.is_role_based) showError("Please use a personal email address");
if (!data.checks.mx_found) showError("This email domain does not exist");
Enter fullscreen mode Exit fullscreen mode

Clean an email list before sending a campaign:

const { data } = await bulkValidate(emailList, { fields: "disposable,role,spamtrap" });
const cleanList = data.results
  .filter(r => r.result === "VALID" && r.score >= 70)
  .map(r => r.email);
Enter fullscreen mode Exit fullscreen mode

Recommended Combinations By Use Case

Use Case fields= Speed Why
Signup form mx,disposable,role ~200ms Blocks the most common bad emails, no SMTP wait
Real-time typing syntax,typo ~0ms Instant format + typo correction as user types
Email marketing list clean disposable,spamtrap,role,mx ~200ms Removes all bad senders before a campaign
Security audit auth,intelligence ~300ms SPF/DMARC/DKIM + domain reputation
High-value lead verification mx,smtp,disposable ~1-3s Full SMTP mailbox confirmation
Business email gate provider,syntax ~0ms Block free providers instantly
Bulk list cleaning disposable ~0ms In-memory lookup — instant even for thousands

Honest Limitations

We believe in being upfront about what this API can and cannot do.
Major providers like Gmail, Yahoo, Outlook, iCloud, and ProtonMail block automated SMTP probing. For these domains smtp_skipped will be true and smtp_verified will be null. The result is still based on the other 11 checks and is reliable for detecting obvious fakes and disposable patterns — but we cannot confirm whether a specific Gmail mailbox exists.

Catch-all domains accept every email address regardless of whether the individual mailbox exists. smtp_catch_all will be true for these. We cannot tell you if a specific address on that domain is real — we recommend flagging these for manual review rather than outright rejecting.

No email validator guarantees 100% accuracy. Some valid emails will occasionally score lower than expected due to server timeouts, temporary DNS issues, or conservative server configurations. Use the result and score together to make decisions, and always give users a way to receive a confirmation email if they believe their address is valid.

We do our best across 11 fields but we are not the only option and may not be perfect for every use case. Test on the free tier first to confirm it meets your needs.

Every live data source has a hardcoded fallback built in. If the
disposable blocklist fetch fails, 769,000+ built-in domains still run.
If the risky TLD live fetch fails, 53 hardcoded TLDs still fire. If MX
fingerprinting cannot resolve, the hardcoded provider list covers all
major cases. The API never returns an error due to a failed external
fetch — it degrades gracefully and silently to its hardcoded layer.

FAQ

Is this GDPR compliant?

Yes. Email addresses submitted for validation are never stored, logged, or shared with any third party. Every request is processed in memory and discarded immediately after the response is sent.

Why is smtp_verified null for Gmail addresses?

Gmail and other major providers block automated SMTP verification by design — they return 250 for every address regardless of whether it exists, making the check useless. We detect this and skip SMTP for these providers, marked by smtp_skipped: true. The result is still based on 11 other checks and is reliable.

What is the fields parameter?

It lets you specify exactly which checks to run. Only those checks execute — the rest are skipped entirely. This means the response time depends on what you ask for. Asking for just disposable takes under 10ms. Asking for smtp takes 1-3 seconds. Pass fields=mx,disposable,role for a fast signup form check, or omit fields entirely for full validation.

What is a catch-all domain?

Some domains are configured to accept every email address regardless of whether the individual mailbox actually exists. smtp_catch_all: true indicates this. We recommend flagging these for manual review and sending a confirmation email rather than rejecting.

What does is_sub_address mean?

It means the email uses plus addressing — for example user+newsletter@gmail.com. This is a real technique where email goes to the base address (user@gmail.com). Some users do this to track who shares their email. It is valid but worth knowing about.

How often is the disposable domain list updated?

The list is fetched from live community blocklists every time the server starts. The 769,000+ domain fallback is always available even if the live fetch fails. New disposable services are typically picked up within hours of being added to community sources.

What does the intelligence object tell me?

It runs deeper analysis on unknown domains — checking how old the domain is, how many other domains share its mail server, the reputation of its hosting provider, and whether it has a real website. A domain registered 3 days ago with 800 other domains on the same IP and no website is almost certainly a disposable email service even if it is not in any blocklist yet.

Should I reject RISKY emails outright?

Not necessarily. RISKY means there are signals worth noting but nothing definitive. The best approach is to allow the signup but send a confirmation email — if they can confirm it the address is real enough to use.

What is domain_entropy?

It is a measure of how pronounceable and human-like the domain name is. Randomly generated domains like xk7mq2p.com score very low. Real business domains and well known providers score high. It feeds into the overall score automatically — you do not need to check it directly.

What happens if I pass an unknown field name?

The API runs the valid field names you provided and returns the unrecognised ones in _unknown_fields. So fields=mx,typo,fakething would run mx and typo normally, and return "_unknown_fields": ["fakething"] in the response so you can fix your integration.

Top comments (0)