Browse

Email Domain Check

Checks the domain behind an email address: MX records, SPF and DMARC policies, and whether the address uses a disposable domain, a free mailbox provider or a role mailbox such as info@ or support@. It never contacts the mail server, so it cannot confirm that a mailbox exists.

POST https://YOUR_API_HOST/v1/email-domain-check

Credits and caching

  • Success billing. 1 credit per address checked. You are charged only when the lookup finds something; a not-found result is free.
  • Results are cached per account for 7 days. Repeating the same lookup in that window is free and returns cache_hit: true.
  • Invalid input, rate limits and errors are never charged.
  • Read the billing rules for the full picture.

Request

Send a JSON body with Authorization: Bearer <key>. The body can be up to 64 KB.

FieldTypeRequiredNotes
emailstringnoUp to 1000 characters.
domainstringnoUp to 2048 characters.

Example request

Terminal
curl -X POST https://YOUR_API_HOST/v1/email-domain-check \
  -H "Authorization: Bearer $LOOKVALID_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email":"info@example.com"}'

Response

The status is 200 whether or not anything was found. Check found. Every response also carries the X-Request-Id, X-Credits-Charged, X-Credits-Remaining and X-RateLimit-* headers.

Envelope

FieldTypeNotes
request_idstring-
product"email-domain-check"-
foundbooleanFalse means the lookup ran and found nothing; it is free.
reasonstring or nullWhy nothing was found; null when found.
sourcesarray of stringWhere the data came from, including any attribution the licence requires.
credits_chargedinteger0 for a cache hit, a not-found result or an error.
credits_remaininginteger-
cache_hitbooleanTrue when the account already paid for this lookup within the cache window.
cacheobject-

The data object

Present when found is true, otherwise null.

FieldTypeNotes
emailstring or nullNormalized address (lowercase, punycode domain); null for a domain-only lookup
syntax_validboolean or nullTrue for an email that passed the syntax check; null for a domain-only lookup (bad syntax is rejected as invalid input)
domainstring-
mx_recordsarray of objectSorted by priority, then host name
mx_records[].exchangestring-
mx_records[].priorityinteger-
has_mxboolean-
null_mxbooleanTrue when the domain publishes a null MX ("0 ."), meaning it accepts no mail
implicit_mxbooleanTrue when there is no MX but an A or AAAA record, so senders fall back to the host itself
spfobject-
spf.recordstring or null-
spf.record_countinteger-
spf.policystring or nullQualifier on the "all" mechanism, after following redirect=
spf.validbooleanTrue when exactly one SPF record exists
spf.issuesarray of string-
dmarcobject-
dmarc.recordstring or null-
dmarc.record_countinteger-
dmarc.policystring or null-
dmarc.subdomain_policystring or null-
dmarc.pctinteger or null-
dmarc.ruaarray of string-
dmarc.validboolean-
dmarc.issuesarray of string-
disposableboolean-
free_providerboolean-
role_accountboolean or nullNull for a domain-only lookup
smtp_checkedfalseThe mail server is never contacted, so mailbox existence is not verified
deliverability_signalstringOne of good, risky, undeliverable.
deliverability_reasonsarray of object-
deliverability_reasons[].codestring-
deliverability_reasons[].messagestring-

Captured example (2026-10-18)

A real run of this lookup on 2026-10-18, using the request above, which is a public input. The envelope fields are left out.

{
  "product": "email-domain-check",
  "found": true,
  "data": {
    "email": "info@example.com",
    "syntax_valid": true,
    "domain": "example.com",
    "mx_records": [],
    "has_mx": false,
    "null_mx": true,
    "implicit_mx": false,
    "spf": {
      "record": "v=spf1 -all",
      "record_count": 1,
      "policy": "-all",
      "valid": true,
      "issues": []
    },
    "dmarc": {
      "record": "v=DMARC1;p=reject;sp=reject;adkim=s;aspf=s",
      "record_count": 1,
      "policy": "reject",
      "subdomain_policy": "reject",
      "pct": null,
      "rua": [],
      "valid": true,
      "issues": []
    },
    "disposable": false,
    "free_provider": false,
    "role_account": true,
    "smtp_checked": false,
    "deliverability_signal": "undeliverable",
    "deliverability_reasons": [
      {
        "code": "null_mx",
        "message": "The domain publishes a null MX record, which means it does not accept email."
      },
      {
        "code": "role_account",
        "message": "The address is a shared role mailbox such as info@ or support@, not a person."
      }
    ]
  },
  "sources": [
    "Public DNS (MX, TXT)",
    "Open disposable-email-domain and free-provider lists"
  ]
}

Errors

  • 400 invalid_input: The request input is invalid.
  • 401 unauthorized: The API key is missing, malformed, revoked or unknown.
  • 402 insufficient_credits: The account does not have enough credits for this lookup. Error code: insufficient_credits. During a trial whose allowance is used up the code is trial_allowance_exhausted: nothing is charged and the customer starts the plan from the billing page.
  • 405 method_not_allowed: This endpoint does not accept that HTTP method.
  • 413 payload_too_large: The request body is too large.
  • 429 rate_limited: Too many requests for this API key.
  • 500 internal_error: An unexpected error occurred.
  • 503 provider_unavailable: The data source for this product is unavailable right now.