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:
{
"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:
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).
| Tier | Rate Limit |
|---|---|
| Anonymous | 30/min per IP, 1,000/day per IP |
| Free (account) | 60/min per key, 30,000/month |
| Starter | 120/min per key |
| Pro | 500/min per key |
Rate limit headers are included in every response:
X-RateLimit-Limit— your per-minute limitX-RateLimit-Remaining— requests remaining in the current window
- Exceeding the limit returns
429 Too Many Requests. - Sustained abusive traffic may result in an automatic IP ban.
- Consider caching results on your side for domains you check frequently.
[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
| Tier | Rate Limit | Bulk Limit | Features |
|---|---|---|---|
| Anonymous (no key) | 30/min, 1,000/day | 10,000 | Core features |
| Free (with account) | 60/min, 30,000/month | 12,000 | Core features + API keys |
| Starter ($9/mo) | 120/min | 25,000 | Core features with higher limits |
| Pro ($19/mo) | 500/min | 100,000 | All 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
| Feature | Tier | Response key | Description |
|---|---|---|---|
spf | Pro | email_auth.spf | SPF record validation (pass, softfail, hardfail, none) |
dkim | Pro | email_auth.dkim_configured | DKIM selector check (true/false + selectors found) |
dmarc | Pro | email_auth.dmarc | DMARC policy (reject, quarantine, none, absent) |
domain_age | Pro | domain_age | Domain registration date and age in days |
inbox_provider | Pro | inbox_provider | Email provider name (Google Workspace, Microsoft 365, etc.) |
deliverability | Pro | deliverability_score | Deliverability 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
curl https://disify.com/api/email/[email protected]
POST Request
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
| Parameter | Type | Description |
|---|---|---|
email | string | The email address to validate |
Response for a disposable email:
{
"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:
{
"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.
curl https://disify.com/api/domain/guerrillamail.com
POST Parameters
| Parameter | Type | Description |
|---|---|---|
domain | string | The domain name to validate |
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 Request
Pass comma-separated emails directly in the URL with the /mass suffix:
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
| Parameter | Type | Description |
|---|---|---|
bulk | boolean | Required. Set to true to enable bulk mode. |
email | string | Comma, space, or newline-separated list of email addresses. |
domain | string | Alternative: comma-separated list of domain names. |
json | boolean | Optional. 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
{
"total": 3,
"invalid_format": 0,
"invalid_dns": 0,
"disposable": 1,
"unique": 3,
"valid": 2,
"session": "d117271ce938bf91bc718f6cfb7954de"
}
Bulk Response Fields
| Field | Type | Description |
|---|---|---|
total | int | Total number of entries submitted |
invalid_format | int | Count of entries with invalid format |
invalid_dns | int | Count of entries with unresolvable MX records |
disposable | int | Count of entries detected as disposable |
unique | int | Count of unique valid entries |
valid | int | Count of valid (non-disposable) entries |
session | string | Session 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.
curl https://disify.com/api/view/d117271ce938bf91bc718f6cfb7954de
Optional Suffixes
| Suffix | Effect |
|---|---|
/download | Forces 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:
# Comma-separated + download
curl https://disify.com/api/view/d117271ce938bf91bc718f6cfb7954de/separator/download
json=1 on the initial bulk submit — the response includes a results map of email → validation. See 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:
{
"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:
{
"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.
Response Fields
Every single email/domain check returns a JSON object with the following fields:
| Field | Type | Description |
|---|---|---|
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.com → gmail.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. |
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:
| Signal | Description |
|---|---|
blacklist_exact | Domain found in the exact domain blacklist |
blacklist_parent | A parent domain is blacklisted (subdomain walk-up match) |
mx_blacklist_exact | MX hostname found in the MX blacklist |
mx_blacklist_parent | A parent of the MX hostname is blacklisted |
mx_ip_blacklist | MX server IP address found in the MX blacklist |
keyword_match | Domain name contains suspicious keywords (temp, disposable, throwaway, etc.) |
pattern_heuristic | Email matches suspicious patterns (tmp+, .tmp, excessive dots) |
high_entropy | Domain appears randomly generated based on character entropy analysis |
high_entropy_suspicious_tld | High entropy domain combined with a suspicious TLD |
suspicious_tld | Domain uses a TLD commonly associated with disposable services |
no_mx_records | Domain has no MX records configured |
fresh_domain | Domain was registered recently (within 30 days). Requires domain_age feature. |
alias_base_exact | Email'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:
| Score | Meaning | Typical Signals |
|---|---|---|
| 0 | Not disposable | No signals triggered |
| 15–20 | Low suspicion | suspicious_tld, high_entropy |
| 25–35 | Moderate suspicion | fresh_domain, no_mx_records |
| 50 | Likely disposable | high_entropy_suspicious_tld (threshold reached) |
| 60 | Probably disposable | pattern_heuristic |
| 80 | Very likely disposable | keyword_match |
| 90–100 | Confirmed disposable | blacklist_exact, blacklist_parent, mx_blacklist_exact, mx_ip_blacklist |
"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:
- Lowercase the local-part and domain.
- Strip everything from
+to@(the plus-alias tag). - Map
googlemail.com→gmail.com. - For
gmail.comonly: remove dots from the local-part (Google's documented policy). - Microsoft (outlook/hotmail/live/msn) and Apple (icloud/me/mac) treat dots as literal — dots are not stripped.
If the canonical form matches a known base account, the response is:
{
"format": true,
"alias": true,
"domain": "gmail.com",
"disposable": true,
"dns": true,
"whitelist": true,
"confidence": 100,
"signals": ["alias_base_exact"]
}
"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": "Invalid request"
}
Common error scenarios:
- No email/domain parameter — the
emailordomainfield is missing or empty. - Invalid format —
"format": falseis returned instead of an error. The response still includes other fields. - Rate limited — Too many requests. Slow down and retry after a brief pause.
Blacklists
DISIFY maintains two public blacklists that power the detection engine:
| Blacklist | Entries | Description |
|---|---|---|
| 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:
- Submit or request removal directly on the website.
- All submissions are manually reviewed before being applied.
- Frequently submitted domains are prioritized for review.
Tips & Best Practices
- 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).
- 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: trueresponse flag if you want to treat trusted-domain results more leniently, but still run the call. - Use the
confidencescore — For critical flows (e.g., account registration), you may want to only block confidence ≥ 90. For less critical checks, blocking anydisposable: trueis fine. - Check
dnstoo — A domain that isn't disposable but has no MX records ("dns": false) can't receive email either. - Handle missing fields gracefully — Optional fields like
alias,whitelist, andsignalsare omitted when not applicable. Always check for existence before reading. - 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.