Email validation for developers and global teams: validate single or bulk addresses with syntax, domain, MX, and SMTP checks, then use structured results in CRM, signup, and email-marketing workflows.
View Email Validation API Pricing Start Free
Base URL: https://parheliaweb.com
All requests must include an API key in the x-api-key header. Responses are in JSON. Review our data methodology to understand the verification stages, caching, SMTP limitations, and risk states.
All prices are listed in Euros (EUR). Your card will be charged in your local currency at the prevailing exchange rate. We use Stripe for secure payment processing, which supports 135+ currencies and local payment methods including iDEAL, Bancontact, and SEPA Direct Debit.
Pass your secret API key as an HTTP header on every request:
x-api-key: YOUR_API_KEY
If the key is missing or invalid, you'll receive a 401 Unauthorized or 403 Forbidden.
Your daily quota depends on your subscription tier, while the rate limit exists to prevent abuse (e.g. using the API as a DDoS bot). The two are independent: exhausting your daily quota requires waiting until the next day, whereas exceeding the rate limit only requires a short cooldown.
| Plan | Price | Rate Limit | Monthly Quota | Verification Depth | Support |
|---|---|---|---|---|---|
| Free | Free | 60 requests / minute | 100 verifications | Syntax + Domain checks + SMTP (5s timeout) | — |
| Starter | €31/month | 60 requests / minute | 5,000 verifications | Full SMTP verification (10s timeout) + Batch validation | Email support |
| Pro | €63/month | 60 requests / minute | 25,000 verifications | Full suite + Catch-all detection + Priority modes | Priority email |
| Business | €143/month | 60 requests / minute | 100,000 verifications | Full verification suite + Custom SLAs | Dedicated support |
When the request rate exceeds the rate limit, the API returns 429 Too Many Requests. Simply retry after a short wait — this does not consume your daily quota.
POST /v1/email/validate
Validates a single email address through our multi-phase verification pipeline. Currently monitoring thousands of blacklisted domains with continuously updated pattern detection for emerging spam techniques.
By default, responses are returned in English. For Chinese-language status values, risk factors, messages, blacklist details, and checks, pass lang: "zh" in the request body. English field names remain unchanged; only the values are translated.
| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | The email address to validate |
lang | string | No | Response language. Use zh for Chinese translations of status, risk factors, messages, blacklist details, and checks. Defaults to en (English). |
# Validate a single email address
curl -X POST https://parheliaweb.com/v1/email/validate \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_KEY" \
-d '{"email": "user@example.com"}'
# Validate a known disposable domain
curl -X POST https://parheliaweb.com/v1/email/validate \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_KEY" \
-d '{"email": "test@mailinator.com"}'
# Validate with Chinese response values
curl -X POST https://parheliaweb.com/v1/email/validate \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_KEY" \
-d '{"email": "test@spidernet.nl", "lang": "zh"}'
{
"status": "ok",
"result": {
"email": "user@example.com",
"status": "valid",
"confidence": 90,
"deliverability_score": 95,
"is_role_based": false,
"cached": false,
"first_seen": "2026-06-15 21:45:00",
"syntax_valid": true,
"domain_check": {
"passed": true,
"whitelisted": false,
"blacklisted": false,
"blacklist_match": null,
"dynamic_match": null,
"no_probe": false,
"checks_performed": [
"blacklist_clean",
"numeric_prefix_clean",
"double_tld_clean"
]
},
"mx_valid": true,
"mx_servers": ["mail.example.com"],
"smtp_check": {
"performed": true,
"result": true,
"code": 250,
"message": "Mailbox accepted (code 250)"
},
"risk_factors": [],
"performance_ms": {
"total": 1847.32,
"phases": {
"syntax": 0.03,
"domain_check": 1.48,
"dns": 45.12,
"smtp": 1800.69
}
}
}
}
{
"status": "ok",
"result": {
"email": "info@company.com",
"status": "risky",
"confidence": 45,
"deliverability_score": 40,
"is_role_based": false,
"cached": false,
"first_seen": "2026-06-15 21:45:00",
"syntax_valid": true,
"domain_check": {
"passed": true,
"whitelisted": false,
"blacklisted": false,
"blacklist_match": null,
"dynamic_match": null,
"no_probe": false,
"checks_performed": [
"blacklist_clean",
"numeric_prefix_clean",
"double_tld_clean"
]
},
"mx_valid": true,
"mx_servers": ["mail.company.com"],
"smtp_check": {
"performed": true,
"result": true,
"code": 250,
"message": "Mailbox accepted (code 250)"
},
"catch_all": {
"detected": true,
"message": "Domain accepts all 2 test addresses — likely catch-all"
},
"risk_factors": [
{"factor": "catch_all_domain", "severity": "medium"}
],
"performance_ms": {
"total": 3215.67,
"phases": {
"syntax": 0.02,
"domain_check": 1.52,
"dns": 38.41,
"smtp": 2847.33,
"catch_all": 328.39
}
}
}
}
{
"status": "ok",
"result": {
"email": "spam@mailinator.com",
"status": "invalid",
"confidence": 95,
"deliverability_score": 0,
"is_role_based": false,
"cached": false,
"first_seen": "2026-06-15 21:45:00",
"syntax_valid": true,
"domain_check": {
"passed": false,
"whitelisted": false,
"blacklisted": true,
"blacklist_match": {
"type": "static_domain",
"domain": "mailinator.com",
"reason": "Disposable email service",
"category": "disposable",
"severity": 10
},
"dynamic_match": null,
"no_probe": false,
"checks_performed": ["blacklist_hit"]
},
"mx_valid": false,
"mx_servers": [],
"smtp_check": {
"performed": false,
"result": null,
"code": null,
"message": "Skipped: domain rejected"
},
"risk_factors": [
{
"factor": "domain_rejected",
"severity": "critical",
"detail": {
"type": "static_domain",
"domain": "mailinator.com",
"reason": "Disposable email service",
"category": "disposable",
"severity": 10
}
}
],
"performance_ms": {
"total": 1.54,
"phases": {
"syntax": 0.02,
"domain_check": 1.48
}
}
}
}
{
"status": "ok",
"result": {
"email": "test@spidernet.nl",
"status": "无效",
"confidence": 95,
"deliverability_score": 0,
"is_role_based": false,
"domain_check": {
"blacklist_match": {
"type": "static_domain",
"domain": "spidernet.nl",
"reason": "从旧版黑名单迁移",
"category": "垃圾邮件"
},
"checks_performed": ["黑名单命中"]
},
"risk_factors": [
{
"factor": "域名已拒绝",
"severity": "严重",
"detail": {
"reason": "从旧版黑名单迁移",
"category": "垃圾邮件"
}
}
]
}
}
| Field | Type | Description |
|---|---|---|
email | string | The email address that was validated |
status | string | Overall assessment: valid, invalid, risky, or unknown |
confidence | integer |
Confidence score 0–100. Meaning depends on the status:For valid: 90 = mailbox confirmed by SMTP server. Always high confidence when valid. For invalid: Indicates which phase caught the problem: • 100 = Syntax invalid (missing @, consecutive dots) • 95 = Domain rejected (blacklisted or dynamic pattern match) • 90 = No MX records (domain has no mail server) • 0 = SMTP server explicitly rejected the mailbox (code 550) For risky: Higher = less risky. 60 = minor issue (temporary failure), 55 = catch-all domain, 45–50 = multiple concerns, 35 = high risk. For unknown: Always 30 = could not obtain any answer (domain blocks probes, rate-limited, network issues). |
deliverability_score | integer | Simple 0–100 score indicating whether the email is safe to send. 95+ = safe, 40–70 = use caution, below 40 = do not send. Distilled from status, confidence, and risk factors for non-technical users and CRM rules. |
is_role_based | boolean | True if the email is a role-based address (admin@, info@, support@). These are often auto-filtered by CRMs or ignored by real humans. Also appears as a role_based_account risk factor with low severity. |
lang | string | Request parameter. Use zh for Chinese translations of status, risk factors, messages, blacklist details, and checks. Defaults to en (English). |
cached | boolean | True if the result was served from cache (instant), false if a fresh SMTP verification was performed |
X-Cache (HTTP header) | string | HIT if the result was served from cache, MISS if fresh verification was performed. Check this header to determine cache status without parsing the JSON body. |
first_seen | string|null | ISO 8601 timestamp of when this email hash was first encountered by our system. null on the first validation |
syntax_valid | boolean | Whether the email passes RFC 5322 syntax validation |
domain_check.passed | boolean | Whether the domain passed all blacklist and pattern checks |
domain_check.whitelisted | boolean | True if the email or domain is on the trusted whitelist |
domain_check.blacklisted | boolean | True if the domain is on the static blacklist (disposable, spam, etc.) |
domain_check.blacklist_match | object|null | Details about the blacklist match if applicable |
domain_check.dynamic_match | object|null | Details about dynamic pattern match (numeric prefix, double TLD, etc.) |
domain_check.no_probe | boolean | True if the domain is known to reject SMTP probes |
domain_check.checks_performed | array | List of all domain-level checks executed and their outcomes |
mx_valid | boolean | Whether the domain has valid MX records |
mx_servers | array | List of MX server hostnames (up to 5, sorted by priority) |
smtp_check.performed | boolean | Whether SMTP verification was attempted |
smtp_check.result | boolean|null | True = mailbox accepted, False = rejected, null = could not determine |
smtp_check.code | integer|null | SMTP response code (250, 550, etc.) |
smtp_check.message | string | Human-readable explanation of the SMTP result |
catch_all.detected | boolean|null | Pro tier: Whether the domain appears to be a catch-all |
catch_all.message | string | Pro tier: Details about catch-all detection |
risk_factors | array | List of risk factors with severity levels (critical, high, medium) |
performance_ms.total | float | Total validation time in milliseconds |
performance_ms.phases | object | Per-phase timing breakdown (syntax, domain_check, dns, smtp, catch_all) |
| Status | Meaning | Recommended Action |
|---|---|---|
| valid | Email syntax is correct, domain exists, and SMTP server confirmed the mailbox | Safe to send |
| invalid | Email failed syntax, domain, or SMTP checks with high confidence | Do not send — will bounce |
| risky | Email could not be fully verified (catch-all domain, greylisting, suspicious patterns) | Send with caution for marketing; avoid for transactional email |
| unknown | Could not determine (rate-limited by provider, domain blocks probes, network issues) | Retry later or verify through other means |
X-Priority header on your requests:
If no header is set, balanced mode is used automatically.
performance_ms so you can see
exactly where the time was spent.
Not all email validators do the same thing. Here's how common approaches compare — and what each one misses.
| Approach | Catches syntax errors | Catches disposable domains | Catches nonexistent mailboxes | Protects your sender IP | Handles catch-all |
|---|---|---|---|---|---|
| Regex only | ✅ | ❌ | ❌ | N/A | ❌ |
| Regex + MX lookup | ✅ | ⚠️ Partial | ❌ | N/A | ❌ |
| Self-hosted SMTP probe | ✅ | ⚠️ Partial | ✅ | ❌ Your IP is exposed | ❌ |
| ParheliaWeb Email Validation API | ✅ | ✅ Thousands, auto-updated | ✅ Real SMTP handshake | ✅ Only ParheliaWeb's IP is visible | ✅ Pro tier+ |
The table above isn't marketing — it's the actual engineering trade-off. If you only need to catch obvious typos, a regex is fine. But if email deliverability matters to your business, you need real SMTP verification with IP isolation, or you'll risk your corporate domain getting flagged as a probing source.
POST /v1/email/validate/batch
Validate multiple email addresses in a single request. Batch limits vary by tier:
Batches of 6+ emails are processed asynchronously — you'll receive an immediate response with a batch_id and can poll for results. Large batches may take several minutes to complete. Each batch is assigned a unique batch_id tracked in your validation logs.
batch_id immediately, and poll the status endpoint to retrieve
results when complete. Cached results return instantly, making repeat batches
significantly faster.
| Field | Type | Required | Description |
|---|---|---|---|
emails | array of strings | Yes | List of email addresses to validate. Limit depends on your tier: Starter=100, Pro=500, Business=2500. |
lang | string | No | Response language. Use zh for Chinese translations of status, risk factors, messages, blacklist details, and checks. Defaults to en (English). |
curl -X POST https://parheliaweb.com/v1/email/validate/batch \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_KEY" \
-d '{
"emails": [
"user@example.com",
"spam@mailinator.com",
"info@catchall-domain.com"
],
"lang": "zh"
}'
{
"status": "ok",
"result": {
"batch_id": "dbb2b6bc8cc9",
"total_emails": 3,
"total_ms": 28.37,
"results": [
{
"email": "user@example.com",
"status": "有效",
"confidence": 90,
"deliverability_score": 95,
"is_role_based": false,
"cached": false,
"first_seen": "2026-06-15 21:45:00"
},
{
"email": "spam@mailinator.com",
"status": "无效",
"confidence": 95,
"deliverability_score": 0,
"is_role_based": false,
"cached": false,
"first_seen": "2026-06-15 21:45:01"
},
{
"email": "info@catchall-domain.com",
"status": "有风险",
"confidence": 45,
"deliverability_score": 40,
"is_role_based": false,
"cached": false,
"first_seen": "2026-06-15 21:45:02"
}
]
}
}
{
"status": "ok",
"result": {
"batch_id": "23f6e6244854",
"total_emails": 2500,
"status": "processing",
"message": "Batch queued for processing. Poll GET /v1/email/validate/batch/23f6e6244854 for results."
}
}
GET /v1/email/validate/batch/{batch_id}
Poll for the results of an asynchronously processed batch. Returns the batch status and, when complete, the full results array.
curl -H "x-api-key: YOUR_KEY" https://parheliaweb.com/v1/email/validate/batch/23f6e6244854
{
"status": "ok",
"result": {
"batch_id": "23f6e6244854",
"total_emails": 2500,
"completed_emails": 0,
"status": "processing",
"total_ms": null
}
}
{
"status": "ok",
"result": {
"batch_id": "23f6e6244854",
"total_emails": 2500,
"completed_emails": 2500,
"status": "completed",
"total_ms": 45230.67,
"results": [
{
"email": "user@example.com",
"status": "valid",
"confidence": 90,
"deliverability_score": 95,
"is_role_based": false,
"cached": false,
"first_seen": "2026-06-15 21:45:00"
},
{
"email": "spam@mailinator.com",
"status": "invalid",
"confidence": 95,
"deliverability_score": 0,
"is_role_based": false,
"cached": false,
"first_seen": "2026-06-15 21:45:01"
}
]
}
}
import requests
headers = {
"Content-Type": "application/json",
"x-api-key": "YOUR_API_KEY"
}
data = {"email": "user@example.com"}
resp = requests.post("https://parheliaweb.com/v1/email/validate", headers=headers, json=data)
result = resp.json()["result"]
print(f"Status: {result['status']}, Confidence: {result['confidence']}%")
# With Chinese response values
data_zh = {"email": "user@example.com", "lang": "zh"}
resp_zh = requests.post("https://parheliaweb.com/v1/email/validate", headers=headers, json=data_zh)
result_zh = resp_zh.json()["result"]
print(f"状态: {result_zh['status']}, 置信度: {result_zh['confidence']}%")
<?php
$api_key = 'YOUR_API_KEY';
$email = 'user@example.com';
$ch = curl_init('https://parheliaweb.com/v1/email/validate');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 15,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'x-api-key: ' . $api_key
],
CURLOPT_POSTFIELDS => json_encode([
'email' => $email
// Add 'lang' => 'zh' for Chinese response values
])
]);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($http_code === 200) {
$data = json_decode($response, true);
$result = $data['result'];
echo "Status: " . $result['status'] . "\n";
echo "Confidence: " . $result['confidence'] . "%\n";
echo "Deliverability: " . $result['deliverability_score'] . "%\n";
} else {
echo "API error (HTTP " . $http_code . ")\n";
}
fetch("https://parheliaweb.com/v1/email/validate", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": "YOUR_API_KEY"
},
body: JSON.stringify({ email: "user@example.com" })
})
.then(res => res.json())
.then(data => console.log(data.result.status));
// With Chinese response values
fetch("https://parheliaweb.com/v1/email/validate", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": "YOUR_API_KEY"
},
body: JSON.stringify({ email: "user@example.com", lang: "zh" })
})
.then(res => res.json())
.then(data => console.log(data.result.status)); // "有效" or "无效"
# Linux / macOS
curl -X POST https://parheliaweb.com/v1/email/validate \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{"email": "user@example.com"}'
# Windows 11 PowerShell
curl.exe -X POST https://parheliaweb.com/v1/email/validate -H "Content-Type: application/json" -H "x-api-key: YOUR_API_KEY" -d '{\"email\": \"user@example.com\"}'
# Windows 10 PowerShell
curl.exe -X POST https://parheliaweb.com/v1/email/validate -H "Content-Type: application/json" -H "x-api-key: YOUR_API_KEY" -d "{""email"": ""user@example.com""}"
# With Chinese response values (Linux / macOS)
curl -X POST https://parheliaweb.com/v1/email/validate \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{"email": "user@example.com", "lang": "zh"}'
Your API key isn't limited to this API. Use it across our full platform:
| API | Endpoint Base | Free Tier | Pro Tier |
|---|---|---|---|
| Email Validation | /v1/email/validate | 100/mo | 25,000/mo |
| Funding Rounds | /v1/funding | 100/day | 1,000/day |
| Layoffs | /v1/layoffs | 100/day | 1,000/day |
| Regulatory Fines | /v1/fines | 100/day | 1,000/day |
| Acquisitions | /v1/acquisitions | 100/day | 1,000/day |
| IPOs | /v1/ipos | 100/day | 1,000/day |
Quotas are per-API. Upgrade each API independently based on your needs. Why different quotas? Email validation performs live SMTP handshakes — per-check infrastructure cost. Data APIs query our cached database — lower marginal cost.
If you run into any issues or have feature suggestions, email us at info@parheliaweb.com.
Email Validator API by ParheliaWeb · Built in the Netherlands · Terms · Privacy · Data Methodology · Why Choose Us · Contact