Validate email addresses with DNS/MX lookup, disposable detection, and typo suggestions. Batch validation support. Free tier.
Bad email addresses cost businesses real money. Bounced emails damage sender reputation, inflate marketing costs, and create friction in user onboarding. An email validation API catches invalid, disposable, and risky email addresses before they enter your system — at the point of signup, form submission, or list import.
The DevProToolkit Email Validation API performs six layers of validation in a single request: syntax checking, DNS verification, MX record lookup, disposable email detection, role-based address detection, and intelligent typo suggestions. This guide covers the full API, with working code examples in cURL, Python, and JavaScript.
Validate any email address right now — no API key required for the playground.
Open Email Validation PlaygroundEmail validation is the process of verifying that an email address is properly formatted, belongs to a real domain, and is likely to receive messages. It goes far beyond checking for an @ symbol. Here is why it matters:
user@gmial.com or user@yahooo.com and suggests corrections, preventing lost customers who mistyped their email.info@, admin@, and support@ are shared inboxes that rarely belong to real individuals. Flagging these helps you maintain a high-quality contact list.Each API call performs all six checks and returns the results in a single response:
Checks that the email address conforms to the RFC 5322 standard — correct format, valid characters, proper use of dots and special characters, no leading or trailing spaces. This catches obviously malformed addresses like user@@domain or user@.com.
Verifies that the domain portion of the email address (everything after the @) has valid DNS records. If the domain does not exist or has no DNS entries, the email address cannot be valid.
Goes a step further than DNS by checking specifically for MX (Mail Exchange) records. MX records tell the internet which servers handle email for a domain. A domain can have valid DNS but no MX records, meaning it cannot receive email.
Checks the domain against a continuously updated database of known disposable email providers — services like Mailinator, Guerrilla Mail, TempMail, 10MinuteMail, and hundreds more. These addresses are temporary and typically used to bypass registration requirements.
Identifies addresses that are associated with a role or department rather than a specific person. Common role-based prefixes include: admin@, info@, support@, sales@, webmaster@, noreply@, and postmaster@. These addresses are shared and often have lower engagement rates.
Analyzes the domain for common misspellings and suggests corrections. For example, user@gmial.com returns a suggestion of user@gmail.com, and user@yaho.com suggests user@yahoo.com. This helps users fix mistakes before submitting forms.
curl "https://api.commandsector.in/api/email/validate/user@example.com" \
-H "X-API-Key: YOUR_API_KEY"
The response tells you everything you need to know:
{
"email": "user@example.com",
"is_valid": true,
"syntax_valid": true,
"domain_exists": true,
"mx_records": true,
"is_disposable": false,
"is_role_based": false,
"suggested_correction": null,
"domain": "example.com",
"local_part": "user",
"mx_hosts": ["mx1.example.com", "mx2.example.com"]
}
GET /api/email/validate/{email}
Path parameters:
| Parameter | Type | Description |
|---|---|---|
email | string | The email address to validate (URL-encoded if necessary) |
Authentication: Pass your API key via the X-API-Key header or as a ?api_key= query parameter.
Response: JSON object with all validation results (see response object reference below).
POST /api/email/batch
Request body (JSON):
{
"emails": [
"user1@gmail.com",
"user2@yahoo.com",
"fake@mailinator.com",
"typo@gmial.com"
]
}
Response: JSON object containing an array of validation results, one for each email in the input list.
Every validation response includes the following fields:
| Field | Type | Description |
|---|---|---|
email | string | The email address that was validated |
is_valid | boolean | Overall validity verdict — true if the email passes syntax, DNS, and MX checks |
syntax_valid | boolean | Whether the email format conforms to RFC 5322 |
domain_exists | boolean | Whether the domain has valid DNS records |
mx_records | boolean | Whether the domain has MX records (can receive email) |
is_disposable | boolean | Whether the domain is a known disposable email provider |
is_role_based | boolean | Whether the address is a role-based address (admin@, info@, etc.) |
suggested_correction | string|null | A suggested correction if a typo is detected, or null if no typo found |
domain | string | The domain portion of the email address |
local_part | string | The local portion (before the @) of the email address |
mx_hosts | array | List of MX hostnames for the domain |
{
"email": "developer@gmail.com",
"is_valid": true,
"syntax_valid": true,
"domain_exists": true,
"mx_records": true,
"is_disposable": false,
"is_role_based": false,
"suggested_correction": null,
"domain": "gmail.com",
"local_part": "developer",
"mx_hosts": ["gmail-smtp-in.l.google.com"]
}
{
"email": "throwaway@mailinator.com",
"is_valid": true,
"syntax_valid": true,
"domain_exists": true,
"mx_records": true,
"is_disposable": true,
"is_role_based": false,
"suggested_correction": null,
"domain": "mailinator.com",
"local_part": "throwaway",
"mx_hosts": ["mail.mailinator.com"]
}
{
"email": "john@gmial.com",
"is_valid": false,
"syntax_valid": true,
"domain_exists": false,
"mx_records": false,
"is_disposable": false,
"is_role_based": false,
"suggested_correction": "john@gmail.com",
"domain": "gmial.com",
"local_part": "john",
"mx_hosts": []
}
{
"email": "support@acme-corp.com",
"is_valid": true,
"syntax_valid": true,
"domain_exists": true,
"mx_records": true,
"is_disposable": false,
"is_role_based": true,
"suggested_correction": null,
"domain": "acme-corp.com",
"local_part": "support",
"mx_hosts": ["mx.acme-corp.com"]
}
{
"email": "not-an-email",
"is_valid": false,
"syntax_valid": false,
"domain_exists": false,
"mx_records": false,
"is_disposable": false,
"is_role_based": false,
"suggested_correction": null,
"domain": null,
"local_part": null,
"mx_hosts": []
}
curl "https://api.commandsector.in/api/email/validate/user@gmail.com" \
-H "X-API-Key: YOUR_API_KEY"
curl "https://api.commandsector.in/api/email/validate/temp@guerrillamail.com" \
-H "X-API-Key: YOUR_API_KEY"
curl "https://api.commandsector.in/api/email/validate/john@yahooo.com" \
-H "X-API-Key: YOUR_API_KEY"
curl -X POST "https://api.commandsector.in/api/email/batch" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"emails": [
"valid@gmail.com",
"fake@mailinator.com",
"admin@example.com",
"typo@gmial.com",
"bad@@syntax"
]
}'
curl "https://api.commandsector.in/api/email/validate/user@example.com?api_key=YOUR_API_KEY"
import requests
API_KEY = "YOUR_API_KEY"
BASE_URL = "https://api.commandsector.in"
def validate_email(email):
"""Validate an email address and return the result."""
response = requests.get(
f"{BASE_URL}/api/email/validate/{email}",
headers={"X-API-Key": API_KEY}
)
return response.json()
# Validate an email
result = validate_email("user@gmail.com")
print(f"Email: {result['email']}")
print(f"Valid: {result['is_valid']}")
print(f"Disposable: {result['is_disposable']}")
print(f"Role-based: {result['is_role_based']}")
print(f"MX Records: {result['mx_records']}")
if result.get('suggested_correction'):
print(f"Did you mean: {result['suggested_correction']}?")
import requests
from django.http import JsonResponse
from django.views.decorators.http import require_POST
API_KEY = "YOUR_API_KEY"
BASE_URL = "https://api.commandsector.in"
@require_POST
def register(request):
"""User registration endpoint with email validation."""
email = request.POST.get("email", "").strip().lower()
password = request.POST.get("password", "")
if not email or not password:
return JsonResponse({"error": "Email and password are required"}, status=400)
# Validate the email via API
validation = requests.get(
f"{BASE_URL}/api/email/validate/{email}",
headers={"X-API-Key": API_KEY}
).json()
# Check for issues
if not validation["is_valid"]:
# Check if there is a typo suggestion
if validation.get("suggested_correction"):
return JsonResponse({
"error": f"Invalid email. Did you mean {validation['suggested_correction']}?"
}, status=400)
return JsonResponse({"error": "Please enter a valid email address"}, status=400)
if validation["is_disposable"]:
return JsonResponse({
"error": "Disposable email addresses are not allowed. Please use a permanent email."
}, status=400)
if validation["is_role_based"]:
return JsonResponse({
"warning": "Role-based emails (info@, admin@) may have delivery issues. "
"Consider using a personal email for account registration."
}, status=200)
# Email is valid - proceed with registration
# ... create user account ...
return JsonResponse({"success": True, "message": "Account created successfully"})
import requests
import csv
API_KEY = "YOUR_API_KEY"
BASE_URL = "https://api.commandsector.in"
def clean_email_list(emails):
"""Validate a list of emails and categorize them."""
response = requests.post(
f"{BASE_URL}/api/email/batch",
json={"emails": emails},
headers={"X-API-Key": API_KEY}
)
results = response.json()
valid = []
invalid = []
disposable = []
typo_fixes = []
for result in results.get("results", results):
email = result["email"]
if result.get("suggested_correction"):
typo_fixes.append({
"original": email,
"suggested": result["suggested_correction"]
})
elif result["is_disposable"]:
disposable.append(email)
elif result["is_valid"]:
valid.append(email)
else:
invalid.append(email)
return {
"valid": valid,
"invalid": invalid,
"disposable": disposable,
"typo_fixes": typo_fixes
}
# Example: Clean a mailing list
emails = [
"alice@gmail.com",
"bob@yahoo.com",
"spam@mailinator.com",
"charlie@gmial.com",
"bad@@syntax.com",
"info@company.com",
"dave@outlook.com",
]
report = clean_email_list(emails)
print(f"Valid emails: {len(report['valid'])}")
for e in report['valid']:
print(f" {e}")
print(f"\nInvalid emails: {len(report['invalid'])}")
for e in report['invalid']:
print(f" {e}")
print(f"\nDisposable: {len(report['disposable'])}")
for e in report['disposable']:
print(f" {e}")
print(f"\nTypo suggestions: {len(report['typo_fixes'])}")
for fix in report['typo_fixes']:
print(f" {fix['original']} -> {fix['suggested']}")
import requests
from functools import lru_cache
API_KEY = "YOUR_API_KEY"
BASE_URL = "https://api.commandsector.in"
@lru_cache(maxsize=10000)
def is_email_valid(email: str) -> dict:
"""Cached email validation to avoid repeated API calls for the same address."""
response = requests.get(
f"{BASE_URL}/api/email/validate/{email}",
headers={"X-API-Key": API_KEY},
timeout=5
)
return response.json()
def validate_signup_email(email: str) -> tuple[bool, str]:
"""Returns (is_acceptable, message) for a signup email."""
result = is_email_valid(email.lower().strip())
if not result["syntax_valid"]:
return False, "The email address format is invalid."
if not result["is_valid"]:
suggestion = result.get("suggested_correction")
if suggestion:
return False, f"This email appears invalid. Did you mean {suggestion}?"
return False, "This email address does not appear to exist."
if result["is_disposable"]:
return False, "Temporary email addresses are not accepted."
return True, "Email is valid."
# Usage in your endpoint
email = "user@gmial.com"
is_ok, message = validate_signup_email(email)
print(f"Accepted: {is_ok}")
print(f"Message: {message}")
# Output: Accepted: False
# Output: Message: This email appears invalid. Did you mean user@gmail.com?
const API_KEY = 'YOUR_API_KEY';
const BASE_URL = 'https://api.commandsector.in';
async function validateEmail(email) {
const response = await fetch(
`${BASE_URL}/api/email/validate/${encodeURIComponent(email)}`,
{ headers: { 'X-API-Key': API_KEY } }
);
if (!response.ok) {
throw new Error(`Validation failed: ${response.status}`);
}
return response.json();
}
// Validate and check results
async function main() {
const result = await validateEmail('test@gmail.com');
console.log(`Email: ${result.email}`);
console.log(`Valid: ${result.is_valid}`);
console.log(`Disposable: ${result.is_disposable}`);
console.log(`Role-based: ${result.is_role_based}`);
if (result.suggested_correction) {
console.log(`Suggestion: ${result.suggested_correction}`);
}
}
main().catch(console.error);
const express = require('express');
const app = express();
app.use(express.json());
const API_KEY = 'YOUR_API_KEY';
const BASE_URL = 'https://api.commandsector.in';
app.post('/api/register', async (req, res) => {
const { email, password, name } = req.body;
if (!email || !password || !name) {
return res.status(400).json({ error: 'All fields are required' });
}
// Validate the email
try {
const validationRes = await fetch(
`${BASE_URL}/api/email/validate/${encodeURIComponent(email)}`,
{ headers: { 'X-API-Key': API_KEY } }
);
const validation = await validationRes.json();
// Reject invalid emails
if (!validation.is_valid) {
const message = validation.suggested_correction
? `Invalid email. Did you mean ${validation.suggested_correction}?`
: 'Please enter a valid email address.';
return res.status(400).json({ error: message });
}
// Reject disposable emails
if (validation.is_disposable) {
return res.status(400).json({
error: 'Disposable email addresses are not allowed. Please use a permanent email.'
});
}
// Warn about role-based emails (but still allow)
const warnings = [];
if (validation.is_role_based) {
warnings.push('Role-based emails may have delivery issues for account notifications.');
}
// Proceed with registration...
// const user = await createUser({ email, password, name });
return res.json({
success: true,
message: 'Account created successfully',
warnings
});
} catch (err) {
console.error('Email validation error:', err);
// If validation service is down, allow registration with basic check
if (!email.includes('@')) {
return res.status(400).json({ error: 'Invalid email format' });
}
// ... proceed with registration
return res.json({ success: true, message: 'Account created' });
}
});
app.listen(3000, () => console.log('Server running on port 3000'));
import { useState, useCallback } from 'react';
import debounce from 'lodash.debounce';
function SignupForm() {
const [email, setEmail] = useState('');
const [emailStatus, setEmailStatus] = useState(null);
const [isChecking, setIsChecking] = useState(false);
const checkEmail = useCallback(
debounce(async (emailValue) => {
if (!emailValue || !emailValue.includes('@')) {
setEmailStatus(null);
return;
}
setIsChecking(true);
try {
const res = await fetch(
`https://api.commandsector.in/api/email/validate/${encodeURIComponent(emailValue)}`,
{ headers: { 'X-API-Key': 'YOUR_API_KEY' } }
);
const data = await res.json();
if (data.suggested_correction) {
setEmailStatus({
type: 'warning',
message: `Did you mean ${data.suggested_correction}?`,
suggestion: data.suggested_correction
});
} else if (data.is_disposable) {
setEmailStatus({
type: 'error',
message: 'Disposable emails are not accepted'
});
} else if (!data.is_valid) {
setEmailStatus({
type: 'error',
message: 'This email address appears to be invalid'
});
} else {
setEmailStatus({
type: 'success',
message: 'Email verified'
});
}
} catch {
setEmailStatus(null);
}
setIsChecking(false);
}, 500),
[]
);
return (
<form>
<label htmlFor="email">Email Address</label>
<input
id="email"
type="email"
value={email}
onChange={(e) => {
setEmail(e.target.value);
checkEmail(e.target.value);
}}
placeholder="you@example.com"
/>
{isChecking && <span>Checking...</span>}
{emailStatus && (
<div className={`email-status ${emailStatus.type}`}>
{emailStatus.message}
{emailStatus.suggestion && (
<button onClick={() => {
setEmail(emailStatus.suggestion);
setEmailStatus({ type: 'success', message: 'Email verified' });
}}>
Use suggestion
</button>
)}
</div>
)}
</form>
);
}
The batch endpoint lets you validate multiple email addresses in a single API call. This is ideal for cleaning mailing lists, validating CSV imports, or processing bulk signups.
import requests
API_KEY = "YOUR_API_KEY"
BASE_URL = "https://api.commandsector.in"
emails = [
"alice@gmail.com",
"bob@yahoo.com",
"temp@mailinator.com",
"typo@gmial.com",
"bad-syntax@@",
"admin@company.com",
"real.user@outlook.com"
]
response = requests.post(
f"{BASE_URL}/api/email/batch",
json={"emails": emails},
headers={"X-API-Key": API_KEY}
)
results = response.json()
for result in results.get("results", results):
flags = []
if result["is_disposable"]:
flags.append("DISPOSABLE")
if result["is_role_based"]:
flags.append("ROLE-BASED")
if result.get("suggested_correction"):
flags.append(f"TYPO -> {result['suggested_correction']}")
if not result["is_valid"]:
flags.append("INVALID")
status = "VALID" if result["is_valid"] and not result["is_disposable"] else "REJECT"
flag_str = f" [{', '.join(flags)}]" if flags else ""
print(f" {status:6s} | {result['email']:30s}{flag_str}")
const API_KEY = 'YOUR_API_KEY';
const BASE_URL = 'https://api.commandsector.in';
async function batchValidate(emails) {
const response = await fetch(`${BASE_URL}/api/email/batch`, {
method: 'POST',
headers: {
'X-API-Key': API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({ emails }),
});
return response.json();
}
// Clean an email list
async function cleanList() {
const emails = [
'user1@gmail.com',
'user2@tempmail.com',
'typo@gmial.com',
'admin@company.com',
'user3@outlook.com',
];
const results = await batchValidate(emails);
const clean = [];
const rejected = [];
for (const r of results.results || results) {
if (r.is_valid && !r.is_disposable) {
clean.push(r.email);
} else {
rejected.push({ email: r.email, reason: !r.is_valid ? 'invalid' : 'disposable' });
}
}
console.log(`Clean emails (${clean.length}):`, clean);
console.log(`Rejected (${rejected.length}):`, rejected);
}
cleanList();
Disposable email addresses are one of the biggest threats to SaaS platforms and online services. Users create throwaway accounts to abuse free tiers, trials, and promotions. The API detects disposable emails from hundreds of known providers including:
Important: Theis_validfield may returntruefor a disposable email because the address is technically valid (correct syntax, real domain, working MX records). Always checkis_disposableseparately if you want to block temporary addresses.
# Python: Block disposable emails at registration
result = validate_email("signup@mailinator.com")
if result["is_disposable"]:
# The email is technically valid but from a disposable provider
print("Blocked: disposable email address")
# Return error to the user
elif result["is_valid"]:
print("Accepted: legitimate email address")
# Proceed with account creation
Typos in email domains are surprisingly common. Studies show that approximately 2-5% of email addresses entered in web forms contain typos. The API detects common misspellings and returns a corrected suggestion:
| Entered Email | Suggested Correction |
|---|---|
user@gmial.com | user@gmail.com |
user@gmai.com | user@gmail.com |
user@yahooo.com | user@yahoo.com |
user@yaho.com | user@yahoo.com |
user@hotmal.com | user@hotmail.com |
user@outloo.com | user@outlook.com |
user@protonmal.com | user@protonmail.com |
Implementing typo suggestions in your signup flow can recover a significant number of users who would otherwise never receive their confirmation email:
// Show a helpful prompt when a typo is detected
async function onEmailBlur(emailInput) {
const email = emailInput.value.trim();
const result = await validateEmail(email);
if (result.suggested_correction) {
const confirmed = confirm(
`Did you mean ${result.suggested_correction}?`
);
if (confirmed) {
emailInput.value = result.suggested_correction;
}
}
}
Validate emails at the point of signup to prevent invalid accounts, block disposable emails from abusing free tiers, and catch typos before the confirmation email bounces. This is the most common use case.
Before sending a campaign, run your email list through batch validation to remove invalid and risky addresses. This protects your sender reputation, reduces bounce rates, and improves deliverability metrics.
Validate emails captured from landing pages, contact forms, and lead magnets. Ensure your sales team only works with verified contacts, saving time and improving conversion rates.
Validate the email at checkout to ensure order confirmations and shipping notifications reach the customer. Suggest typo corrections to prevent frustrated customers who never receive their receipt.
Disposable emails are a strong signal for fraudulent activity. Flag or block signups from disposable providers to reduce fake accounts, coupon abuse, and trial exploitation.
When migrating between CRM platforms or email service providers, validate your entire contact database to start fresh with a clean list. Remove addresses that have become invalid over time.
| Plan | Requests / Day | Rate Limit | Batch Size | Price |
|---|---|---|---|---|
| Free | 100 | 10 / minute | Up to 10 emails | $0 / month |
| Pro | 10,000 | 100 / minute | Up to 100 emails | $9.99 / month |
| Enterprise | Unlimited | Custom | Custom | Contact us |
The free tier is ideal for validating emails in real time during form submissions (one email at a time). For bulk list cleaning, the Pro tier provides enough capacity to validate up to 10,000 addresses per day. Get your free API key here.
The API verifies syntax, DNS, and MX records, which confirms the domain can receive email. It does not perform SMTP mailbox verification (connecting to the mail server and asking if a specific address exists) because many mail servers block this check and it can trigger spam filters. The validation provided covers 95%+ of invalid email detection needs.
The disposable email provider database is updated regularly to include newly created throwaway email services. This ensures accurate detection even as new disposable email providers appear.
Yes. The API processes the email address to check its validity and does not store, log, or retain any email addresses or personal data. The validation is performed in real time and the data is discarded after the response is sent.
We recommend implementing a fallback strategy: if the API returns an error or times out, accept the email with basic syntax validation (check for @ and a dot in the domain) and validate it asynchronously later. Never block user registrations entirely because an external service is down.
is_valid is the overall verdict that combines syntax, DNS, and MX checks. An email can have is_valid: false even if mx_records: true (for example, if the syntax is invalid). Conversely, an email might have valid syntax and DNS but mx_records: false, meaning the domain exists but cannot receive email.
The typo detection covers the most common email providers (Gmail, Yahoo, Hotmail, Outlook, Protonmail, AOL, iCloud, and others) and catches typical keyboard-based misspellings. It does not attempt to correct custom domain typos, as there is no way to know the intended domain for non-public email providers.
Yes, the API responds in under 200ms for most requests, making it suitable for real-time validation as users type. Use a debounce of 500ms on the input field to avoid excessive API calls. See the React example above for a complete implementation.
You can test individual emails in our Email Validation Playground without an API key (limited to 5 requests per minute). For integration and production use, sign up for a free API key.
curl "https://api.commandsector.in/api/email/validate/user@example.com" \
-H "X-API-Key: YOUR_API_KEY"
import requests
result = requests.get("https://api.commandsector.in/api/email/validate/user@example.com",
headers={"X-API-Key": "YOUR_API_KEY"}).json()
print(f"Valid: {result['is_valid']}")
print(f"Disposable: {result['is_disposable']}")
Get a free API key with 100 requests/day. No credit card required.
Get Free API Key