DISIFY API Documentation

Email validation API with disposable detection, DNS/MX validation, SPF/DKIM/DMARC checks, domain age, deliverability scoring, and more. Free tier available — no API key required.

Email Validation

Check email format, DNS/MX records, and detect disposable addresses in one call.

Domain Check

Validate domain names directly without needing a full email address.

Bulk Validation

Validate multiple email addresses or domains in a single request. Limits scale with your tier (10,000 anonymous, higher on paid plans).

62,000+ Blocked Domains

Continuously updated blacklist with multi-layer detection including MX server matching.

Quick Start

No signup or API key needed. Make your first request in seconds:

curl https://disify.com/api/email/[email protected]
import requests

response = requests.get("https://disify.com/api/email/[email protected]")
data = response.json()

if data.get("disposable"):
    print("Disposable email detected!")
else:
    print("Email looks legitimate.")
const response = await fetch("https://disify.com/api/email/[email protected]");
const data = await response.json();

if (data.disposable) {
    console.log("Disposable email detected!");
} else {
    console.log("Email looks legitimate.");
}
$response = file_get_contents("https://disify.com/api/email/[email protected]");
$data = json_decode($response, true);

if ($data['disposable']) {
    echo "Disposable email detected!";
} else {
    echo "Email looks legitimate.";
}

Example response:

JSON Response
{
    "format": true,
    "domain": "gmail.com",
    "disposable": false,
    "dns": true,
    "confidence": 0,
    "whitelist": true,
    "domain_info": {
        "tld": "com",
        "is_subdomain": false,
        "parent_domain": null
    },
    "mx_info": [
        "gmail-smtp-in.l.google.com",
        "alt1.gmail-smtp-in.l.google.com"
    ],
    "role": false,
    "free": true
}

Base URL

All API requests use the following base URL:

https://disify.com/api

The API returns application/json responses for all endpoints. CORS is enabled, so you can make requests directly from the browser.

Rate Limiting

To keep the service available for everyone, requests are rate-limited per IP (anonymous) or per API key (authenticated).

TierRate Limit
Anonymous30/min per IP, 1,000/day per IP
Free (account)60/min per key, 30,000/month
Starter120/min per key
Pro500/min per key

Rate limit headers are included in every response:

💡
Don't skip popular providers. We detect temp-mail services that hand out plus-aliases on real Gmail, Outlook, and iCloud mailboxes (e.g. [email protected] is flagged disposable). If you skip these domains client-side, you'll miss this class of abuse. Cache by domain, not by full email — the whitelist: true response field is a safe domain-level cache key.

Authentication

The API works without authentication for core features. For higher monthly limits, API keys, and premium features, create a free account and use an API key.

API Key

Pass your API key in the X-Api-Key header or Authorization: Bearer header:

# X-Api-Key header
curl -H "X-Api-Key: YOUR_API_KEY" https://disify.com/api/email/[email protected]

# Authorization Bearer header
curl -H "Authorization: Bearer YOUR_API_KEY" https://disify.com/api/email/[email protected]

Usage tiers

TierRate LimitBulk LimitFeatures
Anonymous (no key)30/min, 1,000/day10,000Core features
Free (with account)60/min, 30,000/month12,000Core features + API keys
Starter ($9/mo)120/min25,000Core features with higher limits
Pro ($19/mo)500/min100,000All features (SPF/DKIM/DMARC, domain age, deliverability, spam-trap, inbox provider)

See pricing for full details and credit packs.

Premium Features

Request premium features by adding them to the URL path or as a features parameter. If your tier doesn't include a requested feature, the response will contain a requires_upgrade array listing the denied features.

# Request SPF and DKIM checks via URL path
curl -H "X-Api-Key: YOUR_KEY" https://disify.com/api/email/[email protected]/spf/dkim

# Request multiple features via query parameter
curl -H "X-Api-Key: YOUR_KEY" "https://disify.com/api/email/[email protected]?features=spf,dkim,dmarc"

Available premium features

FeatureTierResponse keyDescription
spfProemail_auth.spfSPF record validation (pass, softfail, hardfail, none)
dkimProemail_auth.dkim_configuredDKIM selector check (true/false + selectors found)
dmarcProemail_auth.dmarcDMARC policy (reject, quarantine, none, absent)
domain_ageProdomain_ageDomain registration date and age in days
inbox_providerProinbox_providerEmail provider name (Google Workspace, Microsoft 365, etc.)
deliverabilityProdeliverability_scoreDeliverability score 0–100 based on auth records and domain age

spam_trap detection is automatically included for Pro tier users — no need to request it.

Pro tier response example

{
    "format": true,
    "domain": "example.com",
    "disposable": false,
    "dns": true,
    "confidence": 0,
    "domain_info": {
        "tld": "com",
        "is_subdomain": false,
        "parent_domain": null
    },
    "mx_info": ["mx1.example.com", "mx2.example.com"],
    "spam_trap": {
        "is_trap": false,
        "type": null,
        "reason": null
    },
    "email_auth": {
        "spf": "pass",
        "spf_record": "v=spf1 include:_spf.google.com ~all",
        "dmarc": {
            "policy": "reject",
            "record": "v=DMARC1; p=reject; rua=mailto:[email protected]",
            "subdomain_policy": "quarantine",
            "pct": 100,
            "rua": "mailto:[email protected]"
        },
        "dkim_configured": true,
        "dkim_selectors_found": ["google", "selector1"]
    },
    "domain_age": {
        "registered": "2015-06-01",
        "age_days": 3848,
        "fresh": false
    },
    "inbox_provider": "Google Workspace",
    "deliverability_score": 100,
    "role": false,
    "free": false
}

Single Email Check

Validates a single email address. Checks format, DNS/MX records, and whether the domain is a known disposable email provider.

GET Request

GET /api/email/{email}
Example
curl https://disify.com/api/email/[email protected]

POST Request

POST /api/email

Send the email address as a form parameter:

curl -X POST https://disify.com/api/email \
     -d "[email protected]"
import requests

response = requests.post("https://disify.com/api/email", data={
    "email": "[email protected]"
})
print(response.json())
const response = await fetch("https://disify.com/api/email", {
    method: "POST",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    body: "[email protected]"
});
const data = await response.json();
$ch = curl_init("https://disify.com/api/email");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, "[email protected]");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
curl_close($ch);

$data = json_decode($response, true);

POST Parameters

ParameterTypeDescription
emailstringThe email address to validate

Response for a disposable email:

Disposable Detected
{
    "format": true,
    "domain": "tempmail.com",
    "disposable": true,
    "dns": true,
    "confidence": 100,
    "domain_info": {
        "tld": "com",
        "is_subdomain": false,
        "parent_domain": null
    },
    "mx_info": ["mx1.tempmail.com"],
    "signals": [
        "keyword_match",
        "mx_blacklist_exact"
    ],
    "role": false,
    "free": false
}

Response for a legitimate email:

Valid Email
{
    "format": true,
    "domain": "gmail.com",
    "disposable": false,
    "dns": true,
    "confidence": 0,
    "whitelist": true,
    "domain_info": {
        "tld": "com",
        "is_subdomain": false,
        "parent_domain": null
    },
    "mx_info": [
        "gmail-smtp-in.l.google.com",
        "alt1.gmail-smtp-in.l.google.com"
    ],
    "role": false,
    "free": true
}

Domain Check

Check a domain name directly, without needing a full email address. Uses the same detection engine.

GET /api/domain/{domain}
POST /api/domain
Example
curl https://disify.com/api/domain/guerrillamail.com

POST Parameters

ParameterTypeDescription
domainstringThe domain name to validate
ℹ️
Use either email or domain parameter — not both. The domain endpoint strips the local part and only checks the domain.

Bulk Validation

Validate multiple email addresses or domains in a single request. Per-request limits depend on your tier (10,000 anonymous → 100,000 on Pro — see Authentication).

GET /api/email/{emails}/mass
POST /api/email

GET Request

Pass comma-separated emails directly in the URL with the /mass suffix:

Example
curl "https://disify.com/api/email/[email protected],[email protected]/mass"

POST Request

Send the bulk parameter alongside comma-separated emails:

curl -X POST https://disify.com/api/email \
     -d "bulk=true" \
     -d "[email protected],[email protected],[email protected]"
import requests

response = requests.post("https://disify.com/api/email", data={
    "bulk": True,
    "email": "[email protected],[email protected],[email protected]"
})
print(response.json())
$ch = curl_init("https://disify.com/api/email");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
    "bulk"  => true,
    "email" => "[email protected],[email protected],[email protected]"
]));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
curl_close($ch);

$data = json_decode($response, true);

POST Parameters

ParameterTypeDescription
bulkbooleanRequired. Set to true to enable bulk mode.
emailstringComma, space, or newline-separated list of email addresses.
domainstringAlternative: comma-separated list of domain names.
jsonbooleanOptional. When set, the response additionally includes a results map of email → validation result so you don't need a second call to /api/view/{session}. Only available for small synchronous batches (≤ 500 addresses).

Bulk Response

JSON Response
{
    "total": 3,
    "invalid_format": 0,
    "invalid_dns": 0,
    "disposable": 1,
    "unique": 3,
    "valid": 2,
    "session": "d117271ce938bf91bc718f6cfb7954de"
}

Bulk Response Fields

FieldTypeDescription
totalintTotal number of entries submitted
invalid_formatintCount of entries with invalid format
invalid_dnsintCount of entries with unresolvable MX records
disposableintCount of entries detected as disposable
uniqueintCount of unique valid entries
validintCount of valid (non-disposable) entries
sessionstringSession hash to retrieve valid results

View Bulk Results

After a bulk validation, use the session hash to retrieve the list of valid email addresses. The response body is plain text — one valid address per line by default.

GET /api/view/{session}
Example
curl https://disify.com/api/view/d117271ce938bf91bc718f6cfb7954de

Optional Suffixes

SuffixEffect
/downloadForces a file download (sets Content-Disposition: inline; filename="valid_list.txt" and application/octet-stream).
/separator (also /separate, /comma)Returns results as comma-separated on a single line instead of newline-separated.

You can combine suffixes in any order:

With options
# Comma-separated + download
curl https://disify.com/api/view/d117271ce938bf91bc718f6cfb7954de/separator/download
💡
Want per-email results (not just the valid list)? Pass json=1 on the initial bulk submit — the response includes a results map of email → validation. See Bulk Validation.
⚠️
Session results are temporary and expire after 1 hour. Retrieve and store your results promptly after bulk validation.

Async bulk jobs (> 500 emails)

Bulk requests under 500 unique addresses are processed synchronously and return the stats response immediately. Larger batches are queued and return a pending response:

Pending response (queued job)
{
    "session": "d117271ce938bf91bc718f6cfb7954de",
    "status": "pending",
    "email_count": 8000,
    "estimated_seconds": 32
}

Poll GET /api/view/{session} for progress. While still running, the same endpoint returns JSON with a status of pending, processing, or failed:

Progress response
{
    "session": "d117271ce938bf91bc718f6cfb7954de",
    "status": "processing",
    "email_count": 8000,
    "processed_count": 3200
}

Once status: "completed", the endpoint returns the plain-text valid list (with the suffix options above). If you configured a webhook on your account, you'll also receive a bulk.completed event with the final stats.

⚠️
Only one async job per API key (or IP for anonymous users) may run at a time. Anonymous users must wait 30 seconds between jobs.

Response Fields

Every single email/domain check returns a JSON object with the following fields:

FieldTypeDescription
format bool Whether the email has a valid format (syntax check)
alias bool Whether the email contains a + alias (e.g., [email protected]). Only present when true. Note: plus-aliases on Gmail/Outlook/Hotmail/Live/MSN/iCloud are additionally checked against a list of known temp-mail base accounts — see plus-alias detection.
domain string The extracted domain from the email address
disposable bool Whether the domain is detected as a disposable/temporary email provider
dns bool Whether the domain has valid MX records
whitelist bool Whether the domain is on our trusted provider whitelist. Only present when true.
role bool Whether the email uses a role-based prefix (e.g., info@, support@, admin@). Always false for domain-only checks.
free bool Whether the domain is a known free email provider (e.g., Gmail, Yahoo, Outlook)
confidence int Confidence score (0–100) of the disposable detection. See Confidence Scoring.
signals array Detection signals that triggered the disposable flag. Only present when disposable. See below.
typo_suggestion string Typo correction suggestion for common domain misspellings (e.g., gmial.comgmail.com). Only present when a typo is detected. Email mode only.
domain_info object Domain metadata: tld (string), is_subdomain (bool), parent_domain (string|null).
mx_info array List of MX hostnames for the domain. Only present when MX records exist.
requires_upgrade array List of requested premium features not available on your current plan. Only present when features are denied. See Premium Features.
ℹ️
Fields like alias, whitelist, signals, typo_suggestion, and premium feature fields are only included when relevant. If a field is absent, treat it as false / empty. Premium features (email_auth, domain_age, inbox_provider, deliverability_score, spam_trap) are only included when your tier supports them and you've requested them.

Detection Signals

When disposable is true, the signals array explains which detection layers matched:

SignalDescription
blacklist_exactDomain found in the exact domain blacklist
blacklist_parentA parent domain is blacklisted (subdomain walk-up match)
mx_blacklist_exactMX hostname found in the MX blacklist
mx_blacklist_parentA parent of the MX hostname is blacklisted
mx_ip_blacklistMX server IP address found in the MX blacklist
keyword_matchDomain name contains suspicious keywords (temp, disposable, throwaway, etc.)
pattern_heuristicEmail matches suspicious patterns (tmp+, .tmp, excessive dots)
high_entropyDomain appears randomly generated based on character entropy analysis
high_entropy_suspicious_tldHigh entropy domain combined with a suspicious TLD
suspicious_tldDomain uses a TLD commonly associated with disposable services
no_mx_recordsDomain has no MX records configured
fresh_domainDomain was registered recently (within 30 days). Requires domain_age feature.
alias_base_exactEmail's canonical form (plus-alias stripped, Gmail dots stripped) matches a known temp-mail base account on Gmail, Outlook, Hotmail, Live, MSN, or iCloud. See plus-alias detection.

Confidence Scoring

The confidence field (0–100) indicates how certain DISIFY is that the domain is disposable:

ScoreMeaningTypical Signals
0Not disposableNo signals triggered
15–20Low suspicionsuspicious_tld, high_entropy
25–35Moderate suspicionfresh_domain, no_mx_records
50Likely disposablehigh_entropy_suspicious_tld (threshold reached)
60Probably disposablepattern_heuristic
80Very likely disposablekeyword_match
90–100Confirmed disposableblacklist_exact, blacklist_parent, mx_blacklist_exact, mx_ip_blacklist
💡
For most use cases, checking "disposable": true is sufficient. Use the confidence score when you want finer control — for example, only blocking confidence ≥ 90 to avoid false positives from heuristic detection.

Plus-alias Temp-Mail Detection

A growing class of temp-mail services hands out plus-aliases on real Gmail, Outlook, Hotmail, Live, MSN, and iCloud mailboxes instead of running their own domain. Every alias routes to the same physical inbox, which the service scrapes. Because the base mailbox is a legitimate provider, checking the domain alone is not enough.

Disify keeps a list of known base accounts and canonicalizes every email before comparing:

If the canonical form matches a known base account, the response is:

Flagged plus-alias example
{
    "format": true,
    "alias": true,
    "domain": "gmail.com",
    "disposable": true,
    "dns": true,
    "whitelist": true,
    "confidence": 100,
    "signals": ["alias_base_exact"]
}
💡
Because the check runs after the domain-level whitelist, you will occasionally see "whitelist": true alongside "disposable": true. The whitelist applies to the base domain; the alias override applies to the specific address. Trust disposable as the final verdict.

Error Handling

If the request is malformed or missing required parameters, the API returns an error object:

Error Response
{
    "error": "Invalid request"
}

Common error scenarios:

Blacklists

DISIFY maintains two public blacklists that power the detection engine:

BlacklistEntriesDescription
Domain Blacklist 62,000+ Known disposable email domains. Checked via exact match and subdomain walk-up.
MX Blacklist 900+ Mail server hostnames and IPs used by disposable email services.

The MX blacklist catches disposable services that rotate domains but continue using the same mail servers — providing an additional layer of detection beyond simple domain matching.

Community Submissions

Help improve DISIFY's blacklist by submitting domains you've identified as disposable, or requesting removal of domains that were incorrectly flagged:

Tips & Best Practices

  1. Cache by domain, not by email — Domain-level disposable status rarely changes, so caching the result keyed on the domain is safe for 24h+. Don't cache per-email on gmail.com / outlook.com / icloud.com and friends — we run per-email plus-alias checks on those (see below).
  2. Always check every email, including popular providers — We detect temp-mail services that ride on real Gmail/Outlook/iCloud mailboxes using plus-alias (and Gmail's dot-trick). Skipping Gmail/Outlook/Yahoo client-side will miss these. Use the whitelist: true response flag if you want to treat trusted-domain results more leniently, but still run the call.
  3. Use the confidence score — For critical flows (e.g., account registration), you may want to only block confidence ≥ 90. For less critical checks, blocking any disposable: true is fine.
  4. Check dns too — A domain that isn't disposable but has no MX records ("dns": false) can't receive email either.
  5. Handle missing fields gracefully — Optional fields like alias, whitelist, and signals are omitted when not applicable. Always check for existence before reading.
  6. Combine with your own checks — DISIFY handles disposable detection, DNS validation, and advanced email authentication checks (Pro). You should still validate that the email format is correct on your end.

Questions or issues? Open an issue on GitHub or submit feedback.