Domain Health Check
Run every DNS, email, TLS and web security check in one go and get a single grade with a plain-language fix list.
About the domain health check
A domain touches many independent systems: DNS, mail authentication, TLS certificates, and the web server's own headers, and a weakness in any one of them can undermine security or deliverability even if the others are configured perfectly. This tool runs the full set of individual checks against a domain in one pass and reports the results together instead of one tool at a time.
Checks cover DNS records, zone health, DNSSEC and propagation; domain registration, locks and expiry; the full email set — MX, SPF, DKIM, DMARC, BIMI, MTA-STS, TLS-RPT, SMTP TLS, reverse DNS and public blocklists; the TLS certificate chain and supported protocols; HTTP reachability, redirects and transport headers; security headers, cookies and CORS; exposed ports; search-engine metadata and crawlability; and page performance. Every one of these also has a tool page of its own, so a single area can be re-checked without re-running everything; what the full scan adds is the cross-referencing, one grade covering all of it, and the checks you would not have thought to run.
Each category starts at a baseline score and loses points for failing rules, weighted by how serious that particular failure is; a missing DMARC record, for instance, deducts more than a missing but non-critical security header. Several things that other scanners report as failures deduct nothing here, on purpose: an unsigned zone, an IPv4-only domain, an absent CAA record and a site with no field performance data are all reported as information, because none of them is a fault. The overall grade is a weighted average across categories, and the exact scoring rules are published and versioned so the number is not a black box.
Where a check could not run, the report says so and scores nothing for it, rather than filling the gap with a pass. The port scan and the TLS protocol enumeration need an external probe host; when it is not connected, those sections say they were not tested and name the reason. A category cannot reach a perfect score on the strength of checks that never ran.
Because it is a single scan rather than a manual sequence of separate lookups, this is the fastest way to get an accurate overall picture of a domain's configuration, and the results link through to each specific finding's own checker page when you need to dig into a particular failure in detail. Because every category is scored against the same public rule set on every run, results are also directly comparable over time, which makes the tool useful not just for a one-time audit but for tracking whether changes actually improved the domain's configuration.
Common questions
- What does the health check test?
- DNS records, zone health, DNSSEC and propagation; registration and expiry; MX, SPF, DKIM, DMARC, BIMI, MTA-STS, TLS-RPT, SMTP TLS, reverse DNS and blocklists; TLS certificate and protocols; HTTP reachability, redirects and headers; security headers, cookies and CORS; open ports; SEO metadata; and performance. All in one scan.
- What happens if part of the scan cannot run?
- That part is reported as not tested, with the reason, and it scores nothing. A failed module never fails the whole report, and it never quietly becomes a pass either.
- How is the score calculated?
- Each category starts at a baseline and loses points per failing rule, weighted by severity. The overall score is a weighted average across categories, and the scoring specification is published and versioned.
- Do I need an account?
- No. Reports are free and anonymous, and a shareable link to the results stays valid for a limited retention window.
- How is this different from running each checker separately?
- It runs every check in one pass and combines the results into a single grade and fix list, instead of requiring you to visit each individual tool and mentally combine the findings yourself.
What this tool checks (292 rules)
- domain.rdap.expired — The domain registration has expired
- domain.rdap.expiring-lt-30d — The domain registration expires within 30 days
- domain.rdap.expiring-lt-7d — The domain registration expires within 7 days
- domain.rdap.expiring-lt-90d — The domain registration expires within 90 days
- domain.rdap.no-registrar-lock — No transfer lock is set on the domain
- domain.rdap.no-update-lock — No update lock is set on the domain
- domain.rdap.on-hold — The domain is suspended by the registrar or registry
- domain.rdap.pending-delete — The domain is scheduled for deletion
- domain.rdap.redemption-period — The domain is in the redemption period
- domain.rdap.registrant-redacted — The registrant contact details are not published
- domain.rdap.registration-data-unavailable — The registration data could not be read
- domain.rdap.registration-healthy — The registration is current and locked
- dns.records.aaaa-missing — The domain has no IPv6 address
- dns.records.apex-cname — The domain apex is a CNAME, which the DNS does not allow
- dns.records.caa-critical-unknown-tag — A CAA record marked critical uses a tag no authority understands
- dns.records.caa-empty-issue — CAA forbids every authority from issuing a certificate
- dns.records.caa-iodef-invalid — The CAA reporting address is not a usable URL
- dns.records.caa-missing — No CAA record says which authorities may issue certificates
- dns.records.duplicate-txt-family — Two TXT records of the same kind are published at one name
- dns.records.no-address-record — The domain has no A or AAAA record
- dns.records.ttl-too-high — Records are published with a very long TTL
- dns.records.ttl-too-low — Records are published with a very short TTL
- dns.records.txt-chunking-broken — A TXT record looks cut off at the 255-character limit
- dns.records.wildcard-present — A wildcard record answers for every subdomain
- dns.health.cname-with-other-data — A name has a CNAME alongside other records
- dns.health.glue-mismatch — A glue record's address does not match the nameserver's own
- dns.health.glue-missing — A nameserver inside the domain has no glue record
- dns.health.lame-delegation — A nameserver you delegate to does not answer for the zone
- dns.health.ns-count-below-2 — The domain has fewer than two nameservers
- dns.health.ns-is-cname — A nameserver name is an alias rather than a host
- dns.health.ns-parent-child-mismatch — The registry and the zone disagree about the nameservers
- dns.health.ns-single-address — All nameservers resolve to one address
- dns.health.ns-single-netblock — All nameservers sit in one network block
- dns.health.ns-unresolvable — A nameserver name has no address
- dns.health.probe-unavailable — The delegation could not be checked
- dns.health.recursion-open — A nameserver answers queries for domains that are not yours
- dns.health.serial-mismatch-across-ns — Your nameservers are serving different versions of the zone
- dns.health.soa-expire-out-of-range — The SOA expire interval is outside the usual range
- dns.health.soa-minimum-out-of-range — The SOA negative-caching TTL is outside the usual range
- dns.health.soa-missing — The zone has no readable SOA record
- dns.health.soa-refresh-out-of-range — The SOA refresh interval is outside the usual range
- dns.health.soa-retry-out-of-range — The SOA retry interval is outside the usual range
- dns.health.tcp53-unreachable — A nameserver answers over UDP but not over TCP
- dns.health.zone-transfer-open — A nameserver hands out the whole zone to anyone who asks
- dns.dnssec.algorithm-deprecated — The zone is signed with a deprecated algorithm
- dns.dnssec.chain-broken-servfail — Validating resolvers refuse to resolve the domain
- dns.dnssec.chain-unverified — Signatures were read but not cryptographically verified
- dns.dnssec.ds-mismatch — The registry's DS record does not match any key in the zone
- dns.dnssec.ds-missing-while-signed — The zone is signed but the registry has no DS record
- dns.dnssec.key-too-short — A DNSSEC key is shorter than the recommended size
- dns.dnssec.nsec-zone-walkable — The zone's record names can be enumerated
- dns.dnssec.nsec3-iterations-nonzero — NSEC3 is configured with extra hash iterations
- dns.dnssec.nsec3-opt-out — NSEC3 opt-out weakens proof for unsigned subdomains
- dns.dnssec.probe-unavailable — DNSSEC could not be checked
- dns.dnssec.rrsig-expired — A DNSSEC signature has expired
- dns.dnssec.rrsig-expiring-soon — A DNSSEC signature expires within seven days
- dns.dnssec.rrsig-missing — The zone publishes keys but no signatures
- dns.dnssec.unsigned — The domain is not signed with DNSSEC
- dns.propagation.partial-nxdomain — Some resolvers say the domain does not exist
- dns.propagation.probe-unavailable — No resolver could be asked what it is serving
- dns.propagation.resolver-disagreement — Public resolvers are serving different answers
- dns.propagation.resolvers-unreachable — Some resolvers did not answer and were not counted
- dns.propagation.stale-answers — A recent change has not reached every resolver yet
- dns.propagation.ttl-too-high-for-migration — The record's TTL makes a change slow to take effect
- email.mx.duplicate-preference — Two MX hosts share the same preference value
- email.mx.host-is-cname — MX record points at a CNAME
- email.mx.host-is-ip — MX record points at an IP address instead of a hostname
- email.mx.host-no-rdns — Mail server address has no reverse DNS name
- email.mx.host-unresolvable — MX host does not resolve to an address
- email.mx.no-record — No MX record — this domain cannot receive email
- email.mx.no-redundancy — Every mail server resolves to the same address
- email.mx.null-mx — Domain publishes a null MX (receives no mail)
- email.mx.single-host — Only one mail server host is published
- email.spf.catch-all-range — SPF authorises the whole internet through an address range
- email.spf.duplicate-mechanism — SPF record lists the same sender twice
- email.spf.include-loop — SPF include chain contains a loop
- email.spf.include-unresolvable — SPF include target has no SPF record
- email.spf.lookups-near-limit — SPF is close to the 10 DNS lookup limit
- email.spf.multiple-records — More than one SPF record published
- email.spf.no-all — SPF record has no all mechanism
- email.spf.no-record — No SPF record published
- email.spf.overly-broad-range — SPF authorises a very large block of addresses
- email.spf.plus-all — SPF ends in +all — anyone may send as your domain
- email.spf.ptr-mechanism — SPF uses the deprecated ptr mechanism
- email.spf.question-all — SPF ends in ?all (neutral)
- email.spf.redirect-with-all — SPF has both redirect= and an all mechanism
- email.spf.syntax-invalid — SPF record has a syntax error
- email.spf.too-many-lookups — SPF needs more than 10 DNS lookups
- email.spf.void-lookups-exceeded — SPF exceeds the void DNS lookup limit
- email.dkim.key-1024-bit — DKIM key is only 1024 bits
- email.dkim.key-revoked — DKIM record has an empty p= tag (key revoked)
- email.dkim.key-too-short — DKIM key is shorter than 1024 bits
- email.dkim.no-selector-found — No DKIM key found for any known selector
- email.dkim.syntax-invalid — DKIM record cannot be parsed
- email.dkim.testing-flag-set — DKIM record is in testing mode (t=y)
- email.dkim.unsupported-algorithm — DKIM key uses an algorithm receivers reject
- email.dmarc.external-rua-unauthorised — DMARC reports are sent to an unauthorised external domain
- email.dmarc.forensic-reporting-enabled — DMARC requests forensic reports (ruf)
- email.dmarc.inherited-from-parent — Subdomain has no DMARC record and inherits the parent policy
- email.dmarc.multiple-records — More than one DMARC record published
- email.dmarc.no-record — No DMARC record published
- email.dmarc.no-rua — DMARC record requests no aggregate reports
- email.dmarc.pct-below-100 — DMARC record still carries a pct tag
- email.dmarc.policy-none — DMARC policy is p=none (monitor only)
- email.dmarc.subdomain-policy-none — Subdomains are exempt from an enforcing DMARC policy
- email.dmarc.syntax-invalid — DMARC record has a syntax error
- email.dmarc.test-mode — DMARC is in test mode, so the policy is not applied
- email.bimi.dmarc-not-enforcing — BIMI is published but DMARC is not enforcing
- email.bimi.logo-not-svg-tiny-ps — BIMI logo is not a valid SVG Tiny Portable/Secure file
- email.bimi.logo-unreachable — BIMI logo URL cannot be fetched
- email.bimi.no-mark-certificate — BIMI record has no mark certificate
- email.bimi.no-record — No BIMI record published
- email.bimi.syntax-invalid — BIMI record has a syntax error
- email.mta-sts.max-age-too-low — MTA-STS max_age is very short
- email.mta-sts.mode-none — MTA-STS policy mode is none
- email.mta-sts.mode-testing — MTA-STS policy is still in testing mode
- email.mta-sts.mx-not-covered — A live MX host is not listed in the MTA-STS policy
- email.mta-sts.no-record — No MTA-STS policy published
- email.mta-sts.policy-invalid — MTA-STS policy file is malformed
- email.mta-sts.policy-unreachable — MTA-STS policy file cannot be fetched
- email.mta-sts.record-invalid — MTA-STS DNS record is malformed
- email.tls-rpt.no-record — No TLS-RPT record published
- email.tls-rpt.syntax-invalid — TLS-RPT record has a syntax error
- email.tls-rpt.uri-unreachable — TLS-RPT HTTPS report endpoint is unreachable
- email.smtp-tls.banner-malformed — Mail server's SMTP greeting does not conform to the protocol
- email.smtp-tls.certificate-expired — Mail server's TLS certificate has expired or is not yet valid
- email.smtp-tls.certificate-name-mismatch — Mail server's certificate does not cover its own hostname
- email.smtp-tls.certificate-untrusted — Mail server's TLS certificate does not verify
- email.smtp-tls.no-starttls — Mail server does not offer STARTTLS
- email.smtp-tls.port-unreachable — Mail server does not accept connections on port 25
- email.smtp-tls.probe-unavailable — SMTP transport security was not tested
- email.smtp-tls.starttls-failed — STARTTLS is advertised but the handshake does not complete
- email.smtp-tls.weak-protocol — Mail server negotiates a deprecated TLS version
- email.rdns.generic-hostname — Reverse DNS looks like a generic provider-assigned name
- email.rdns.name-mismatch — Reverse DNS name does not match the mail server's own hostname
- email.rdns.no-ptr — Mail server address has no reverse DNS (PTR) record
- email.rdns.not-forward-confirmed — Reverse DNS does not confirm forward (no full-circle match)
- email.blocklists.advisory-listing — Listed on a source we show but do not score
- email.blocklists.coverage-limited — Which blocklists we check, and which we do not
- email.blocklists.domain-listed — Domain is listed on a domain reputation blocklist
- email.blocklists.list-unavailable — A blocklist did not answer, so it is not counted as clean
- email.blocklists.mx-ip-listed — Mail server address is listed on a blocklist
- tls.certificate.chain-incomplete — Certificate chain is missing an intermediate
- tls.certificate.chain-out-of-order — Certificate chain is not in the required order
- tls.certificate.expired — TLS certificate has expired
- tls.certificate.expiring-lt-30d — TLS certificate expires in under 30 days
- tls.certificate.expiring-lt-7d — TLS certificate expires in under 7 days
- tls.certificate.hostname-mismatch — Certificate does not cover the hostname
- tls.certificate.no-san — Certificate has no Subject Alternative Name
- tls.certificate.not-yet-valid — TLS certificate is not valid yet
- tls.certificate.self-signed — Certificate is self-signed
- tls.certificate.unreadable — Certificate could not be parsed
- tls.certificate.untrusted-root — Certificate does not chain to a trusted root
- tls.certificate.validity-too-long — Certificate is valid for longer than a public CA may issue
- tls.certificate.weak-key — Certificate uses a key that is too small
- tls.certificate.weak-signature-algorithm — Certificate is signed with a broken hash algorithm
- tls.certificate.wildcard-too-broad — Certificate uses an unusually broad wildcard
- tls.protocols.insecure-cipher — Server accepts a broken cipher suite
- tls.protocols.no-forward-secrecy — Some connections have no forward secrecy
- tls.protocols.no-tls12 — Neither TLS 1.2 nor TLS 1.3 is supported
- tls.protocols.no-tls13 — TLS 1.3 is not supported
- tls.protocols.probe-unavailable — Protocol and cipher support could not be tested
- tls.protocols.sslv2-enabled — SSL 2.0 is enabled
- tls.protocols.sslv3-enabled — SSL 3.0 is enabled
- tls.protocols.tls10-enabled — TLS 1.0 is enabled
- tls.protocols.tls11-enabled — TLS 1.1 is enabled
- tls.protocols.weak-cipher — Server accepts a weak cipher suite
- http.reachability.error-status — The site's home page returns an error status
- http.reachability.http-closed — Plain HTTP is not served at all
- http.reachability.http-open-no-redirect — Plain HTTP does not redirect to HTTPS
- http.reachability.https-unreachable — The site does not answer over HTTPS
- http.reachability.slow-response — The server was slow to respond
- http.redirects.chain-too-long — The redirect chain is longer than it needs to be
- http.redirects.cross-host-hop — The chain moves between hostnames
- http.redirects.hop-refused — A redirect pointed somewhere the scanner will not follow
- http.redirects.loop — The redirect chain loops
- http.redirects.malformed-location — A redirect destination is malformed
- http.redirects.missing-location — A redirect response has no destination
- http.redirects.protocol-downgrade — A redirect drops from HTTPS to plain HTTP
- http.redirects.temporary-for-canonical — A permanent redirect is marked temporary
- http.headers.cache-directives-conflicting — The caching instructions contradict each other
- http.headers.charset-missing — A text response does not declare its character encoding
- http.headers.compression-encoding-mismatch — The declared Content-Encoding may not match the body
- http.headers.compression-not-applied — A compressible response was sent uncompressed
- http.headers.content-type-missing — The response has a body but no Content-Type
- http.headers.deprecated-header-present — The response sends obsolete headers, one of them harmful
- http.headers.http3-not-advertised — No Alt-Svc header advertises HTTP/3
- http.headers.internal-address-disclosed — A response header leaks an internal address
- http.headers.no-cache-control — The response does not say how long it may be cached
- http.headers.no-validator — The response cannot be revalidated without downloading it again
- http.headers.vary-missing-accept-encoding — A compressed response does not vary on Accept-Encoding
- http.headers.vary-wildcard — Vary: * makes the response uncacheable by any shared cache
- web.security-headers.coep-missing — No Cross-Origin-Embedder-Policy is set
- web.security-headers.coop-missing — No Cross-Origin-Opener-Policy is set
- web.security-headers.corp-missing — No Cross-Origin-Resource-Policy is set
- web.security-headers.csp-missing — No Content Security Policy is enforced
- web.security-headers.csp-no-object-or-base — The policy leaves plugins or the base URL unrestricted
- web.security-headers.csp-report-only — The Content Security Policy is report-only
- web.security-headers.csp-unsafe-eval — The policy allows eval()
- web.security-headers.csp-unsafe-inline — The policy allows inline scripts or styles
- web.security-headers.csp-wildcard-source — The policy allows resources from anywhere
- web.security-headers.duplicate-conflicting — A security header was sent twice with different values
- web.security-headers.hsts-max-age-too-low — HSTS max-age is shorter than six months
- web.security-headers.hsts-missing — HTTP Strict Transport Security is not in force
- web.security-headers.hsts-no-subdomains — HSTS does not cover subdomains
- web.security-headers.hsts-not-preloaded — The site is not set up for HSTS preloading
- web.security-headers.malformed-value — A response header is malformed
- web.security-headers.no-frame-protection — The page can be embedded in another site
- web.security-headers.permissions-policy-missing — No Permissions-Policy is set
- web.security-headers.referrer-policy-missing — No Referrer-Policy is set
- web.security-headers.referrer-policy-weak — The Referrer-Policy leaks full URLs
- web.security-headers.server-version-disclosed — The server announces its exact version
- web.security-headers.technology-disclosed — Response headers name the application stack
- web.security-headers.xcto-missing — Browsers may guess the type of your responses
- web.cookies.domain-not-accepted — Cookie sets a Domain the browser will not accept, so it is discarded
- web.cookies.malformed-attribute — Cookie carries an attribute browsers cannot read
- web.cookies.no-httponly — Cookie can be read by JavaScript
- web.cookies.no-samesite — Cookie has no SameSite attribute
- web.cookies.no-secure — Cookie is sent over unencrypted connections
- web.cookies.none-set — The page set no cookies
- web.cookies.overly-broad-domain — Cookie is shared with every subdomain
- web.cookies.prefix-requirements-unmet — Cookie name promises protections its attributes do not provide
- web.cookies.samesite-none-insecure — Cookie uses SameSite=None without Secure, so it is rejected
- web.cors.headers-overly-broad — The CORS policy accepts any request header from any origin
- web.cors.malformed-allow-origin — The Access-Control-Allow-Origin value is not a valid origin
- web.cors.methods-overly-broad — The CORS policy grants broad methods on an unrestricted origin
- web.cors.null-origin-allowed — The null origin is on the CORS allow-list
- web.cors.origin-reflected — Any website is allowed to read this site's responses
- web.cors.origin-reflected-with-credentials — Any website can read authenticated responses from this site
- web.cors.preflight-not-cached — Preflight results are not cached
- web.cors.vary-origin-missing — The CORS response varies by origin but is not marked Vary: Origin
- web.cors.wildcard-origin — Resources are shared with every origin, without credentials
- web.cors.wildcard-with-credentials — The CORS policy pairs a wildcard origin with credentials
- net.ports.database-exposed — A database port is reachable from the internet
- net.ports.ftp-exposed — FTP is reachable from the internet
- net.ports.open — Ports reachable from the internet
- net.ports.probe-unavailable — No port could be tested
- net.ports.remote-admin-exposed — A remote desktop service is reachable from the internet
- net.ports.ssh-exposed — SSH is reachable from the internet
- web.technology.cms-version-disclosed — The exact version of your CMS is published on every page
- web.technology.detected — Technologies identified from the response
- perf.lab.excessive-javascript — The page ships more JavaScript than it uses
- perf.lab.images-legacy-format — Images are served in older, heavier formats
- perf.lab.images-oversized — Images are much larger than the space they are shown in
- perf.lab.metrics — Lab measurement of one page load
- perf.lab.render-blocking-resources — Stylesheets and scripts stop the page from rendering
- perf.lab.score-withheld — This report never publishes a headline performance score
- perf.lab.static-assets-short-cache — Static files are re-downloaded because they are barely cached
- perf.lab.subresources-uncompressed — Scripts and stylesheets are sent without compression
- perf.lab.unavailable — The page was not measured in a browser
- perf.crux.cls-poor — The page jumps around while it loads for real visitors
- perf.crux.fcp-slow — Real visitors stare at a blank page for too long
- perf.crux.field-data — Real-user experience over the last 28 days
- perf.crux.inp-poor — The page is slow to respond when real visitors interact with it
- perf.crux.insufficient-data — Not enough real-user traffic for field data
- perf.crux.lcp-poor — Real visitors wait too long for the main content to appear
- perf.crux.not-configured — Real-user performance data was not requested
- perf.crux.query-failed — Real-user performance data could not be retrieved
- perf.crux.ttfb-slow — The server takes too long to send the first byte to real visitors
- seo.canonical.conflicting — The page declares more than one canonical URL
- seo.canonical.invalid — The canonical URL cannot be used
- seo.canonical.missing — The page declares no canonical URL
- seo.canonical.points-elsewhere — The canonical URL points at a different page
- seo.headings.h1-missing — The page has no h1 heading
- seo.headings.hierarchy-skipped — The heading levels skip a level
- seo.headings.multiple-h1 — The page has more than one h1
- seo.hreflang.invalid — An hreflang annotation is not valid
- seo.hreflang.missing-self-reference — The hreflang set does not include this page
- seo.html-lang.invalid — The page's declared language is not a well-formed language tag
- seo.html-lang.missing — The page does not declare what language it is written in
- seo.images.missing-alt — Images on the page have no alt attribute
- seo.indexability.blocked-by-robots-txt — robots.txt blocks this page from being crawled
- seo.indexability.nofollow — The page tells crawlers not to follow its links
- seo.indexability.noindex — The page asks search engines not to index it
- seo.indexability.noindex-blocked-by-robots — A noindex directive is unreachable behind a robots.txt block
- seo.meta-description.length-outside-guidance — The meta description is likely to be truncated or is very short
- seo.meta-description.missing — The page has no meta description
- seo.meta.duplicate-tags — The page declares the same metadata more than once
- seo.meta.title-matches-description — The title and the meta description are identical
- seo.opengraph.incomplete — Open Graph metadata is missing required properties
- seo.robots-txt.missing — No robots.txt is published
- seo.robots-txt.unreadable — The robots.txt at the site root was not readable as directives
- seo.sitemap.missing — No XML sitemap could be found
- seo.sitemap.not-declared — The sitemap is not declared in robots.txt
- seo.sitemap.not-xml — The sitemap URL does not return XML
- seo.structured-data.absent — The page carries no JSON-LD structured data
- seo.structured-data.invalid — A JSON-LD block on the page does not parse
- seo.structured-data.missing-required-property — Structured data is missing a documented required property
- seo.structured-data.retired-type — Structured data uses a type that no longer produces a rich result
- seo.title.length-outside-guidance — The title is likely to be truncated or is very short
- seo.title.missing — The page has no title
- seo.twitter-card.missing — No Twitter card type is declared