Domain Health Checker avatar

Domain Health Checker

Pricing

from $4.25 / 1,000 domain health evidence cards

Go to Apify Store
Domain Health Checker

Domain Health Checker

Audit DNS resolution, MX, SPF, DMARC, name servers, and TLS for a list of domains. Complete evidence cards include a 0–100 score, source states, issues, confidence, data gaps, and a next action. Incomplete or unsafe destinations remain unscored and are not billed as results.

Pricing

from $4.25 / 1,000 domain health evidence cards

Rating

0.0

(0)

Developer

Tim Zinin

Tim Zinin

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

Share

Domain Health Checker — DNS, MX, SPF, DMARC & TLS Evidence

Turn a list of domains into client-ready technical evidence. Domain Health Checker observes public DNS records and the TLS certificate on port 443, separates verified problems from source outages, scores only complete audits, and returns a prioritized next action for every unique domain.

Use it to prepare an agency pitch, review a website launch, qualify a maintenance opportunity, check a portfolio, or add technical context to a company record. You get the underlying records, not just a red or green badge.

Domain Health Checker turns domain lists into evidence and next actions

The result in one sentence

For each unique requested domain, the Actor returns a timestamped evidence card with:

  • A, AAAA, NS, MX and www CNAME observations;
  • SPF and DMARC records, including the exact organizational p= policy;
  • Null MX recognition, so “this domain explicitly accepts no mail” is not mistaken for working MX;
  • TLS issuer, trust status, authorization error, expiry date and days remaining;
  • a 0–100 score only when every required source is known;
  • verified issues, evidence states, confidence, data gaps, priority and a recommended next action;
  • safeToAutomate: false, because public technical evidence should be reviewed before changing a customer's DNS, email or production certificate;
  • an OUTPUT receipt reconciling requested, unique, duplicate, delivered, paid, free and withheld rows, plus fatal state and replay safety.

Temporary DNS or TLS infrastructure failures are not sold as defects in the buyer's domain. If a required source is unavailable, the audit becomes partial, the score is null, the row is free, and the action is to retry after source recovery.

Who this is for

Marketing and web agencies

Run a bounded technical pre-audit before a discovery call. A prospect may have a working homepage but no enforced DMARC policy, an untrusted certificate, no usable mail exchanger, or a certificate close to expiry. The evidence card gives the account manager a concrete, reviewable conversation starter without claiming a vulnerability or inventing a business emergency.

Useful agency workflows include:

  1. export the domains of target companies from your CRM;
  2. audit them in one run;
  3. filter for actionPriority equal to critical or high;
  4. review the underlying DNS/TLS evidence;
  5. prepare a specific remediation offer: DNS recovery, certificate renewal, email-authentication setup, launch QA, or ongoing website care.

Small businesses and founders

Check the domains that matter before a launch, migration, campaign or investor demo. The Actor does not require a security scanner, a browser session, or access to the DNS provider. It observes what the public internet can see and tells you what to verify next.

MSPs, website-care teams and fractional IT

Use one Dataset row per domain as a portfolio review queue. Schedule repeat runs, export to a spreadsheet or warehouse, compare ssl.daysLeft, email.dmarcPolicy, healthScore and recommendedAction, and route the exceptions to a technician.

This Actor is a point-in-time observer rather than a stateful alert engine. Your automation should compare successive Datasets or store the results in your own system if you need change alerts.

Email deliverability consultants

Check whether a domain publishes a usable MX route, one SPF record and one DMARC record, and whether the DMARC organizational policy is none, quarantine or reject. A record's presence is not the same as inbox placement, and the Actor says so explicitly.

Portfolio operators and due-diligence teams

Add technical hygiene evidence to a company or asset inventory. The result can help prioritize manual review, but it is not proof of domain ownership, control, legal identity, solvency, security compliance or acquisition risk.

Five products you can build with the data

1. Agency prospect audit

Input the domains already in an authorized prospect list. Keep records whose next action is FIX_TLS_CERTIFICATE, ENFORCE_DMARC_POLICY, PUBLISH_SPF_POLICY, CONFIRM_EMAIL_INTENT_OR_CONFIGURE_MX or RESTORE_DNS_RESOLUTION. Attach the relevant record and timestamp to the account note. Do not send a generic “your site is broken” message: use the evidence to prepare a relevant, human-reviewed conversation.

2. Website launch readiness

Audit production and campaign domains before launch. Verify public DNS resolution, name servers, the trusted port-443 certificate, and the email-authentication posture. A complete high score means the seven configured checks passed at observation time; it does not replace end-to-end application, checkout, form, analytics or deliverability testing.

3. Client portfolio review

Run 20, 50 or 100 client domains on a schedule. Sort by actionPriority, then by ssl.daysLeft. Route critical certificate or DNS findings first, high-priority mail findings next, and keep healthy results as timestamped evidence that no configured issue was observed.

4. CRM company enrichment

Join the result by normalized domain or stable entityId. Keep resultId and observedAt for lineage. The enrichment describes the supplied domain only; it does not prove the CRM company owns or controls it. Preserve that relationship as an unverified association unless you have a separate identity source.

5. Migration and vendor handoff QA

Run once before a DNS, email-provider or certificate migration and once after propagation. Compare A/AAAA, MX, NS, SPF, DMARC and TLS fields. Because DNS is cached and distributed, review timestamps and repeat after the expected propagation window before declaring success or rollback.

What the Actor observes

LayerDirect observationWhat it can supportWhat it cannot prove
DNS addressA and AAAA answersthe name resolves at check timethe application works
DNS authorityNS answersauthoritative servers are publishedregistrar access or ownership
Email routingMX answers and Null MXmail route exists, or mail is explicitly refuseda mailbox exists or accepts a message
SPFTXT records starting with v=spf1one SPF policy is publishedevery sender is correctly authorized
DMARC_dmarc TXT starting with v=DMARC1exact organizational p policyalignment rates or enforcement outcomes
TLSlive handshake on port 443certificate, issuer, trust and expiry observedwebsite content, uptime SLA or vulnerability status
Decision layerdeterministic interpretation of the observationsreview priority and next actionpermission to change production automatically

No WHOIS, backlink, reputation, blacklist, page-content, vulnerability, port-range or mailbox probe is performed.

Quick start

  1. Click Try for free.
  2. Paste one to 100 domains into Domains.
  3. Leave Max concurrency at 10 unless you need a slower or faster bounded run.
  4. Start the Actor.
  5. Open Dataset for evidence cards and OUTPUT for run completeness and billing reconciliation.

Input accepts a domain or an HTTP(S) URL. Scheme, path, query, trailing dot and leading www. are normalized away. Semantic duplicates are audited once and counted in OUTPUT.duplicateItemCount.

{
"domains": [
"apify.com",
"https://www.example.com/pricing",
"github.com"
],
"maxConcurrency": 10
}

Runtime validation is intentionally stricter than silent JavaScript coercion:

  • every item must be a real string;
  • input must contain 1–100 items;
  • custom ports, embedded credentials, IP literals and control characters are rejected;
  • only HTTP(S) URL syntax is accepted when a scheme is present;
  • concurrency must be an integer from 1 to 50, not the string "10";
  • Unicode domain names are normalized to their ASCII/Punycode DNS representation.

Example evidence card

The structure below is illustrative. DNS records, certificate dates, scores and actions change over time; always use the values from your own run.

{
"schemaVersion": "1.0.0",
"entityId": "68d2e...stable-domain-id",
"resultId": "4f5a1...observation-id",
"domain": "brand.example",
"found": true,
"error": null,
"checkedAt": "2026-08-11T03:00:00.000Z",
"observedAt": "2026-08-11T03:00:00.000Z",
"auditState": "complete",
"healthScore": 71,
"resolves": true,
"records": {
"a": ["203.0.113.10"],
"aaaa": [],
"mx": ["mail.brand.example"],
"ns": ["ns1.provider.example", "ns2.provider.example"],
"wwwCname": []
},
"email": {
"canReceive": true,
"nullMx": false,
"spf": "v=spf1 include:sender.example -all",
"spfRecordCount": 1,
"dmarc": "v=DMARC1; p=none; rua=mailto:dmarc@brand.example",
"dmarcRecordCount": 1,
"dmarcPolicy": "none"
},
"ssl": {
"issuer": "Example CA",
"validTo": "2026-11-30T23:59:59.000Z",
"daysLeft": 111,
"authorized": true,
"authorizationError": null,
"observedAddressFamily": 4
},
"issues": [
"DMARC policy is \"none\" — monitoring only; failing mail is not quarantined or rejected."
],
"confidence": {
"score": 100,
"level": "high",
"basis": "all_required_dns_and_tls_sources_observed"
},
"recommendedAction": "ENFORCE_DMARC_POLICY",
"actionPriority": "high",
"safeToAutomate": false,
"billing": {
"billable": true,
"eventName": "result-found",
"unit": "one_unique_requested_complete_domain_health_audit_delivered"
}
}

How the score works

The score is the percentage of seven deterministic checks that pass:

CheckPass condition
DNS resolutionat least one A or AAAA answer is observed
Email routingat least one non-empty, non-Null-MX exchanger is observed
SPFexactly one v=spf1 policy is observed
DMARC enforcementexactly one DMARC record has p=quarantine or p=reject
TLS trusta port-443 certificate is observed and Node's trust evaluation authorizes it
TLS runwaythe authorized certificate has more than 30 whole days remaining
DNS authorityat least one NS answer is observed

Each check has equal weight. Seven passes produce 100; five passes produce 71. The score is not a security grade, SEO grade, deliverability grade or legal-compliance grade. It is a compact summary of these seven configured public observations.

The Actor does not publish a score if a required source is unavailable or the resolved TLS target is unsafe. In those cases healthScore is null, auditState is partial or blocked, confidence is unknown, and the row is free.

Source-state contract

StateMeaningScoreBillingRecommended handling
completeevery required DNS/TLS source returned a known observation0–100paid when deliveredreview evidence and next action
partialat least one required source had timeout, SERVFAIL, lookup failure or ambiguous transportnullfreeretry after source recovery
blockedthe domain resolved to a private, loopback, link-local, metadata or reserved addressnullfreeinspect the input and public DNS target
withheldsource work completed but the run maximum charge could not cover deliverynullfree noticeincrease the run maximum charge

Known absence is different from source failure. For example, a clean NXDOMAIN/NODATA response is a complete, actionable observation: the name does not resolve. A resolver timeout or SERVFAIL is unknown and cannot honestly be sold as “the domain is down.”

The same principle applies to email and TLS:

  • a published Null MX is known evidence that the domain explicitly does not accept email;
  • an unavailable MX resolver is not evidence that MX is missing;
  • a refused port 443 with no certificate observed is a point-in-time negative observation;
  • a TLS timeout or network-path error is incomplete evidence and produces no score;
  • a certificate can be present but unauthorized; presence alone does not pass the trust checks.

Known and unknown evidence follow different delivery paths

ActionTriggerHuman follow-up
RESTORE_DNS_RESOLUTIONno A/AAAA records are knownverify zone, delegation, recent expiry or migration
FIX_TLS_CERTIFICATEuntrusted, expired or near-expiry certificateinspect SNI, hostname, chain and renewal path
CONFIRM_EMAIL_INTENT_OR_CONFIGURE_MXno usable MX or Null MXdetermine whether the domain should receive mail
ENFORCE_DMARC_POLICYDMARC missing or p=noneinventory senders, validate alignment, then phase enforcement
PUBLISH_SPF_POLICYreceiving domain has MX but no SPFinventory authorized senders before publishing one record
REVIEW_DOMAIN_HEALTH_FINDINGSanother verified configured issue existsinspect issues, evidence and source states
RETRY_AFTER_SOURCE_RECOVERYrequired source unavailableretry; do not turn the gap into a customer claim
REVIEW_INPUT_AND_PUBLIC_DNS_TARGETunsafe resolved destination blockedcorrect public DNS/input; private-network audit is out of scope
INCREASE_RUN_MAXIMUM_CHARGEresult delivery withheld by the buyer capraise the run cap and submit intentionally
MONITOR_DOMAIN_HEALTHno configured issue observedretain timestamp and schedule the next review

safeToAutomate is always false. The action is a routing recommendation, not authorization to edit DNS, rotate certificates, change mail policy, contact a prospect, or create a compliance claim.

Field dictionary

Identity and lineage

FieldMeaning
schemaVersionadditive commercial contract version
domainnormalized unique public DNS name
entityIdstable 24-character hash for the normalized domain
resultIdstable hash for this domain plus observation timestamp
checkedAt, observedAtwhen the source collection started
foundtrue only when a complete audit is available; known NXDOMAIN remains a complete answer
errorfree-outcome explanation when a complete audit cannot be asserted

DNS and email

FieldMeaning
records.a, records.aaaaobserved address answers
records.nsobserved authoritative name servers
records.mxpriority-sorted usable mail exchangers; Null MX is excluded
records.wwwCnameCNAME answers for www.<domain>
email.canReceiveat least one usable, non-Null-MX route exists
email.nullMxan explicit empty/root MX target was observed
email.spffirst observed SPF string for compatibility
email.spfRecordCountnumber of SPF records; more than one is invalid
email.dmarcfirst observed DMARC string for compatibility
email.dmarcRecordCountnumber of DMARC records; more than one is ambiguous
email.dmarcPolicyexact organizational p tag, never accidentally parsed from sp

TLS

FieldMeaning
ssl.issuercertificate issuer organization or common name
ssl.validToparsed certificate expiry timestamp
ssl.daysLeftwhole days until expiry; negative after expiry
ssl.authorizedNode trust evaluation for the observed certificate and hostname
ssl.authorizationErrortrust error when authorization fails
ssl.observedAddressFamily4 or 6 for the pinned verified connection

Decision and uncertainty

FieldMeaning
auditStatecomplete, partial, blocked or withheld
healthScore0–100 for complete audits; otherwise null
issuesverified interpretations of known observations
sourceStatusstate, error and timestamp for each source
evidencesource name, query, state, error and observation time
dataGapsunavailable evidence plus product limitations
confidencehigh only for complete required-source coverage; otherwise unknown
recommendedActiondeterministic review route
actionPrioritycritical, high, medium or low
safeToAutomatealways false
billingwhether the delivered row is billable and the exact unit name

OUTPUT run receipt

Dataset rows answer “what was observed for this domain?” The OUTPUT record answers “did the run deliver everything safely?” Check both before downstream automation.

{
"schemaVersion": "1.0.0",
"status": "PARTIAL",
"requestedItemCount": 4,
"uniqueItemCount": 3,
"duplicateItemCount": 1,
"sourceCompleteCount": 2,
"sourceFailureCount": 1,
"deliveredRowCount": 3,
"paidRowCount": 2,
"freeRowCount": 1,
"localRowCount": 0,
"withheldRowCount": 0,
"budgetStopped": false,
"fatal": null,
"replaySafe": true,
"billingUnit": "one_unique_requested_complete_domain_health_audit_delivered"
}

Interpretation:

  • SUCCEEDED: every unique source audit was complete and delivered;
  • PARTIAL: at least one free source-failure row or budget-withheld notice exists;
  • FAILED: Dataset/PPE delivery, free Dataset delivery, or budget-state reading became ambiguous;
  • replaySafe: false: do not blindly retry because a Dataset/PPE operation may have crossed the network boundary without an exact receipt.

Billing

This Actor uses pay-per-event pricing. On the Free Apify tier, the current unit price is:

  • one Actor start event at $0.005; the Actor is pinned to 512 MB, so one normal run start maps to one start event;
  • one result-found event at $0.005 per unique requested complete domain audit delivered.

Volume account tiers reduce both event rates; the live Apify pricing panel is authoritative for your account. At the Free-tier event rate, 100 complete unique audits are about $0.505 including one start. Duplicates do not create another audit. Partial, blocked and withheld outcome rows are free. Known NXDOMAIN is billable because “this domain does not resolve” is a complete direct answer, not a source failure.

The runtime verifies pricing before source work, checks the buyer's maximum charge before each paid delivery, links Dataset delivery and the result-found event in one operation, and requires an exact receipt for both operations. Ambiguous delivery is fatal and recorded in OUTPUT.

API access

JavaScript

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('zinin/domain-health-checker').call({
domains: ['example.com', 'apify.com'],
maxConcurrency: 5,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
const output = await client.keyValueStore(run.defaultKeyValueStoreId).getRecord('OUTPUT');
if (output.value.replaySafe !== true || output.value.fatal) {
throw new Error('Review the run receipt before retrying or importing results.');
}
console.log(items);

Python

import os
from apify_client import ApifyClient
client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('zinin/domain-health-checker').call(run_input={
'domains': ['example.com', 'apify.com'],
'maxConcurrency': 5,
})
rows = client.dataset(run['defaultDatasetId']).list_items().items
output = client.key_value_store(run['defaultKeyValueStoreId']).get_record('OUTPUT')['value']
print(output['status'], len(rows))

REST

curl -X POST \
"https://api.apify.com/v2/acts/zinin~domain-health-checker/runs?token=$APIFY_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"domains":["example.com","apify.com"],"maxConcurrency":5}'

Keep tokens in environment variables or a secret store. Never paste a production token into a README, shared spreadsheet or browser-visible URL.

Automation recipes

Google Sheets or Airtable review queue

  1. Schedule the Actor.
  2. Export the Dataset through Make, Zapier, n8n or a small API job.
  3. Upsert by resultId for immutable observations or entityId for latest-domain state.
  4. Expose domain, score, priority, action, first issue, observed time and source state.
  5. Require a human checkbox before any client outreach or production change.

Slack or email exception digest

Filter complete rows to actionPriority in critical and high. Send a digest with evidence and timestamp. Route partial/blocked rows to an operational retry queue, not the client-alert channel.

CRM enrichment

Store entityId, resultId, the supplied-domain relationship, score, action and evidence URL. Do not overwrite verified company identity or ownership fields with a domain observation.

Certificate review

Sort complete rows by ssl.daysLeft, but also require ssl.authorized === true. A long expiry on an untrusted certificate is not a healthy TLS result.

Email-authentication review

Inspect record counts before policy. Multiple SPF or DMARC records are configuration defects. For DMARC rollout, inventory authorized senders and alignment before moving from none to enforcement. The Actor reports evidence; it does not design the safe rollout for you.

Security and privacy boundaries

The buyer submits public domain names. The Actor performs public DNS queries and a TLS handshake on port 443. Before the handshake, every resolved address is checked; private, loopback, link-local, metadata, documentation, multicast and reserved destinations are refused, and the connection is pinned to a verified address to close DNS-rebinding gaps.

The Actor does not:

  • accept IP-literal input or custom ports;
  • scan port ranges or private networks;
  • read website bodies, cookies, accounts or authenticated pages;
  • access registrar, DNS-provider or mailbox credentials;
  • call another Actor, CRM, messaging recipient or buyer-controlled write endpoint;
  • require an API key besides the normal Apify runtime authorization used by the caller;
  • claim a domain is owned by the company whose CRM record contains it.

DNS records and certificates may contain operational names or reporting addresses. Treat exported results according to your own data-retention and access-control policy.

Limitations

  • DNS is distributed and cached; results are observations from the Actor's resolver at one time.
  • The Actor does not follow DNS propagation globally or query every authoritative server.
  • TLS is checked on port 443 with SNI for the normalized domain; other ports are out of scope.
  • A successful handshake does not prove the web application is healthy.
  • ssl.authorized describes the observed trust evaluation; it is not a vulnerability assessment.
  • SPF presence does not validate every include chain or guarantee legitimate sender coverage.
  • DMARC presence and policy do not report alignment rates, aggregate-report history or inbox results.
  • MX presence does not prove a particular address exists or can accept a message.
  • The score weights seven configured checks equally; your business risk model may weight them differently.
  • A known negative observation can change after DNS, mail or certificate updates.
  • The Actor is not a substitute for security testing, legal review, KYC, ownership verification, deliverability testing or change authorization.

Troubleshooting

auditState is partial

Open sourceStatus and dataGaps. Resolver timeouts, SERVFAIL, network errors and ambiguous TLS transport remain unknown. Retry later. Do not turn a partial row into a prospect claim.

auditState is blocked

The public name resolved to an unsafe destination. Verify the input and public DNS. Private-network audits are intentionally out of scope.

healthScore is null

This is expected for partial, blocked and withheld rows. A number would imply completeness the Actor does not have.

email.canReceive is false but MX exists in another tool

Inspect email.nullMx, the exact observation time and source state. A root/empty MX target is Null MX, an explicit declaration that the domain does not receive email. DNS propagation can also cause time-sensitive differences.

DMARC policy looks different from sp=

The score uses the organizational p= tag. sp= is a separate subdomain policy and must not be mistaken for p.

TLS exists but the score is lower than expected

Certificate presence and certificate trust are separate. Inspect ssl.authorized, ssl.authorizationError and ssl.daysLeft.

Fewer paid rows than unique inputs

Check OUTPUT.sourceFailureCount, freeRowCount, withheldRowCount, budgetStopped and fatal. Only complete unique audits delivered with an exact linked receipt are paid.

Can I automatically fix DNS or DMARC from the action field?

No. safeToAutomate is false by design. Review the evidence, confirm ownership and intended configuration, coordinate with the responsible operator, and use a separately authorized change workflow.

ActorAdd it when you need
Social Preview Checkerthe title, description and image shown when a public page is shared
AI Crawler Access Checkerrobots.txt and llms.txt evidence for AI crawler policy reviews
AI Overview Citation Trackerevidence about which domains are cited for tracked queries
LLM Brand Visibility Trackerbrand and competitor observations in model answers
Website Contact Extractorpublic website contact evidence after domain qualification

FAQ

Does this scan for vulnerabilities? No. It observes configured public DNS records and one TLS handshake on port 443.

Does it use WHOIS? No.

Does it prove a company owns a domain? No. The Actor audits the supplied domain. Ownership and legal identity require separate evidence.

Does MX mean an email address is valid? No. MX is domain-level routing evidence, not mailbox verification.

Does SPF or DMARC guarantee inbox placement? No. The Actor reports published policy evidence, not sending alignment, reputation, content or recipient behavior.

Why is known NXDOMAIN paid? A clean DNS absence is a complete direct answer and supports the RESTORE_DNS_RESOLUTION action. A resolver failure is unknown and free.

Why are partial rows free? The product sells complete domain-health audits, not attempts or confident-looking guesses produced during a source outage.

Can I run it for subdomains? Yes, if the normalized input is a public DNS name with a valid suffix. Remember that organizational DMARC policy semantics can differ for subdomains; review the records rather than assuming legal or administrative boundaries.

Can an AI agent call it? Yes, through the Apify API, SDK or MCP integration. Keep the human review boundary: safeToAutomate remains false.

How many domains per run? One to 100 requested items, with semantic duplicates audited once.

What should I store? At minimum: domain, entityId, resultId, observedAt, auditState, healthScore, recommendedAction, actionPriority, evidence/source state and the run OUTPUT.


Built by zinin. Questions or a reproducible wrong result? Use the issue link on the Actor page and include the normalized domain, resultId, observation timestamp and the specific field you expected to differ. Do not include passwords, private DNS data or API tokens.