Rule catalogue
The 292 checks a dotvitals scan runs. Each one states a condition, what it costs your score when it is true, why it matters and how to put it right.
Ruleset 2026.09.9 ·how the score is calculated
Filter
Email authentication (40)
- BIMI is published but DMARC is not enforcing
You have a BIMI record, but your DMARC policy is not strict enough for it to be used.
email.bimi.dmarc-not-enforcing
- BIMI logo is not a valid SVG Tiny Portable/Secure file
Your logo is not in the restricted SVG format BIMI requires. Mailbox providers reject anything else, so the logo is not shown.
email.bimi.logo-not-svg-tiny-ps
- BIMI logo URL cannot be fetched
The logo your BIMI record points at could not be downloaded. Mailbox providers that cannot fetch it simply show no logo.
email.bimi.logo-unreachable
- BIMI record has no mark certificate
Your BIMI record points at a logo but not at a mark certificate. Gmail, Apple Mail and Yahoo will not show the logo without one, so most recipients see…
email.bimi.no-mark-certificate
- No BIMI record published
You have not published a BIMI record, so your logo does not appear next to your messages in the inboxes that support it.
email.bimi.no-record
- BIMI record has a syntax error
A BIMI record is published but cannot be read, so no inbox will show your logo. The setup looks complete from the DNS side and does nothing.
email.bimi.syntax-invalid
- DKIM key is only 1024 bits
Your signing key still works, but it is at the minimum size the standard allows. Larger keys are now the norm and some receivers treat 1024-bit signatures as…
email.dkim.key-1024-bit
- DKIM record has an empty p= tag (key revoked)
The DKIM record for this selector exists but contains no key. An empty key means revoked, so every message signed with this selector is rejected outright.
email.dkim.key-revoked
- DKIM key is shorter than 1024 bits
The signing key published for your domain is too small to be trusted. Receiving servers are told to reject keys this short, so your signature may be treated…
email.dkim.key-too-short
- No DKIM key found for any known selector
We could not find a DKIM signing key published for your domain. DKIM is the cryptographic signature that proves a message really came from you and was not…
email.dkim.no-selector-found
- DKIM record cannot be parsed
The record published for this selector is not a valid DKIM key record, so receivers cannot verify signatures made with it.
email.dkim.syntax-invalid
- DKIM record is in testing mode (t=y)
Your DKIM record tells receivers to ignore any failures because you are still testing. Left in place, it means a genuine signature failure is never acted on.
email.dkim.testing-flag-set
- DKIM key uses an algorithm receivers reject
Your key is published with a signing algorithm that receiving servers no longer accept, so signatures made with it are not verified.
email.dkim.unsupported-algorithm
- DMARC reports are sent to an unauthorised external domain
Your reports are addressed to a mailbox on a different domain, and that domain has not published the record that says it agrees to receive them.
email.dmarc.external-rua-unauthorised
- DMARC requests forensic reports (ruf)
Your record asks receivers to send you copies of individual failing messages. Few receivers do this, and the ones that do may send you other people's…
email.dmarc.forensic-reporting-enabled
- Subdomain has no DMARC record and inherits the parent policy
This subdomain publishes no DMARC record of its own, so receivers apply the policy from your main domain. That is normal and usually what you want.
email.dmarc.inherited-from-parent
- More than one DMARC record published
Two or more DMARC records exist at the same name. The rules tell receivers to ignore all of them, so your domain effectively has no DMARC policy.
email.dmarc.multiple-records
- No DMARC record published
Your domain does not publish a DMARC policy, so receiving mail servers have no instruction about what to do with mail that fails your other checks.
email.dmarc.no-record
- DMARC record requests no aggregate reports
Your DMARC record has no address for receivers to send reports to, so you have no way of finding out who is sending mail as your domain or whether it passes.
email.dmarc.no-rua
- DMARC record still carries a pct tag
Your policy is enforcing, but it still carries the old `pct` tag asking receivers to apply it to only some messages.
email.dmarc.pct-below-100
- DMARC policy is p=none (monitor only)
Your domain publishes a DMARC record, but it tells receivers to take no action on messages that fail authentication.
email.dmarc.policy-none
- Subdomains are exempt from an enforcing DMARC policy
Your main domain is protected, but the record explicitly exempts every subdomain. Attackers routinely spoof a subdomain that was never used for mail, because…
email.dmarc.subdomain-policy-none
- DMARC record has a syntax error
The record at _dmarc cannot be read as a valid DMARC policy, so receivers discard it and treat your domain as having no policy.
email.dmarc.syntax-invalid
- DMARC is in test mode, so the policy is not applied
Your record states a policy and then, with `t=y`, asks receiving mail servers not to act on it.
email.dmarc.test-mode
- SPF authorises the whole internet through an address range
Your SPF record authorises an address range so wide that it covers the internet itself.
email.spf.catch-all-range
- SPF record lists the same sender twice
The same entry appears more than once in your SPF record. It has no extra effect, and if it is one that costs a DNS lookup it brings you closer to the limit…
email.spf.duplicate-mechanism
- SPF include chain contains a loop
One of the records your SPF policy pulls in eventually points back at a record already in the chain.
email.spf.include-loop
- SPF include target has no SPF record
Your SPF record refers to another domain that does not publish an SPF record of its own.
email.spf.include-unresolvable
- SPF is close to the 10 DNS lookup limit
Your SPF record still works, but it is close to the maximum number of DNS lookups allowed.
email.spf.lookups-near-limit
- More than one SPF record published
Two or more SPF records exist for your domain. The rules say a receiver must treat this as an error, so in practice none of them is applied and your SPF is…
email.spf.multiple-records
- SPF record has no all mechanism
Your SPF record lists authorised senders but never says what to do about everyone else.
email.spf.no-all
- No SPF record published
Your domain does not tell receiving mail servers which computers are allowed to send email for it.
email.spf.no-record
- SPF authorises a very large block of addresses
Your SPF record authorises a huge range of internet addresses to send mail as you.
email.spf.overly-broad-range
- SPF ends in +all — anyone may send as your domain
Your SPF record explicitly authorises every server on the internet to send mail as your domain.
email.spf.plus-all
- SPF uses the deprecated ptr mechanism
Your SPF record uses a mechanism the standard tells people not to use. It is slow, it puts load on other people's DNS servers, and some receivers ignore it…
email.spf.ptr-mechanism
- SPF ends in ?all (neutral)
Your SPF record ends by telling receivers to form no opinion about servers that are not on your list.
email.spf.question-all
- SPF has both redirect= and an all mechanism
Your record contains a redirect to another domain's policy and also its own closing rule.
email.spf.redirect-with-all
- SPF record has a syntax error
Your SPF record cannot be read by receiving mail servers. Because it is unreadable, the whole check fails with an error and none of your listed senders is…
email.spf.syntax-invalid
- SPF needs more than 10 DNS lookups
Evaluating your SPF record requires more DNS lookups than the standard allows. Receiving servers stop early and return an error, so your SPF check does not…
email.spf.too-many-lookups
- SPF exceeds the void DNS lookup limit
Too many of the lookups in your SPF record point at names that do not exist. Receivers stop evaluating and return an error, so the record authenticates…
email.spf.void-lookups-exceeded
Email transport (33)
- MTA-STS max_age is very short
Your policy asks senders to forget it again after a short time. A short lifetime narrows the window in which the policy actually protects you.
email.mta-sts.max-age-too-low
- MTA-STS policy mode is none
Your published policy explicitly tells senders to ignore any previous policy for your domain. It provides no protection at all.
email.mta-sts.mode-none
- MTA-STS policy is still in testing mode
Your policy is published but asks senders only to report problems, not to act on them. Mail can still be delivered unencrypted.
email.mta-sts.mode-testing
- A live MX host is not listed in the MTA-STS policy
One of your mail servers is missing from the policy. If the policy is enforcing, senders will refuse to deliver to that server and mail to your domain…
email.mta-sts.mx-not-covered
- No MTA-STS policy published
Mail sent to your domain is encrypted only if the sending server happens to try. An attacker positioned on the network can strip that encryption and read the…
email.mta-sts.no-record
- MTA-STS policy file is malformed
The policy file exists but cannot be understood. Senders discard it and go back to unencrypted delivery.
email.mta-sts.policy-invalid
- MTA-STS policy file cannot be fetched
Your domain announces an MTA-STS policy but the policy file itself cannot be downloaded. Senders that cannot fetch it fall back to unencrypted delivery.
email.mta-sts.policy-unreachable
- MTA-STS DNS record is malformed
The DNS record that announces your MTA-STS policy cannot be read, so senders never look for the policy file.
email.mta-sts.record-invalid
- Two MX hosts share the same preference value
Two of your mail servers are given the same priority, so senders will spread mail across both at random. That is only correct if both really are equivalent.
email.mx.duplicate-preference
- MX record points at a CNAME
One of your mail server records points at an alias rather than a real host. The standard forbids this, and some sending servers refuse to follow it.
email.mx.host-is-cname
- MX record points at an IP address instead of a hostname
One of your mail server records contains an IP address where a hostname is required. Many sending servers will not deliver mail to it at all.
email.mx.host-is-ip
- Mail server address has no reverse DNS name
The address behind one of your mail servers has no reverse DNS entry. Many receiving systems treat that as a spam signal when this machine also sends mail.
email.mx.host-no-rdns
- MX host does not resolve to an address
One of your mail servers is named in DNS but that name has no address, so nothing can connect to it. Mail directed there fails.
email.mx.host-unresolvable
- No MX record — this domain cannot receive email
Your domain publishes no mail server records, so nobody can send email to any address at it. Messages bounce back to the sender.
email.mx.no-record
- Every mail server resolves to the same address
You publish more than one mail server, but they all point at the same machine. If it goes down, the backup goes down with it and inbound mail is delayed or…
email.mx.no-redundancy
- Domain publishes a null MX (receives no mail)
Your domain explicitly declares that it does not accept email. That is a valid and useful configuration for a domain that only hosts a website.
email.mx.null-mx
- Only one mail server host is published
All of your inbound mail depends on a single server. If it is unreachable, senders queue messages and eventually give up, and some mail is lost.
email.mx.single-host
- Reverse DNS looks like a generic provider-assigned name
Your mail server's reverse name looks automatically generated rather than chosen — the sort of name a provider mints for a whole block of addresses.
email.rdns.generic-hostname
- Reverse DNS name does not match the mail server's own hostname
The name in your mail server's reverse DNS is different from the name your MX record points at.
email.rdns.name-mismatch
- Mail server address has no reverse DNS (PTR) record
One of the addresses your mail server uses has no name attached to it. Many large mail providers reject or heavily filter mail from an address with no…
email.rdns.no-ptr
- Reverse DNS does not confirm forward (no full-circle match)
Your mail server's address has a name attached, but that name does not resolve back to the same address.
email.rdns.not-forward-confirmed
- Mail server's SMTP greeting does not conform to the protocol
Your mail server's opening greeting is not shaped the way the standard requires — it is over-long, contains characters it should not, or does not start with…
email.smtp-tls.banner-malformed
- Mail server's TLS certificate has expired or is not yet valid
The certificate your mail server presents is outside its validity dates. Senders that verify certificates will refuse to deliver mail to you.
email.smtp-tls.certificate-expired
- Mail server's certificate does not cover its own hostname
The certificate your mail server presents is for a different name than the one your MX record points at.
email.smtp-tls.certificate-name-mismatch
- Mail server's TLS certificate does not verify
Your mail server encrypts, but its certificate is self-signed or issued by an authority senders do not trust, so senders cannot tell they are talking to you…
email.smtp-tls.certificate-untrusted
- Mail server does not offer STARTTLS
Your mail server does not offer encryption, so mail sent to this domain crosses the internet in plain text where anyone on the path can read it.
email.smtp-tls.no-starttls
- Mail server does not accept connections on port 25
Your mail server did not answer on the port email is delivered to. If this is not a temporary fault, inbound mail to this domain is not arriving.
email.smtp-tls.port-unreachable
- SMTP transport security was not tested
We could not test your mail servers' encryption on this scan. Nothing below was measured — this is a gap in our result, not a finding about your mail.
email.smtp-tls.probe-unavailable
- STARTTLS is advertised but the handshake does not complete
Your mail server offers encryption and then fails to deliver it. This is worse than not offering it: senders that saw the offer may refuse to fall back to…
email.smtp-tls.starttls-failed
- Mail server negotiates a deprecated TLS version
Your mail server agreed to an old, deprecated version of TLS. It still encrypts, but with a protocol that has known weaknesses and that senders are actively…
email.smtp-tls.weak-protocol
- No TLS-RPT record published
Nobody tells you when encrypted delivery to your mail servers fails. Senders that could not connect securely simply do not, and you never find out.
email.tls-rpt.no-record
- TLS-RPT record has a syntax error
The record exists but cannot be read, so no reports are sent. You have the appearance of TLS reporting without the reporting.
email.tls-rpt.syntax-invalid
- TLS-RPT HTTPS report endpoint is unreachable
Your record asks for reports to be posted to a web address that does not accept them. The reports are generated and then thrown away.
email.tls-rpt.uri-unreachable
Email reputation (5)
- Listed on a source we show but do not score
One of your mail server addresses appears on {{listName}}. We show this because it is real, but it does not affect your score — this list often lists whole…
email.blocklists.advisory-listing
- Which blocklists we check, and which we do not
We check {{checkedLists}}. We do not check {{excludedLists}} — not because we cannot, but because their free feeds are licensed for non-commercial use and we…
email.blocklists.coverage-limited
- Domain is listed on a domain reputation blocklist
Your domain name itself appears on a reputation blocklist. Unlike an address listing, this follows the domain everywhere — changing servers does not clear it.
email.blocklists.domain-listed
- A blocklist did not answer, so it is not counted as clean
{{listName}} {{outcome}} for {{address}}. That is not evidence you are clean — it means we do not know, and the result above is scoped to the lists that did…
email.blocklists.list-unavailable
- Mail server address is listed on a blocklist
One of your mail server addresses appears on {{listName}}. Receivers that consult that list will reject or quarantine mail from this address until it is…
email.blocklists.mx-ip-listed
DNS (38)
- A name has a CNAME alongside other records
One of your names is both an alias and a real record at the same time. The DNS does not allow that, and different resolvers resolve it differently, so the…
dns.health.cname-with-other-data
- A glue record's address does not match the nameserver's own
The address your registry publishes for a nameserver is not the address that nameserver's own record gives.
dns.health.glue-mismatch
- A nameserver inside the domain has no glue record
One of your nameservers lives inside the domain it serves, and the registry does not hold its address.
dns.health.glue-missing
- A nameserver you delegate to does not answer for the zone
One of the nameservers listed for your domain does not serve it. Resolvers pick a nameserver at random, so a share of your visitors wait for a timeout before…
dns.health.lame-delegation
- The domain has fewer than two nameservers
Everything about this domain depends on a single machine. If it stops answering, the website, the email and every service on the domain disappear at once.
dns.health.ns-count-below-2
- A nameserver name is an alias rather than a host
One of your nameservers is listed under a name that redirects to another name. The DNS forbids this, and some resolvers refuse to follow it, so those…
dns.health.ns-is-cname
- The registry and the zone disagree about the nameservers
The nameserver list held at your registry is not the list your own zone publishes.
dns.health.ns-parent-child-mismatch
- All nameservers resolve to one address
You have several nameserver names, but they all point at the same machine. It looks like redundancy in your control panel and provides none.
dns.health.ns-single-address
- All nameservers sit in one network block
Your nameservers have different addresses but live in the same corner of the internet.
dns.health.ns-single-netblock
- A nameserver name has no address
One of the nameservers listed for your domain is a name that does not resolve to anything. Nothing can ask it a question, so it contributes nothing but delay.
dns.health.ns-unresolvable
- The delegation could not be checked
We could not reach your nameservers directly, so none of the delegation checks ran. This says nothing about your zone — only that we could not look.
dns.health.probe-unavailable
- A nameserver answers queries for domains that are not yours
One of your nameservers will look up any domain on the internet for anybody who asks.
dns.health.recursion-open
- Your nameservers are serving different versions of the zone
Your nameservers do not all hold the same copy of your DNS records. Which answer a visitor gets depends on which nameserver their resolver happened to pick.
dns.health.serial-mismatch-across-ns
- The SOA expire interval is outside the usual range
The timer that says how long a backup nameserver may keep serving your zone after losing contact with the primary is set unusually. {{consequence}}
dns.health.soa-expire-out-of-range
- The SOA negative-caching TTL is outside the usual range
The timer that controls how long the internet remembers "this name does not exist" is set unusually. {{consequence}}
dns.health.soa-minimum-out-of-range
- The zone has no readable SOA record
Every DNS zone must have a record describing itself. None of your nameservers returned one, which means either the zone is not properly loaded or the servers…
dns.health.soa-missing
- The SOA refresh interval is outside the usual range
The timer that tells your backup nameservers how often to check for changes is set unusually. {{consequence}}
dns.health.soa-refresh-out-of-range
- The SOA retry interval is outside the usual range
The timer that decides how soon a backup nameserver tries again after a failed check is set unusually. {{consequence}}
dns.health.soa-retry-out-of-range
- A nameserver answers over UDP but not over TCP
One of your nameservers refuses connections on the TCP port it is required to serve.
dns.health.tcp53-unreachable
- A nameserver hands out the whole zone to anyone who asks
One of your nameservers gave us a complete copy of your DNS zone, without being asked to prove who we are.
dns.health.zone-transfer-open
- Some resolvers say the domain does not exist
Some public resolvers report that your domain does not exist, while others return records for it normally.
dns.propagation.partial-nxdomain
- No resolver could be asked what it is serving
We could not query the public resolvers, so nothing was compared. This says nothing about your domain — only that the check did not run.
dns.propagation.probe-unavailable
- Public resolvers are serving different answers
Resolvers around the world do not agree on your records, and the difference is not a change still spreading.
dns.propagation.resolver-disagreement
- Some resolvers did not answer and were not counted
Some of the public resolvers we ask did not reply. They are excluded from the comparison rather than counted as disagreeing, because a resolver that said…
dns.propagation.resolvers-unreachable
- A recent change has not reached every resolver yet
Some resolvers are still serving the previous value from their cache. Nothing is wrong: the old answer expires by itself, and we can tell you when.
dns.propagation.stale-answers
- The record's TTL makes a change slow to take effect
This record tells resolvers to remember it for a long time. Any change you make — including undoing a mistake — takes that long to reach everyone, and there…
dns.propagation.ttl-too-high-for-migration
- The domain has no IPv6 address
The domain is reachable over IPv4 only. Everything works today, but visitors on IPv6-only mobile networks reach you through their carrier's translation layer…
dns.records.aaaa-missing
- The domain apex is a CNAME, which the DNS does not allow
Your domain's root name points at another name instead of at an address. The DNS forbids this, and the usual symptom is that email stops arriving while the…
dns.records.apex-cname
- A CAA record marked critical uses a tag no authority understands
One of your CAA records is flagged as must-understand and uses a name that certificate authorities do not recognise.
dns.records.caa-critical-unknown-tag
- CAA forbids every authority from issuing a certificate
Your CAA record says that no certificate authority may issue for this domain. If that was deliberate, nothing is wrong.
dns.records.caa-empty-issue
- The CAA reporting address is not a usable URL
Your CAA record asks certificate authorities to report refused requests to an address they cannot use.
dns.records.caa-iodef-invalid
- No CAA record says which authorities may issue certificates
Any certificate authority in the world may issue a certificate for your domain. A CAA record names the ones you actually use, and every authority is required…
dns.records.caa-missing
- Two TXT records of the same kind are published at one name
There are two records of the same type where there should be one. Software that reads them is required to treat that as an error and ignore both, so the…
dns.records.duplicate-txt-family
- The domain has no A or AAAA record
Nothing on the internet knows where to find this domain. A browser asked to open it gets no address back, so the site cannot load at all.
dns.records.no-address-record
- Records are published with a very long TTL
Resolvers are told to remember these records for a very long time. If you need to change or undo one, a large part of the internet will keep using the old…
dns.records.ttl-too-high
- Records are published with a very short TTL
Your records tell resolvers to forget them almost immediately, so the world re-asks your nameservers constantly.
dns.records.ttl-too-low
- A TXT record looks cut off at the 255-character limit
One of your TXT records appears to have been truncated where the DNS forces long values to be split.
dns.records.txt-chunking-broken
- A wildcard record answers for every subdomain
Any name under this domain resolves, including ones you never created. Typos, old links and names invented by other people all point at your server.
dns.records.wildcard-present
DNSSEC (14)
- The zone is signed with a deprecated algorithm
Your zone is signed using cryptography that is no longer considered safe. Validators are being encouraged to stop accepting it, and some already treat it as…
dns.dnssec.algorithm-deprecated
- Validating resolvers refuse to resolve the domain
Public resolvers that check DNSSEC cannot resolve your domain at all. For everyone using one of them — a large share of the internet — your website and email…
dns.dnssec.chain-broken-servfail
- Signatures were read but not cryptographically verified
We checked that your DNSSEC records exist, that the link to your registry matches, and that no signature has expired.
dns.dnssec.chain-unverified
- The registry's DS record does not match any key in the zone
The fingerprint your registrar publishes does not match any signing key your zone actually holds.
dns.dnssec.ds-mismatch
- The zone is signed but the registry has no DS record
Your DNS host is signing the zone, but your registrar has not published the record that tells the world to check those signatures.
dns.dnssec.ds-missing-while-signed
- A DNSSEC key is shorter than the recommended size
One of your signing keys is smaller than current guidance calls for. The signatures still work today, but the margin of safety is thinner than it should be.
dns.dnssec.key-too-short
- The zone's record names can be enumerated
Your zone proves that a name does not exist by naming the next one that does. Following that chain lets anyone list every hostname in your zone.
dns.dnssec.nsec-zone-walkable
- NSEC3 is configured with extra hash iterations
Your zone asks every resolver to do extra repeated hashing on each lookup that finds nothing.
dns.dnssec.nsec3-iterations-nonzero
- NSEC3 opt-out weakens proof for unsigned subdomains
Your zone is configured so that it cannot prove an unsigned subdomain does not exist.
dns.dnssec.nsec3-opt-out
- DNSSEC could not be checked
We could not read your zone's signing records, so none of the DNSSEC checks ran. This says nothing about whether your domain is signed — only that we could…
dns.dnssec.probe-unavailable
- A DNSSEC signature has expired
One of your zone's signatures is out of date. Validating resolvers treat an expired signature as a forgery, so they refuse to answer for your domain at all.
dns.dnssec.rrsig-expired
- A DNSSEC signature expires within seven days
One of your signatures is close to its expiry date. If whatever normally renews it has stopped, your domain will become unresolvable for a large part of the…
dns.dnssec.rrsig-expiring-soon
- The zone publishes keys but no signatures
Your zone has DNSSEC keys but the records themselves are not signed. Any resolver that trusts your keys will refuse every answer, because there is nothing…
dns.dnssec.rrsig-missing
- The domain is not signed with DNSSEC
Nothing proves that the DNS answers people receive for your domain are the ones you published. A resolver that is fed a forged answer has no way to detect it.
dns.dnssec.unsigned
Domain registration (12)
- The domain registration has expired
The registry's expiry date for this domain is in the past. Depending on how long ago, the domain may already have stopped resolving, and after a grace period…
domain.rdap.expired
- The domain registration expires within 30 days
The registry's expiry date for this domain is under a month away. This is normal for a domain that auto-renews — it is worth one check that the renewal will…
domain.rdap.expiring-lt-30d
- The domain registration expires within 7 days
The registry's expiry date for this domain is less than a week away. If the automatic renewal does not go through, the domain starts down the deletion path…
domain.rdap.expiring-lt-7d
- The domain registration expires within 90 days
The registry's expiry date is roughly a quarter away. This is a note, not a problem: it is the normal state of a domain approaching its renewal, and it…
domain.rdap.expiring-lt-90d
- No transfer lock is set on the domain
The registry shows no `clientTransferProhibited` status, so nothing at your registrar has to be unlocked before a transfer request to another registrar can…
domain.rdap.no-registrar-lock
- No update lock is set on the domain
The registry shows no `clientUpdateProhibited` status, so the domain's nameservers and contact details can be changed from inside the registrar account with…
domain.rdap.no-update-lock
- The domain is suspended by the registrar or registry
A `clientHold` or `serverHold` status means the domain has been pulled from the zone deliberately.
domain.rdap.on-hold
- The domain is scheduled for deletion
The redemption window has closed and the registry has queued the domain for release — usually about five days.
domain.rdap.pending-delete
- The domain is in the redemption period
The domain expired, was deleted, and is in the roughly 30-day window in which the previous owner can still get it back — by asking the registrar for a…
domain.rdap.redemption-period
- The registrant contact details are not published
The registry does not publish who holds this domain. That is the normal, expected state for an individual registrant, it is not a misconfiguration, and it…
domain.rdap.registrant-redacted
- The registration data could not be read
We could not get a registration record for this domain, so nothing in this section was checked.
domain.rdap.registration-data-unavailable
- The registration is current and locked
The registry shows a comfortable expiry date, a transfer lock in place, and no suspension or deletion status. This is what a well-kept domain looks like.
domain.rdap.registration-healthy
TLS (25)
- Certificate chain is missing an intermediate
The server sent its own certificate but not the linking certificates above it. Some visitors see the site fine and others get a security warning, seemingly…
tls.certificate.chain-incomplete
- Certificate chain is not in the required order
The linking certificates are present but sent in the wrong order, or one is repeated. Modern clients cope; older and stricter ones do not.
tls.certificate.chain-out-of-order
- TLS certificate has expired
The certificate's end date has passed. Every browser now shows a full-page security warning instead of your site, and most visitors will not click through it.
tls.certificate.expired
- TLS certificate expires in under 30 days
The certificate still works, but it runs out within the month. This is the point where automatic renewal should already have replaced it.
tls.certificate.expiring-lt-30d
- TLS certificate expires in under 7 days
The certificate is about to run out. If renewal has not already succeeded, your site goes down within the week.
tls.certificate.expiring-lt-7d
- Certificate does not cover the hostname
The certificate is for a different name than the one visitors type. Browsers show a security warning and refuse to continue without an explicit override.
tls.certificate.hostname-mismatch
- Certificate has no Subject Alternative Name
The certificate lists its hostname only in the old Common Name field, which browsers stopped reading in 2017.
tls.certificate.no-san
- TLS certificate is not valid yet
The certificate's start date is in the future, so browsers reject it exactly as they would reject an expired one.
tls.certificate.not-yet-valid
- Certificate is self-signed
The certificate vouches for itself. Nobody else has confirmed the site is who it says it is, so browsers treat it as untrusted.
tls.certificate.self-signed
- Certificate could not be parsed
The server sent something in place of a certificate that could not be read as one. No client can validate what it cannot decode.
tls.certificate.unreadable
- Certificate does not chain to a trusted root
The certificate cannot be traced back to an authority browsers trust, so it is rejected the same way an expired or mismatched one is.
tls.certificate.untrusted-root
- Certificate is valid for longer than a public CA may issue
The certificate's lifetime is longer than any publicly trusted authority is allowed to grant, which means it did not come from one.
tls.certificate.validity-too-long
- Certificate uses a key that is too small
The certificate's key is smaller than the current minimum, so the encryption protecting the site is weaker than it should be.
tls.certificate.weak-key
- Certificate is signed with a broken hash algorithm
The certificate is signed using an outdated method that can be forged. Browsers have rejected these since 2017.
tls.certificate.weak-signature-algorithm
- Certificate uses an unusually broad wildcard
The certificate covers a very wide range of names. If its private key ever leaks, the damage extends far beyond this one site.
tls.certificate.wildcard-too-broad
- Server accepts a broken cipher suite
One of the encryption methods the server agrees to is broken — it can be read, forged, or provides no protection at all.
tls.protocols.insecure-cipher
- Some connections have no forward secrecy
For some connections the server uses a method where one leak of its private key would expose every past conversation that anyone recorded.
tls.protocols.no-forward-secrecy
- Neither TLS 1.2 nor TLS 1.3 is supported
The server offers only versions of TLS that browsers have already removed. Most visitors cannot connect at all.
tls.protocols.no-tls12
- TLS 1.3 is not supported
The server does not offer the current version of TLS. Connections still work over the older version, but they are slower to set up and lack its safety…
tls.protocols.no-tls13
- Protocol and cipher support could not be tested
We could not run the handshakes needed to find out which TLS versions this server accepts, so this part of the report is missing rather than clear.
tls.protocols.probe-unavailable
- SSL 2.0 is enabled
The server still accepts a protocol from 1995 that is completely broken. Its presence weakens the modern connections too.
tls.protocols.sslv2-enabled
- SSL 3.0 is enabled
The server accepts SSL 3.0, which has been formally prohibited since 2015 and can be attacked to reveal parts of an encrypted session.
tls.protocols.sslv3-enabled
- TLS 1.0 is enabled
The server still accepts TLS 1.0, a version from 1999 that browsers removed in 2020. Keeping it available lets a connection be pushed down to it.
tls.protocols.tls10-enabled
- TLS 1.1 is enabled
The server accepts TLS 1.1, which browsers removed alongside TLS 1.0 in 2020. It offers nothing TLS 1.2 does not.
tls.protocols.tls11-enabled
- Server accepts a weak cipher suite
One of the encryption methods on offer is outdated. It is not trivially broken, but it has known weaknesses and nothing current needs it.
tls.protocols.weak-cipher
HTTP (25)
- The caching instructions contradict each other
The response asks for two different things at once — for example, do not reuse this, and also reuse it for an hour.
http.headers.cache-directives-conflicting
- A text response does not declare its character encoding
The response says it is text but not which alphabet it is written in, so the browser works it out from the bytes.
http.headers.charset-missing
- The declared Content-Encoding may not match the body
The response claims to be compressed, but the body we measured was the same size as the uncompressed one.
http.headers.compression-encoding-mismatch
- A compressible response was sent uncompressed
This page is text, it is big enough to be worth compressing, and we asked for a compressed copy — the server sent it in full anyway.
http.headers.compression-not-applied
- The response has a body but no Content-Type
The server sent content without saying what kind of content it is, so each browser guesses.
http.headers.content-type-missing
- The response sends obsolete headers, one of them harmful
Some of these headers do nothing at all now. One of them switches on a browser feature that was removed because it could itself be used to attack the page.
http.headers.deprecated-header-present
- No Alt-Svc header advertises HTTP/3
The response does not mention that an HTTP/3 endpoint is available. This is a note, not a problem — and it only tells you what was advertised, not what your…
http.headers.http3-not-advertised
- A response header leaks an internal address
One of your headers contains an address from inside your own network — a private IP or an internal-only hostname.
http.headers.internal-address-disclosed
- The response does not say how long it may be cached
Your page arrives with no caching instructions, so browsers and networks in between invent their own.
http.headers.no-cache-control
- The response cannot be revalidated without downloading it again
Your response carries no fingerprint, so a browser holding an old copy has no way to ask 'has this changed?'. It has to download the whole thing to find out.
http.headers.no-validator
- A compressed response does not vary on Accept-Encoding
The server sends different versions of this page depending on what the visitor's browser can unpack, but it does not tell shared caches that.
http.headers.vary-missing-accept-encoding
- Vary: * makes the response uncacheable by any shared cache
This response tells every shared cache and CDN never to reuse it. If you are paying for a CDN in front of this site, this header is switching it off.
http.headers.vary-wildcard
- The site's home page returns an error status
The address answered, but with an error code rather than a page. Visitors landing on the home page see an error.
http.reachability.error-status
- Plain HTTP is not served at all
Nothing answers on the insecure port. That is a safe configuration — there is no unencrypted request to intercept — with one practical caveat.
http.reachability.http-closed
- Plain HTTP does not redirect to HTTPS
The insecure port serves the site instead of sending visitors to the secure one. Anyone typing your address without `https://` gets an unencrypted page.
http.reachability.http-open-no-redirect
- The site does not answer over HTTPS
Nothing responded on the secure port. Either the site is down, the encrypted service is not running, or something between us and it is blocking the…
http.reachability.https-unreachable
- The server was slow to respond
The home page took noticeably long to start responding. Visitors feel this as the site hanging before anything appears.
http.reachability.slow-response
- The redirect chain is longer than it needs to be
Visitors are bounced through several addresses before reaching the page. Each bounce is a full round trip they wait for.
http.redirects.chain-too-long
- The chain moves between hostnames
Visitors are handed from one hostname to another along the way. That is normal — it is how `www` redirects and content networks work — and it is recorded…
http.redirects.cross-host-hop
- A redirect pointed somewhere the scanner will not follow
One step of the chain led to an address we refuse to connect to — a private network address, a cloud metadata endpoint, or an internal-only name.
http.redirects.hop-refused
- The redirect chain loops
The site sends visitors in a circle: one address redirects to another, which redirects back. Browsers give up and show an error instead of the page.
http.redirects.loop
- A redirect destination is malformed
The address the server redirected to is not a usable web address. Browsers may refuse it, or may interpret it in a way you did not intend.
http.redirects.malformed-location
- A redirect response has no destination
The server said 'go somewhere else' without saying where. Browsers show a blank page or an error.
http.redirects.missing-location
- A redirect drops from HTTPS to plain HTTP
Part of the journey moves visitors from the secure address back to the insecure one. Whatever they send after that point travels in the clear.
http.redirects.protocol-downgrade
- A permanent redirect is marked temporary
The redirect between your `www` and non-`www` addresses says 'this is temporary'. Browsers and search engines therefore keep asking for the old address every…
http.redirects.temporary-for-canonical
Web security (42)
- Cookie sets a Domain the browser will not accept, so it is discarded
The cookie names a domain that this host is not part of. A browser does not narrow the scope in that case — it throws the whole cookie away, so the cookie is…
web.cookies.domain-not-accepted
- Cookie carries an attribute browsers cannot read
Part of the cookie's definition is not valid. Browsers ignore the unreadable part, so the cookie may behave differently from how it was written.
web.cookies.malformed-attribute
- Cookie can be read by JavaScript
This cookie has no HttpOnly flag, so any script running on the page can read it — including a script that was injected.
web.cookies.no-httponly
- Cookie has no SameSite attribute
You have not said whether this cookie should be sent when another website triggers a request to yours.
web.cookies.no-samesite
- Cookie is sent over unencrypted connections
This cookie has no Secure flag, so the browser also sends it over plain HTTP. Anyone on the same network can read it from that request.
web.cookies.no-secure
- The page set no cookies
No cookies were set on the page we checked. There is nothing to grade here.
web.cookies.none-set
- Cookie is shared with every subdomain
The cookie carries a Domain attribute, so it is not scoped to this host alone: every subdomain of that domain receives it too — including ones you may not…
web.cookies.overly-broad-domain
- Cookie name promises protections its attributes do not provide
The cookie's name starts with a special prefix that browsers enforce rules for, and those rules are not met — so the browser rejects the cookie entirely.
web.cookies.prefix-requirements-unmet
- Cookie uses SameSite=None without Secure, so it is rejected
This combination is invalid and browsers throw the cookie away. Whatever it was for is not working.
web.cookies.samesite-none-insecure
- The CORS policy accepts any request header from any origin
The preflight said another site may send any header it likes with its request — on a policy that does not restrict which sites may ask.
web.cors.headers-overly-broad
- The Access-Control-Allow-Origin value is not a valid origin
The header is there but its value is not something a browser can use — several origins at once, a trailing slash, a path, or a hostname with no https:// in…
web.cors.malformed-allow-origin
- The CORS policy grants broad methods on an unrestricted origin
The preflight said which HTTP methods another site may use, and the list includes ones that change or delete data — on a policy that does not restrict which…
web.cors.methods-overly-broad
- The null origin is on the CORS allow-list
The server allows an origin called `null`. That is not a website — it is what the browser sends for sandboxed frames and local files, and any page on the…
web.cors.null-origin-allowed
- Any website is allowed to read this site's responses
The server told a website we invented that it may read this page's contents. It will tell any website the same thing.
web.cors.origin-reflected
- Any website can read authenticated responses from this site
We asked for this page while claiming to be a website we made up, and the server said that website is allowed to read the answer — with the visitor's cookies…
web.cors.origin-reflected-with-credentials
- Preflight results are not cached
Before most cross-origin calls the browser asks permission with a separate request.
web.cors.preflight-not-cached
- The CORS response varies by origin but is not marked Vary: Origin
The allowed-origin header changes depending on who asks, but the response does not tell caches that.
web.cors.vary-origin-missing
- Resources are shared with every origin, without credentials
This endpoint tells every website it may read the response, and no cookies are involved. That is the normal, correct setting for something meant to be public.
web.cors.wildcard-origin
- The CORS policy pairs a wildcard origin with credentials
The response says every website is allowed, and also that cookies should be sent. Browsers refuse that combination, so the cross-origin request fails and…
web.cors.wildcard-with-credentials
- No Cross-Origin-Embedder-Policy is set
The page has not required embedded resources to opt in to being loaded. This is optional and only matters for specific advanced features.
web.security-headers.coep-missing
- No Cross-Origin-Opener-Policy is set
Windows your site opens, and windows that open your site, can still reach into each other. Setting this separates them.
web.security-headers.coop-missing
- No Cross-Origin-Resource-Policy is set
Other sites may load this page's resources directly. For a public site that is normal; for private content it is worth restricting.
web.security-headers.corp-missing
- No Content Security Policy is enforced
Nothing limits where the page may load scripts from. If a script is ever injected — through a comment field, a compromised plugin, or a third-party widget —…
web.security-headers.csp-missing
- The policy leaves plugins or the base URL unrestricted
Two easily-forgotten parts of the policy are unset. Both are used to work around otherwise strict policies.
web.security-headers.csp-no-object-or-base
- The Content Security Policy is report-only
A policy exists but the browser only reports what it would have blocked. Nothing is actually blocked.
web.security-headers.csp-report-only
- The policy allows eval()
The policy lets the page turn text into running code. Anything that can control that text can run code on your site.
web.security-headers.csp-unsafe-eval
- The policy allows inline scripts or styles
The policy permits code written directly into the page. That is the exact form injected code takes, so this removes most of the policy's value.
web.security-headers.csp-unsafe-inline
- The policy allows resources from anywhere
Part of the policy uses a wildcard, which permits any address at all. That directive restricts nothing.
web.security-headers.csp-wildcard-source
- A security header was sent twice with different values
The same header arrived more than once with conflicting values. Which one applies depends on the browser, so the protection you think you have may not be the…
web.security-headers.duplicate-conflicting
- HSTS max-age is shorter than six months
The instruction to always use HTTPS expires sooner than it should. A visitor who has not been back for a while makes an insecure first request again.
web.security-headers.hsts-max-age-too-low
- HTTP Strict Transport Security is not in force
Browsers are not told to always use the secure version of your site. The first visit of every day can still be made over plain HTTP, where it can be…
web.security-headers.hsts-missing
- HSTS does not cover subdomains
The always-use-HTTPS instruction applies to this hostname only. Subdomains can still be reached over plain HTTP.
web.security-headers.hsts-no-subdomains
- The site is not set up for HSTS preloading
Browsers only learn to force HTTPS after the first visit. Preloading builds that instruction into the browser itself, so even the very first visit is secure.
web.security-headers.hsts-not-preloaded
- A response header is malformed
One of the headers contains something that should not be in a header — a line break, or a value far longer than any header needs.
web.security-headers.malformed-value
- The page can be embedded in another site
Nothing stops another website from loading your page inside an invisible frame and tricking visitors into clicking things they cannot see.
web.security-headers.no-frame-protection
- No Permissions-Policy is set
You have not restricted which browser features the page — and anything embedded in it — may use, such as the camera, microphone or location.
web.security-headers.permissions-policy-missing
- No Referrer-Policy is set
You have not said how much of your addresses to share when visitors follow a link away from your site.
web.security-headers.referrer-policy-missing
- The Referrer-Policy leaks full URLs
The policy you set sends your complete addresses — including the path and anything after the question mark — to other websites visitors click through to.
web.security-headers.referrer-policy-weak
- The server announces its exact version
Every response says which software you run and which version. That turns 'find a vulnerable site' into a search query.
web.security-headers.server-version-disclosed
- Response headers name the application stack
Headers such as X-Powered-By tell every visitor which framework and version builds your pages. They serve no purpose for the visitor.
web.security-headers.technology-disclosed
- Browsers may guess the type of your responses
Without this header a browser may ignore what you say a file is and decide for itself — which can turn an uploaded image into a running script.
web.security-headers.xcto-missing
- The exact version of your CMS is published on every page
Your site tells every visitor which version of {{product}} it runs. Anyone can compare that number against the list of known vulnerabilities for it without…
web.technology.cms-version-disclosed
Network (6)
- A database port is reachable from the internet
Port {{port}} on {{host}} accepts connections from anywhere on the internet, and that port is where {{service}} listens.
net.ports.database-exposed
- FTP is reachable from the internet
Port 21 on {{host}} accepts connections. FTP sends the username, the password and the file contents in clear text, so anyone able to observe the connection…
net.ports.ftp-exposed
- Ports reachable from the internet
{{summary}} Each one is listed with what normally listens there and whether being reachable from the internet is expected for that service.
net.ports.open
- No port could be tested
We were not able to run the port check on {{host}}, so this section reports nothing at all rather than reporting that everything is closed.
net.ports.probe-unavailable
- A remote desktop service is reachable from the internet
Port {{port}} on {{host}} accepts connections from anywhere, and that port is where {{service}} listens — remote desktop, either RDP or VNC.
net.ports.remote-admin-exposed
- SSH is reachable from the internet
Port 22 on {{host}} accepts connections. This is normal — it is how most servers are administered — and it is worth knowing, because it guarantees a…
net.ports.ssh-exposed
Performance (18)
- The page jumps around while it loads for real visitors
Content on {{scope}} moves after it has already appeared, scoring {{value}} for a quarter of real visits. Google's threshold for a good experience is 0.1.
perf.crux.cls-poor
- Real visitors stare at a blank page for too long
For a quarter of real visits to {{scope}}, {{value}} passed before anything at all was drawn on the screen.
perf.crux.fcp-slow
- Real-user experience over the last 28 days
This is what real Chrome visitors experienced on {{scope}} over the trailing 28-day window, and whether the site passes Google's Core Web Vitals assessment.
perf.crux.field-data
- The page is slow to respond when real visitors interact with it
When real visitors tapped, clicked or typed on {{scope}}, the page took {{value}} to show a visible response for a quarter of those interactions.
perf.crux.inp-poor
- Not enough real-user traffic for field data
Chrome does not publish real-user performance data for {{scope}}. That almost always means the site does not get enough Chrome visits to reach the reporting…
perf.crux.insufficient-data
- Real visitors wait too long for the main content to appear
For a quarter of real visits to {{scope}}, the largest thing on the screen — usually the hero image or the headline — took {{value}} to appear.
perf.crux.lcp-poor
- Real-user performance data was not requested
We did not look up how real visitors experience this site, because this deployment has no Chrome UX Report API key.
perf.crux.not-configured
- Real-user performance data could not be retrieved
The Chrome UX Report API did not answer our request, so we have no real-user data to show. This is a failure on our side or Google's, not on yours.
perf.crux.query-failed
- The server takes too long to send the first byte to real visitors
For a quarter of real visits to {{scope}}, {{value}} passed before the server sent anything at all. Google's guidance is 800 milliseconds.
perf.crux.ttfb-slow
- The page ships more JavaScript than it uses
This page downloads {{totalJs}} of JavaScript, of which roughly {{unusedBytes}} is never executed during the page load.
perf.lab.excessive-javascript
- Images are served in older, heavier formats
{{count}} image(s) are served as JPEG, PNG or GIF where AVIF or WebP would carry the same picture in far fewer bytes — an estimated {{savingsBytes}} less on…
perf.lab.images-legacy-format
- Images are much larger than the space they are shown in
{{count}} image(s) on this page are downloaded at a far higher resolution than they are displayed at.
perf.lab.images-oversized
- Lab measurement of one page load
These are the timings and the resource breakdown from a single controlled load of {{scope}} in a browser we drive. They show where the time and the bytes go.
perf.lab.metrics
- Stylesheets and scripts stop the page from rendering
{{count}} resource(s) on this page must be downloaded and processed before the browser is allowed to draw anything.
perf.lab.render-blocking-resources
- This report never publishes a headline performance score
We measured {{scope}} in a browser, and we are showing you what we found — but we do not publish a single 0-100 speed score, on this run or any other.
perf.lab.score-withheld
- Static files are re-downloaded because they are barely cached
{{count}} static file(s) this page loads — scripts, stylesheets, fonts, images — are served with a short or missing cache lifetime, so returning visitors…
perf.lab.static-assets-short-cache
- Scripts and stylesheets are sent without compression
{{count}} text file(s) this page loads — JavaScript, CSS, JSON or SVG — arrived uncompressed.
perf.lab.subresources-uncompressed
- The page was not measured in a browser
We did not load {{scope}} in a real browser, so there is no lab measurement in this report. Nothing about the site's speed is being claimed here, good or bad.
perf.lab.unavailable
SEO (33)
- The page declares more than one canonical URL
This page names {{count}} different canonical URLs. When a page gives conflicting answers, search engines disregard all of them and decide for themselves.
seo.canonical.conflicting
- The canonical URL cannot be used
The page declares a canonical, but the value is not a usable web address, so search engines have nothing to act on.
seo.canonical.invalid
- The page declares no canonical URL
There is no `<link rel="canonical">` on this page. Search engines will choose which version of the URL to show, and their choice may not be the one you would…
seo.canonical.missing
- The canonical URL points at a different page
This page tells search engines that a different URL is the one to index. That is often exactly right — it is how duplicate versions of a page are…
seo.canonical.points-elsewhere
- The page has no h1 heading
There is no `<h1>` in the served HTML. The top-level heading is how both readers and assistive technology identify what the page is about.
seo.headings.h1-missing
- The heading levels skip a level
The page jumps from one heading level to a level more than one below it — an `<h4>` directly under an `<h2>`, for example.
seo.headings.hierarchy-skipped
- The page has more than one h1
This page uses {{count}} `<h1>` elements. HTML5 permits this and search engines handle it, so it is reported for you to consider rather than as a fault.
seo.headings.multiple-h1
- An hreflang annotation is not valid
{{count}} of the page's `hreflang` links are malformed. Search engines discard the whole annotation set when it cannot be parsed, so the other language…
seo.hreflang.invalid
- The hreflang set does not include this page
The page lists alternate language versions but does not list itself. Google's documentation requires every page in a set to reference every page in the set,…
seo.hreflang.missing-self-reference
- The page's declared language is not a well-formed language tag
`<html lang="{{lang}}">` is not the shape BCP 47 defines for a language tag. A tag that cannot be parsed is discarded, which leaves the page in the same…
seo.html-lang.invalid
- The page does not declare what language it is written in
The `<html>` element carries no `lang` attribute, so nothing in the markup says what language the page is written in.
seo.html-lang.missing
- Images on the page have no alt attribute
{{missing}} of {{total}} images have no `alt` attribute at all. Anyone using a screen reader gets nothing in their place, and image search has no text to…
seo.images.missing-alt
- robots.txt blocks this page from being crawled
Your robots.txt tells crawlers not to fetch this page. They will not read it, so its content cannot be used in search results.
seo.indexability.blocked-by-robots-txt
- The page tells crawlers not to follow its links
A `nofollow` directive applies to every link on this page. Crawlers will still read the page, but they will not use its links to find anything else.
seo.indexability.nofollow
- The page asks search engines not to index it
This page carries a `noindex` directive, which tells search engines to leave it out of their results entirely.
seo.indexability.noindex
- A noindex directive is unreachable behind a robots.txt block
This page carries a `noindex` directive and is also blocked in robots.txt. Because crawlers never fetch the page, they never see the directive — so the page…
seo.indexability.noindex-blocked-by-robots
- The meta description is likely to be truncated or is very short
The description is {{length}} characters. {{detail}} As with the title, this is about how much is displayed, not about ranking.
seo.meta-description.length-outside-guidance
- The page has no meta description
There is no meta description on this page. Search engines will write the snippet under your result themselves, using text they pick from the page.
seo.meta-description.missing
- The page declares the same metadata more than once
This page carries more than one {{field}}, with different values. Which one is used is decided by the consumer, and different consumers decide differently.
seo.meta.duplicate-tags
- The title and the meta description are identical
The description repeats the title word for word. A search result then shows the same sentence twice, which wastes the only two lines you get.
seo.meta.title-matches-description
- Open Graph metadata is missing required properties
When this page is shared on a social platform or in a chat app, the preview is assembled from Open Graph tags.
seo.opengraph.incomplete
- No robots.txt is published
There is no robots.txt at the site root. This is not a fault — RFC 9309 says a crawler that gets a 404 may access everything — and it is worth knowing…
seo.robots-txt.missing
- The robots.txt at the site root was not readable as directives
`/robots.txt` did not return a file a crawler can read: an HTML error page served with a success status, a refusal, a redirect this scan does not follow, or…
seo.robots-txt.unreadable
- No XML sitemap could be found
Neither robots.txt nor the conventional `/sitemap.xml` location produced a sitemap.
seo.sitemap.missing
- The sitemap is not declared in robots.txt
A sitemap was found at the conventional location, but robots.txt does not mention it. Crawlers that do not guess that location will not find it.
seo.sitemap.not-declared
- The sitemap URL does not return XML
Something answers at `{{sitemapUrl}}`, but it is not an XML sitemap. Crawlers will discard it, so the sitemap is effectively missing while appearing to be…
seo.sitemap.not-xml
- The page carries no JSON-LD structured data
No JSON-LD was found. Structured data is optional — it makes a page eligible for enhanced result formats, and its absence costs nothing beyond that…
seo.structured-data.absent
- A JSON-LD block on the page does not parse
{{count}} of the page's JSON-LD blocks are not valid JSON, so they are discarded entirely. The markup is present and is doing nothing.
seo.structured-data.invalid
- Structured data is missing a documented required property
The page's {{type}} markup is missing {{property}}, which Google's documentation lists as required.
seo.structured-data.missing-required-property
- Structured data uses a type that no longer produces a rich result
The page marks up {{types}}, which Google no longer shows as an enhanced result. The markup is still valid and harmless — it just no longer earns anything in…
seo.structured-data.retired-type
- The title is likely to be truncated or is very short
This page's title is {{length}} characters. {{detail}} This is a display guideline, not a ranking factor — a long title is cut off in the result, not…
seo.title.length-outside-guidance
- The page has no title
There is no `<title>` on this page, or it is empty. The title is the clickable line in a search result and the text in the browser tab, so search engines…
seo.title.missing
- No Twitter card type is declared
The page declares no `twitter:card`. Most platforms fall back to the Open Graph tags, so a page with good Open Graph metadata usually previews correctly…
seo.twitter-card.missing
Technology (1)
- Technologies identified from the response
This is what the site's response and page source suggest it is built with. It is an observation, not a problem, and each entry carries how sure we are.
web.technology.detected
No rules match that combination.