ParheliaWeb

Email Validator API

Real‑time email verification with syntax, domain, and SMTP checks. Built for developers who want transparency, not black boxes.

Base URL: https://parheliaweb.com

All requests must include an API key in the x-api-key header. Responses are in JSON.

New? Head over to the home page and click Subscribe to get your API key instantly.

πŸ’Ά Pricing & Currency

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.

EU-Based: ParheliaWeb is built and hosted in the Netherlands. All data processing complies with GDPR. Email addresses are never stored in plain text β€” only SHA-256 hashed for operational monitoring. Our servers are located in Dutch data centers, ensuring full compliance with EU data protection regulations.

πŸ” Authentication

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.

πŸ“‘ Rate Limits & Access

PlanPriceRate LimitMonthly QuotaVerification DepthSupport
Loading pricing...

When you exceed the limit, the API returns 429 Too Many Requests.

πŸ”„ Concurrent requests: The number of simultaneous validations allowed depends on your plan: 1 (Free), 2 (Starter), 3 (Pro), 10 (Business). Additional requests will receive an immediate error response. For higher concurrency needs, contact us for Enterprise.

πŸ“¦ Endpoint: Validate an Email Address

POST /v1/email/validate

Validates a single email address through our multi-phase verification pipeline. Currently monitoring β€” blacklisted domains with dynamic pattern detection for emerging spam techniques.

Request Body

FieldTypeRequiredDescription
emailstringYesThe email address to validate

Example Requests

# 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"}'

Example Response β€” Valid Email

{
  "status": "ok",
  "result": {
    "email": "user@example.com",
    "status": "valid",
    "confidence": 90,
    "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
      }
    }
  }
}

Example Response β€” Risky (Catch-All Domain)

{
  "status": "ok",
  "result": {
    "email": "info@company.com",
    "status": "risky",
    "confidence": 45,
    "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
      }
    }
  }
}

Example Response β€” Invalid (Blacklisted Domain)

{
  "status": "ok",
  "result": {
    "email": "spam@mailinator.com",
    "status": "invalid",
    "confidence": 95,
    "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
      }
    }
  }
}

Response Fields

FieldTypeDescription
emailstringThe email address that was validated
statusstringOverall assessment: valid, invalid, risky, or unknown
confidenceinteger 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).
cachedbooleanTrue if the result was served from cache (instant), false if a fresh SMTP verification was performed
X-Cache (HTTP header)stringHIT 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_seenstring|nullISO 8601 timestamp of when this email hash was first encountered by our system. null on the first validation
syntax_validbooleanWhether the email passes RFC 5322 syntax validation
domain_check.passedbooleanWhether the domain passed all blacklist and pattern checks
domain_check.whitelistedbooleanTrue if the email or domain is on the trusted whitelist
domain_check.blacklistedbooleanTrue if the domain is on the static blacklist (disposable, spam, etc.)
domain_check.blacklist_matchobject|nullDetails about the blacklist match if applicable
domain_check.dynamic_matchobject|nullDetails about dynamic pattern match (numeric prefix, double TLD, etc.)
domain_check.no_probebooleanTrue if the domain is known to reject SMTP probes
domain_check.checks_performedarrayList of all domain-level checks executed and their outcomes
mx_validbooleanWhether the domain has valid MX records
mx_serversarrayList of MX server hostnames (up to 5, sorted by priority)
smtp_check.performedbooleanWhether SMTP verification was attempted
smtp_check.resultboolean|nullTrue = mailbox accepted, False = rejected, null = could not determine
smtp_check.codeinteger|nullSMTP response code (250, 550, etc.)
smtp_check.messagestringHuman-readable explanation of the SMTP result
catch_all.detectedboolean|nullPro tier: Whether the domain appears to be a catch-all
catch_all.messagestringPro tier: Details about catch-all detection
risk_factorsarrayList of risk factors with severity levels (critical, high, medium)
performance_ms.totalfloatTotal validation time in milliseconds
performance_ms.phasesobjectPer-phase timing breakdown (syntax, domain_check, dns, smtp, catch_all)

Status Values Explained

StatusMeaningRecommended Action
validEmail syntax is correct, domain exists, and SMTP server confirmed the mailboxSafe to send
invalidEmail failed syntax, domain, or SMTP checks with high confidenceDo not send β€” will bounce
riskyEmail could not be fully verified (catch-all domain, greylisting, suspicious patterns)Send with caution for marketing; avoid for transactional email
unknownCould not determine (rate-limited by provider, domain blocks probes, network issues)Retry later or verify through other means
🎯 Priority Modes (Pro & Business tiers): Control the balance between speed and accuracy by setting the X-Priority header on your requests:

If no header is set, balanced mode is used automatically.

⚠️ About major email providers: Verification accuracy varies by provider. Gmail provides real responses and can be verified reliably. Microsoft (Outlook, Hotmail, Live) accepts all addresses during SMTP verification, so results for these domains may be uncertain. Yahoo and some other providers block verification probes entirely. For domains where we cannot get a definitive answer, we return risky with a clear explanation rather than guessing. We believe in transparency β€” you deserve to know what we can and can't verify.
⏱️ About validation speed: Most validations complete in under 2 seconds. Some providers, particularly Gmail, may take 5–10 seconds to respond to SMTP probes. This is normal β€” Gmail deliberately introduces slight delays as part of their anti-spam measures. We wait for a real answer rather than guessing or returning early. Every response includes per-phase timing in performance_ms so you can see exactly where the time was spent.
How Verification Works: Our pipeline runs three phases:
(1) RFC 5322 syntax validation,
(2) domain checks against β€” blacklisted domains and dynamic spam patterns, and
(3) SMTP handshake verification. Each phase must pass before proceeding to the next. Results include per-phase timing so you can see exactly what happened.

πŸ“¦ Endpoint: Batch Validation

POST /v1/email/validate/batch

Validate up to 100 email addresses in a single request. Batches of 6 or more emails are processed asynchronously β€” you'll receive an immediate response with a batch_id and can poll for results. Small batches (5 or fewer) are processed synchronously and return results immediately. Each batch is assigned a unique batch_id tracked in your validation logs. Batch validation uses connection pooling β€” emails to the same domain share a single SMTP connection, significantly reducing verification time for large lists with repeated domains.

⏱️ Batch processing: Large batches are processed asynchronously in the background across multiple workers. Submit your batch, receive a batch_id immediately, and poll the status endpoint to retrieve results when complete. Cached results return instantly, making repeat batches significantly faster.

Request Body

FieldTypeRequiredDescription
emailsarray of stringsYesList of email addresses to validate (max 100)

Example Request

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"
    ]
  }'

Example Response β€” Small Batch (Synchronous)

{
  "status": "ok",
  "result": {
    "batch_id": "dbb2b6bc8cc9",
    "total_emails": 3,
    "total_ms": 28.37,
    "results": [
      {
        "email": "user@example.com",
        "status": "valid",
        "confidence": 90,
        "cached": false,
        "first_seen": "2026-06-15 21:45:00"
      },
      {
        "email": "spam@mailinator.com",
        "status": "invalid",
        "confidence": 95,
        "cached": false,
        "first_seen": "2026-06-15 21:45:01"
      },
      {
        "email": "info@catchall-domain.com",
        "status": "risky",
        "confidence": 45,
        "cached": false,
        "first_seen": "2026-06-15 21:45:02"
      }
    ]
  }
}

Example Response β€” Large Batch (Async)

{
  "status": "ok",
  "result": {
    "batch_id": "23f6e6244854",
    "total_emails": 20,
    "status": "processing",
    "message": "Batch queued for processing. Poll GET /v1/email/validate/batch/23f6e6244854 for results."
  }
}

πŸ“¦ Endpoint: Poll Batch 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.

Example Request

curl -H "x-api-key: YOUR_KEY" https://parheliaweb.com/v1/email/validate/batch/23f6e6244854

Example Response β€” Still Processing

{
  "status": "ok",
  "result": {
    "batch_id": "23f6e6244854",
    "total_emails": 20,
    "completed_emails": 0,
    "status": "processing",
    "total_ms": null
  }
}

Example Response β€” Completed

{
  "status": "ok",
  "result": {
    "batch_id": "23f6e6244854",
    "total_emails": 20,
    "completed_emails": 20,
    "status": "completed",
    "total_ms": 45230.67,
    "results": [
      {
        "email": "user@example.com",
        "status": "valid",
        "confidence": 90,
        "cached": false,
        "first_seen": "2026-06-15 21:45:00"
      },
      {
        "email": "spam@mailinator.com",
        "status": "invalid",
        "confidence": 95,
        "cached": false,
        "first_seen": "2026-06-15 21:45:01"
      }
    ]
  }
}

πŸ’» Code Snippets

Python

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']}%")

JavaScript (fetch)

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));

cURL

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"}'

πŸ“¬ Support

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 Β· Contact

AI verification powered by DeepSeek