Domain Health Checker
Pricing
from $4.25 / 1,000 domain health evidence cards
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
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
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.

The result in one sentence
For each unique requested domain, the Actor returns a timestamped evidence card with:
- A, AAAA, NS, MX and
wwwCNAME 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
OUTPUTreceipt 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:
- export the domains of target companies from your CRM;
- audit them in one run;
- filter for
actionPriorityequal tocriticalorhigh; - review the underlying DNS/TLS evidence;
- 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
| Layer | Direct observation | What it can support | What it cannot prove |
|---|---|---|---|
| DNS address | A and AAAA answers | the name resolves at check time | the application works |
| DNS authority | NS answers | authoritative servers are published | registrar access or ownership |
| Email routing | MX answers and Null MX | mail route exists, or mail is explicitly refused | a mailbox exists or accepts a message |
| SPF | TXT records starting with v=spf1 | one SPF policy is published | every sender is correctly authorized |
| DMARC | _dmarc TXT starting with v=DMARC1 | exact organizational p policy | alignment rates or enforcement outcomes |
| TLS | live handshake on port 443 | certificate, issuer, trust and expiry observed | website content, uptime SLA or vulnerability status |
| Decision layer | deterministic interpretation of the observations | review priority and next action | permission to change production automatically |
No WHOIS, backlink, reputation, blacklist, page-content, vulnerability, port-range or mailbox probe is performed.
Quick start
- Click Try for free.
- Paste one to 100 domains into Domains.
- Leave Max concurrency at 10 unless you need a slower or faster bounded run.
- Start the Actor.
- 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:
| Check | Pass condition |
|---|---|
| DNS resolution | at least one A or AAAA answer is observed |
| Email routing | at least one non-empty, non-Null-MX exchanger is observed |
| SPF | exactly one v=spf1 policy is observed |
| DMARC enforcement | exactly one DMARC record has p=quarantine or p=reject |
| TLS trust | a port-443 certificate is observed and Node's trust evaluation authorizes it |
| TLS runway | the authorized certificate has more than 30 whole days remaining |
| DNS authority | at 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
| State | Meaning | Score | Billing | Recommended handling |
|---|---|---|---|---|
complete | every required DNS/TLS source returned a known observation | 0–100 | paid when delivered | review evidence and next action |
partial | at least one required source had timeout, SERVFAIL, lookup failure or ambiguous transport | null | free | retry after source recovery |
blocked | the domain resolved to a private, loopback, link-local, metadata or reserved address | null | free | inspect the input and public DNS target |
withheld | source work completed but the run maximum charge could not cover delivery | null | free notice | increase 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.

Recommended actions
| Action | Trigger | Human follow-up |
|---|---|---|
RESTORE_DNS_RESOLUTION | no A/AAAA records are known | verify zone, delegation, recent expiry or migration |
FIX_TLS_CERTIFICATE | untrusted, expired or near-expiry certificate | inspect SNI, hostname, chain and renewal path |
CONFIRM_EMAIL_INTENT_OR_CONFIGURE_MX | no usable MX or Null MX | determine whether the domain should receive mail |
ENFORCE_DMARC_POLICY | DMARC missing or p=none | inventory senders, validate alignment, then phase enforcement |
PUBLISH_SPF_POLICY | receiving domain has MX but no SPF | inventory authorized senders before publishing one record |
REVIEW_DOMAIN_HEALTH_FINDINGS | another verified configured issue exists | inspect issues, evidence and source states |
RETRY_AFTER_SOURCE_RECOVERY | required source unavailable | retry; do not turn the gap into a customer claim |
REVIEW_INPUT_AND_PUBLIC_DNS_TARGET | unsafe resolved destination blocked | correct public DNS/input; private-network audit is out of scope |
INCREASE_RUN_MAXIMUM_CHARGE | result delivery withheld by the buyer cap | raise the run cap and submit intentionally |
MONITOR_DOMAIN_HEALTH | no configured issue observed | retain 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
| Field | Meaning |
|---|---|
schemaVersion | additive commercial contract version |
domain | normalized unique public DNS name |
entityId | stable 24-character hash for the normalized domain |
resultId | stable hash for this domain plus observation timestamp |
checkedAt, observedAt | when the source collection started |
found | true only when a complete audit is available; known NXDOMAIN remains a complete answer |
error | free-outcome explanation when a complete audit cannot be asserted |
DNS and email
| Field | Meaning |
|---|---|
records.a, records.aaaa | observed address answers |
records.ns | observed authoritative name servers |
records.mx | priority-sorted usable mail exchangers; Null MX is excluded |
records.wwwCname | CNAME answers for www.<domain> |
email.canReceive | at least one usable, non-Null-MX route exists |
email.nullMx | an explicit empty/root MX target was observed |
email.spf | first observed SPF string for compatibility |
email.spfRecordCount | number of SPF records; more than one is invalid |
email.dmarc | first observed DMARC string for compatibility |
email.dmarcRecordCount | number of DMARC records; more than one is ambiguous |
email.dmarcPolicy | exact organizational p tag, never accidentally parsed from sp |
TLS
| Field | Meaning |
|---|---|
ssl.issuer | certificate issuer organization or common name |
ssl.validTo | parsed certificate expiry timestamp |
ssl.daysLeft | whole days until expiry; negative after expiry |
ssl.authorized | Node trust evaluation for the observed certificate and hostname |
ssl.authorizationError | trust error when authorization fails |
ssl.observedAddressFamily | 4 or 6 for the pinned verified connection |
Decision and uncertainty
| Field | Meaning |
|---|---|
auditState | complete, partial, blocked or withheld |
healthScore | 0–100 for complete audits; otherwise null |
issues | verified interpretations of known observations |
sourceStatus | state, error and timestamp for each source |
evidence | source name, query, state, error and observation time |
dataGaps | unavailable evidence plus product limitations |
confidence | high only for complete required-source coverage; otherwise unknown |
recommendedAction | deterministic review route |
actionPriority | critical, high, medium or low |
safeToAutomate | always false |
billing | whether 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-foundevent 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 osfrom apify_client import ApifyClientclient = 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().itemsoutput = 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
- Schedule the Actor.
- Export the Dataset through Make, Zapier, n8n or a small API job.
- Upsert by
resultIdfor immutable observations orentityIdfor latest-domain state. - Expose domain, score, priority, action, first issue, observed time and source state.
- 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.authorizeddescribes 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.
Related Actors
| Actor | Add it when you need |
|---|---|
| Social Preview Checker | the title, description and image shown when a public page is shared |
| AI Crawler Access Checker | robots.txt and llms.txt evidence for AI crawler policy reviews |
| AI Overview Citation Tracker | evidence about which domains are cited for tracked queries |
| LLM Brand Visibility Tracker | brand and competitor observations in model answers |
| Website Contact Extractor | public 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.