MCP documentation menu

Domain Health Report Fields

The field reference for the report datapulse_live_domain_health returns in raw_output. For what the tool does, how to call it and how to read the verdict, see datapulse_help(topic="domain_health").

Conventions

  • Arrays are always present, never null; an empty list is []. Booleans are always present.

  • The report distinguishes “we looked and the answer is no” from “we could not tell”, everywhere. Several checks can come back not-determined, and each says so in its own way:

    FieldNot determined as
    nameservers.serials_consistentnull
    nameservers.ipv4_prefixes_24, ipv6_prefixes_48null
    wildcard.consistentnull
    caa.hosts.*.permittedabsent, with note saying why
    mail.dmarc.unresolvedtrue
    wildcard.status"unknown"
    tlsa.result"unknown"
    hsts_preload"unknown", with hsts_preload_error
    dns.resolver_reachable.*a skipped: string

    Not determined is neither the good case nor the bad one. Branch three ways.

    Both shortcuts are wrong, in opposite directions. Folding null into the pass reports a clean audit for a run that checked nothing. Folding it into the fail is worse: if serials_consistent is not true then the servers disagree turns “no nameserver answered” into “the nameservers disagree with each other”, which is an affirmative finding someone will act on. The same inversion hides in if prefixes == 0 then there is no diversity and in if wildcard.status != "present" then there is no wildcard, which folds unknown into absent.

    if serials_consistent is null:  not determined — say so, or omit the finding
    elif serials_consistent:        the serials agree
    else:                           the serials disagree
    
  • wildcard.status is the same three-way choice carried as a value rather than a null: present, absent, unknown.

  • An object is omitted only when the whole check did not apply: mail and nameservers for a name that is not a zone apex, mail also for a name that cannot receive mail at all (one carrying reserved_name or public_suffix, or one that does not exist), web.www for anything that is not a registrable domain, glue when the parent could not be asked, tls when 443 did not answer, quic when the probe was not run, hsts when no header was served, web.apex / web.www (and web itself, as {}) when the name resolved to no usable addresses.

  • Optional scalars appear only when they have a value: unicode_domain, not_a_zone, enclosing_zone, reserved_addresses, hsts_preload_covered_by, hsts_preload_policy, hsts_preload_error, cname, retries, ede, detail, parent_only, child_only, error.

  • Warning and error strings are stable; key on them by prefix (apex: certificate expired, www (ipv4): redirect chain, nameserver <name>:, resolver returned SERVFAIL:, apex: CAA records do not permit, MTA-STS:, DKIM selector, HSTS).

  • Findings are per host and cause, not per address, and carry a count: apex: certificate expired on 1 of 1 addresses: ..., apex: certificate handshake failed on 7 of 7 addresses: .... No address appears in a finding. Which address failed is in the web section, under web.apex.ipv4[].tls and its IPv6 equivalent. The nameserver findings already had this shape.

  • Error text from a probe carries only the condition, not the socket that hit it: i/o timeout, not read tcp4 10.12.60.35:46962->80.245.156.34:443: i/o timeout. That applies to tls.error, the HTTP result error and the MTA-STS fetch error as well as the finding text, so two runs that failed the same way now compare equal instead of differing by an ephemeral port.

Top level

KeyTypeMeaning
domainstringA-label of the probed name
unicode_domainstringU-label, IDN only
not_a_zone, enclosing_zonebool, stringPresent when the name is a host inside a zone; enclosing_zone when a SOA revealed it
resolverstringResolver used for validated lookups (127.0.0.1:8053 in production)
familieslistAddress families used for the web probes: ipv4, ipv6
timeout_sec, tcp_timeout_sec, quic_timeout_secintProbe budgets
dns_concurrencyintHow many DNS helper processes the run was allowed in flight at once (0 means unlimited). Set by the worker, not by the caller; it bounds load, not results, so two runs of the same domain under different caps produce the same report
dnsobjectapex and www maps keyed by record type, plus resolver_reachable
dnssecobjectstate, ds, dnskey, optional ede, detail
delegationobjectstatus, parent_ns, parent_server, child_ns, child_server, optional parent_only, child_only, error
webobjectapex and www host objects, or {}. www is probed only for a registrable domain, one label below a public suffix: www.jeff.co.uk is a name someone would configure, www.old.reddit.com is one only this tool would ever ask for
mailobjectMail posture. Absent for a non-apex, reserved, nonexistent name or a public suffix
nameserversobjectNameserver audit (zone apexes only)
caaobjectCAA verdict per host
tlsaobjectDANE verdict
wildcardobjectWildcard detection
reserved_addresseslistAddresses in reserved ranges, when any
public_suffixboolThe name is itself a public suffix, such as com or co.uk. Mail is skipped for it, because a missing DMARC record on a registry’s own TLD is advice nobody can act on, and web.www is absent. Private suffixes such as github.io are ordinary domains their owners operate and keep their mail checks
reserved_namestringThe RFC reserving this name, for suffixes outside the global DNS: invalid, test, localhost, example (RFC 6761), local (RFC 6762), onion (RFC 7686), home.arpa (RFC 8375). Such a name never resolves by definition, so dnssec.state reads unknown rather than bogus, delegation and zone checks are skipped, and one warning explains why. example.com and its siblings are reserved for documentation but are really delegated, so they are checked like any other domain
hsts_preloadstringpreloaded (browsers enforce HSTS for this name), absent (list consulted, name not covered), unknown (list could not be obtained)
hsts_preload_covered_bystringThe ancestor entry whose includeSubDomains makes this name preloaded, when it is not the name itself
hsts_preload_policystringChromium’s policy for the covering entry, when preloaded. bulk-legacy, bulk-18-weeks, bulk-1-year: submitted through hstspreload.org, must keep serving a compliant header, and warn when they do not. google, custom, public-suffix, public-suffix-requested, test: kept by hand, no header owed, never warn
hsts_preload_errorstringWhy the list could not be obtained, when hsts_preload is unknown
errors, warningslistFindings; see “Reading the verdict”
okbooltrue when errors is empty
elapsed_msintProbe wall time

dns

Each entry under dns.apex (keys A, AAAA, MX, NS, TXT) and dns.www (A, AAAA) has status (ok, nxrrset, nxdomain, failure, timeout), trust (secure, insecure, bogus), records (rdata strings, when any), and optionally cname (chain followed), error, retries (a query retried after a timeout, the same key the nameserver audit uses). dns.resolver_reachable maps ipv4 / ipv6 to yes, no, or a string starting with skipped that names the reason. It measures the configured resolver, not the domain being probed: the check is exempt from dns_concurrency, so a target whose own nameservers hang cannot starve it and make a healthy resolver read no.

web

web.apex and web.www each have:

KeyTypeMeaning
ipv4, ipv6listOne address entry per address
same_as_apexboolwww resolves to exactly the apex’s addresses (www only)
(no www key)—web.www is present only for a registrable domain. For a host inside a zone, a CNAMEd name or a public suffix there is no www anyone would configure, and asking for one invited a catch-all answer served with a certificate that could not cover the extra label, reported as a hostname mismatch on a healthy site
via_wildcardboolwww is answered by the zone’s wildcard (www only)
redirectsobjectPer family (ipv4, ipv6): hops (url, status), ended, final_url, external (target outside apex/www, not followed), loop, error. Read ended, not the absence of final_url. It says why the chain stopped: final (a terminal response, with final_url set), external (the next hop left the zone and was deliberately not followed), loop, hop_limit or error. A chain that hands off externally is finished rather than truncated, and its last status is the redirect that left rather than a terminal 200, so without ended a healthy domain such as github.io looks broken
cert_consistentboolAll addresses of this host served the same certificate

Each address entry:

KeyTypeMeaning
ipstringThe address
80, 443stringopen, refused, timeout, unreachable, error, skipped (reserved address)
http, httpsobjectOne GET /: status, location, server, hsts (max_age, include_subdomains, preload), error
tlsobjectchain (the headline defect), chain_problems (every defect, headline first), version, alpn, cipher, tls10, tls11 (legacy protocol accepted), cert, chain_length, error
tls.certobjectsubject, issuer, not_before, not_after, days_remaining (negative when expired), sans, covers_apex, covers_www, wildcard, key, fingerprint_sha256. issuer is whatever the served chain says, and CAs rotate intermediates: Let’s Encrypt now issues from YR1, YR2 and YE2 rather than the older R and E series, so an unfamiliar name there is not itself a finding. chain is what says whether the chain verified
tlsastringmatch, mismatch, none — only when TLSA records exist
quicobjectsupported, alpn, tls_version, server_addr, handshake_ms, error; on a failure (reports since 2026-09-15) also reason — timeout, tls_rejected, resolve_failed, version_negotiation, stateless_reset, transport_error, application_error, listen_failed, invalid_args or other — and, for tls_rejected, tls_alert (e.g. “handshake failure”) and tls_alert_code (e.g. 40). A CDN with HTTP/3 disabled reads tls_rejected with alert 40; a host that drops UDP reads timeout

What the TLS verdict covers, and what it does not. chain names the single most urgent defect; chain_problems lists every one of them, headline first. The badssl fallback certificate is both expired and served for a name it does not cover, and reads chain: "expired" with chain_problems: ["expired", "hostname_mismatch"]. Key on chain for a headline and iterate chain_problems before telling anyone the certificate is fixed, because renewing on the strength of chain alone would leave the site broken.

incomplete_chain and untrusted_root are close together and easy to confuse. incomplete_chain means the server did not send the intermediate, but the certificate’s AIA URL was fetched and that repair produced a chain that verifies. The URL is named in tls.error on the affected address, and only there: there is no AIA field on tls.cert. untrusted_root means the chain does not verify even with the intermediate supplied, whether or not an AIA fetch succeeded. The distinction cannot be read off the issuer’s name, because a certificate can be issued by a CA whose name is well known under a root no trust store carries.

valid and incomplete_chain differ in who has to do the repair, and that decides which clients break. A browser generally fetches the missing intermediate itself, so an incomplete chain often looks fine in Chrome while failing in curl, Java and some mobile clients. One address of a host can be misconfigured while its sibling is correct, so the same name can report valid and incomplete_chain at once, which is why every address is probed rather than one.

Live examples of incomplete_chain are transient by nature: a domain observed serving one certificate on one address may be repaired within hours, and un.org was fixed on 2026-09-07 between two probes. Treat a public domain as a snapshot, not a fixture.

valid means the chain as served verified against the trust store at probe time, with no repair needed. It is not a statement about revocation, which is not checked, so a revoked certificate whose chain is intact reports valid. cert.key and the signature algorithm are reported but not judged: there is no weak-key or weak-signature finding, so a 1024-bit RSA key appears in the output without a warning attached.

mail

Present only for a name that could configure mail: absent for a host inside a zone, for a reserved name, and for a name that does not exist. Its absence is the answer, not a gap.

KeyMeaning
dmarcpresent, unresolved, policy, subdomain_policy, pct, rua (reporting address present), records (count), problems. unresolved is true when the _dmarc lookup did not complete, which is not the same as a domain publishing no DMARC record
spfrecords (count), lookups (DNS-querying terms, limit 10), void_lookups, txt_answer_octets (the apex TXT reply size without EDNS, reports since 2026-09-15; warned past 450 and 512 octets, the RFC 7208 §3.4 UDP limit), all (the all qualifier, e.g. -all), includes, problems
mxOne entry per MX: host, preference, addresses (count), cname, ip_literal, unresolved, problems. A null MX appears as host . with addresses 0. unresolved means the target’s address lookup did not complete, which is a gap in the check rather than a fault in the domain and does not fail it
dkimselectors_found, revoked (selectors publishing an empty key), wildcard. A random selector is probed as a negative control: when it answers, the zone wildcards _domainkey, wildcard is set and no selector is named, because every guess would answer. Selectors cannot be enumerated, so an empty list is a fact, not a finding
mta_stsrecord, id, mode, max_age, mx (policy patterns), policy_ok, mx_covered, error
tls_rptTLS-RPT record present

nameservers (zone apexes only)

KeyMeaning
countDistinct NS names
serversOne entry per NS address: name, ip, aa (answered authoritatively), rcode, serial, no_soa (answered authoritatively with no SOA in an untruncated response, so an absent serial is a recorded fact rather than a missing key; a truncated UDP answer is not counted, since it looks identical in the first message of the audit’s three-query run), tcp, edns, retries (present as 1 when the first audit query went unanswered and a retry succeeded), error

A nameserver’s verdict turns on whether it answered at all, not on how many addresses failed:

ObservedVerdictFinding
Answered but disclaimed authorityError at any countnameserver <name>: not authoritative ...
Silent on every addressErrornameserver <name>: no answer on N of N addresses
Silent on some addressesWarningnameserver <name>: no answer on N of M addresses, the others are authoritative

Answering with REFUSED on one address of nine is proven lameness and stays an error; a node that merely goes quiet while its siblings answer authoritatively is a warning, because a flaky anycast node is not a misconfiguration of the domain. The reason for a silent address is the fixed text no answer, rather than whichever of dig timed out or no servers could be reached arrived first, so the string no longer varies between runs on the same domain. | serials_consistent | Every server reported the same SOA serial, or null when no server answered authoritatively and nothing was compared. true means the serials were actually checked. The drift warning names the address as well as the name, because the disagreeing server is often one node behind an anycast address: aluminium-supplier.com has a node of dns9.hichina.com serving serial 2016081111 while its siblings serve 2026082616, a decade apart | | ipv4_prefixes_24, ipv6_prefixes_48 | Distinct prefixes across all addresses; 1 means no diversity, null means no address was examined | | glue | required (in-bailiwick names), missing, mismatch; omitted when the parent could not be asked, or when no nameserver address was known to compare it against | | ns_cname, unresolvable | NS names that are CNAMEs, or that the resolver said have no address. Both are errors | | unresolved | NS names whose address lookup never completed. A gap in the check rather than a fault in the domain, so it is a warning, not an error |

caa

caa contains hosts and nothing else: one verdict for apex and one for www, each judged against the certificate that host actually served. There is no domain-wide CAA verdict, because a domain need not have one.

KeyMeaning
publishedThe CAA records at that name. [] for a name that publishes none of its own
effectiveThe records that govern the name, after the RFC 8659 climb. A www that publishes nothing shows the apex set here
issuerOrganisation of the certificate that host served
permittedWhether effective allows that issuer
noteWhy no verdict was reached, when permitted is absent

Both arrays are always present. published empty alongside a non-empty effective is how the report says the set was inherited from the apex.

permitted is true when no records govern the name (any CA may issue). It is absent whenever nothing could be judged, and note distinguishes two materially different reasons, which a caller must not collapse:

  • Nothing to check. no certificate observed, because the host serves no TLS, so there is no issuer to compare against the policy. This is by far the common case: in one 49-domain batch all 42 null verdicts were this one. The policy was read fine; there was simply nothing to judge against it.
  • Could not check. The CAA lookup did not complete, so the policy itself is unknown. issuer not in the CAA mapping table is a third, narrower variant of the same idea.

The difference matters because “any CA may issue” is a security-relevant all-clear, and it is never derived from a query that failed. A host with no TLS is unremarkable; a policy that could not be read is a gap in the check.

A wildcard certificate is judged against issuewild when the governing set has one, so a CA that issue permits can still be forbidden for wildcards (RFC 8659 gives issuewild precedence for wildcards).

A CAA identifier need not resemble the issuer’s organisation name. A CA that has acquired other CAs honours each brand’s identifier at issuance, so posteo.de permits geotrust.com and is correctly served a certificate whose organisation reads DigiCert Inc, DigiCert having acquired GeoTrust. Reading caa.hosts.*.issuer beside published will therefore turn up pairs that look mismatched and are not, and the verdict in permitted accounts for the brands each CA issues under. Do not re-derive it by comparing the two strings yourself.

Two hosts can reach opposite verdicts from one CAA set, and that is not a bug. apache.org permits Let’s Encrypt at the apex and forbids it at www, from the same effective records and the same issuer. The apex is served a non-wildcard certificate, judged against issue, while www.apache.org is served *.apache.org, judged against issuewild, and the zone publishes issuewild "ssl.com" only. When two hosts disagree, check whether the served certificate is a wildcard before concluding the verdict is wrong.

tlsa

KeyMeaning
apex, www_443._tcp TLSA records as published
signedThe TLSA answers, positive or negative, were DNSSEC-validated. In a signed zone this is true even with result: none, because the denial itself is signed
resultnone (looked up, no TLSA records exist), match, mismatch, unverified, unknown (the lookup did not complete, so whether DANE is configured is unknown; signed is false because nothing was validated)

A domain where nothing could be determined

On 2026-09-07, while its nameservers were down, microsoft.jp.net fired every not-determined path at once. An earlier build asserted from those four failed lookups that it publishes no DMARC record, that any CA may issue for it, that it has no DANE, and that it has no wildcard. The same outage now yields mail.dmarc.unresolved, caa.hosts.*.permitted absent, tlsa.result: "unknown" and wildcard.status: "unknown", while still failing on what was actually observed: nameservers answering nothing, and www lookups timing out. Four confident negatives became four honest unknowns without losing a single real error.

Its nameservers have since recovered, so probing it today returns ordinary answers. That is the nature of live examples, and the reason this one is dated.

wildcard

Whether the zone answers names that were never published, tested by looking up random 12-letter labels.

KeyMeaning
statuspresent (three random names all answered), absent (one was definitively denied, or an answer already in hand settled it, such as www NXDOMAIN), unknown (a probe never came back)
determined_byWhy the verdict was reached, in words: 3 random names all answer, the random name qhrmzvbxklap is denied
probesOne entry per random name actually issued: label, status (answered, denied, unresolved), addresses, optional cname. Its length is how much evidence the verdict rests on: 0 when an answer was already in hand, 1 when the first name was denied, 3 for a confirmed wildcard
addressesWhat the wildcard answers with, when there is one
consistentnull unless status is present; true when all three probes returned the same addresses and CNAME
www_via_wildcardwww resolves to exactly the wildcard’s addresses, so it is a catch-all answer rather than a real host

unknown is the reason this is a tri-state. A single present: false previously covered NXDOMAIN, NODATA, timeout and failure alike, so a lookup that quietly failed was indistinguishable from a clean zone. Do not render unknown as false.

A wildcard on its own raises no warning; only www_via_wildcard produces one. It is data to score, not a fault. consistent: false is worth scoring separately, since a catch-all that rotates its answers is a different shape from a stable one.

Enumerations

FieldValues
dns.*.*.statusok, nxrrset, nxdomain, failure, timeout
dns.*.*.trustsecure, insecure, bogus
dns.resolver_reachable.*yes, no, skipped: resolver has no <family> address
dnssec.statesecure, insecure, island (DNSKEY but no DS), bogus, servfail, unknown
delegation.statusmatch, mismatch, not_delegated, no_child_answer, same_servers, child_no_ns, not_a_zone, error
web.*.*[].80 / .443open, refused, timeout, unreachable, error, skipped
web.*.*[].tls.chainvalid, expired, not_yet_valid, hostname_mismatch, self_signed, incomplete_chain, untrusted_root, invalid, handshake_failed
web.*.*[].tlsamatch, mismatch, none
tlsa.resultnone, match, mismatch, unverified, unknown
hsts_preloadpreloaded, absent, unknown
wildcard.statuspresent, absent, unknown
wildcard.probes[].statusanswered, denied, unresolved
redirects.*.endedfinal, external, loop, hop_limit, error

Generated from the live server (DataPulse MCP 1.0.0) on October 1, 2026. Your AI assistant reads this page by calling datapulse_help(topic="domain_health_fields").