Dataset documentation · Free and paid

Domain Posture & Intelligence

What every domain publishes for email authentication and transport security — SPF, DMARC, MTA-STS, DNSSEC and BIMI — and what those records actually say. One row per registrable domain.

Not yet on a cloud marketplace. Talk to us about access while the listing is in preparation.

Grain
One row per registrable domain
Refresh
Daily
Free tier
16 of 21 columns
Every domain, not a sample — paid adds columns, not rows
License
Clean for redistribution
01

Overview

One row per registrable domain, carrying the email-authentication and transport-security records that domain publishes in DNS, and what each record says. Not whether a domain looks secure — what it has actually published, read from the live record.

The distinction that makes it useful is between publishing a control and enforcing one. A domain can publish DMARC and ask receivers to do nothing about failures. This dataset separates the two: dmarc_present says a record exists, dmarc_policy and dmarc_enforced say whether it does anything. The same split runs through SPF, MTA-STS and BIMI.

The free tier is the whole estate, not a sample. Every domain we have observed is in it, with 16 of the 21 columns. The paid tier adds five columns of depth on the same rows — it does not add domains.

Observed by Datazag from public DNS. No third-party feed is redistributed through it, and every release passes an automated licensing gate that scans each published value before it leaves our boundary.

Datazag observes 370M+ live domains daily; this dataset is the posture layer of that corpus.

02

Schema reference

Table: domain_intel

Columns shipped in domain_intel
ColumnTypeDescription
domainJoin keyVARCHARThe registrable domain this row describes. Unique across the table.
spf_presentBOOLEANWhether the domain publishes an SPF record.
spf_qualifierVARCHARHow the domain's SPF record treats senders it does not list: -all rejects them, ~all marks them soft-fail, ?all is neutral, +all permits anyone, and no-all means the record ends without an all mechanism. Empty where no SPF record was published, or where the record ended in something we could not read as a valid qualifier.
spf_include_countINTEGERPaid tier. How many include: mechanisms the SPF record chains to. SPF permits at most 10 DNS lookups, so a high count is a sign the record is close to failing.
dmarc_presentBOOLEANWhether the domain publishes a DMARC record.
dmarc_policyVARCHARThe action the domain asks receivers to take on mail that fails DMARC: none, quarantine or reject. Empty where no valid policy was published — an unrecognised p= is invalid under RFC 7489, and we do not guess an intent the domain never declared.
dmarc_enforcedBOOLEANWhether the DMARC policy is actually enforcing, rather than published in monitor-only mode. This is the column to filter on when you want domains that are protected rather than domains that have a record.
dmarc_ruaBOOLEANPaid tier. Whether the DMARC record requests aggregate reports, which indicates the owner is monitoring results rather than publishing and forgetting.
dmarc_pctINTEGERPaid tier. The percentage of failing mail the domain asks receivers to apply its policy to. Below 100 the policy is only partially applied. A DMARC record that omits this value is applying its policy in full, and is published here as 100; this is empty only where there is no DMARC record at all.
mta_stsBOOLEANWhether the domain publishes an MTA-STS policy, which asks senders to require TLS when delivering to it.
dnssecBOOLEANWhether the domain is signed with DNSSEC.
tlsrpt_presentBOOLEANWhether the domain publishes a TLS-RPT record requesting reports about delivery failures over TLS.
bimi_presentBOOLEANWhether the domain publishes a BIMI record, used to display a brand logo in supporting mail clients.
bimi_has_vmcBOOLEANPaid tier. Whether that BIMI record references a Verified Mark Certificate, the stronger form that requires the trademark to have been verified.
is_parkedBOOLEANWhether the domain appears to be parked rather than in active use. This is our assessment from the domain's DNS configuration on the snapshot date, not a fact the domain publishes, and the indicators behind it are maintained over time.
primary_mx_hostVARCHARThe hostname of the domain's primary mail exchanger, where it publishes one. A hostname only — this dataset carries no ASN, prefix or provider column.
posture_first_seen_atTIMESTAMPWhen we first observed this domain's email posture. Posture capture began on 2026-08-20, so no value precedes that date. It is not the domain's registration date and not the first time the domain existed.
last_observed_atTIMESTAMP WITH TIME ZONEWhen this posture was last observed, in UTC. Domains are re-observed on a rolling basis, so this varies across rows within a single release.
snapshot_dateDATEThe date this row was built. Every row in a release carries the same date, so you can pin an analysis to a snapshot.
tierVARCHARDistribution tier this row belongs to. Every row is in the free tier; the paid tier adds columns, not rows.
data_completenessVARCHARPaid tier. Records, per signal, whether the domain published a value we could read, published nothing, or published something that could not be parsed. Most domains do not publish DMARC, SPF or MTA-STS at all, and that absence is a finding rather than a gap in our observation.

16 of these 21 columns are in the free tier, on every domain. The five marked Paid tier — spf_include_count, dmarc_rua, dmarc_pct, bimi_has_vmc and data_completeness — are the correctness layer: how close an SPF record is to its lookup limit, whether the owner is collecting reports, how much of the policy is actually applied, whether the BIMI mark is verified, and what we could and could not read per signal. The paid tier adds no domains.

03

Join guide

The grain is the registrable domain and it is unique, so this is a plain equi-join against your own domain list. Normalise your side to the registrable domain first — a row for mail.example.com will not match, because the table keys on example.com.

Which of your domains publish DMARC but do not enforce it

The gap this dataset exists to show: a record is published, and it asks receivers to do nothing.

sql
SELECT d.domain,
       p.dmarc_policy,
       p.spf_qualifier
FROM   your_domains d
JOIN   domain_intel p USING (domain)
WHERE  p.dmarc_present
  AND  NOT p.dmarc_enforced
ORDER  BY d.domain;

dmarc_enforced is the column to filter on. dmarc_present only says a record exists.

Score an acquisition target's estate in one pass

Counts of what is published against what is enforced, across a domain list.

sql
SELECT count(*)                                   AS domains,
       count(*) FILTER (WHERE spf_present)      AS with_spf,
       count(*) FILTER (WHERE dmarc_present)    AS with_dmarc,
       count(*) FILTER (WHERE dmarc_enforced)   AS enforcing_dmarc,
       count(*) FILTER (WHERE dnssec)           AS signed,
       count(*) FILTER (WHERE mta_sts)          AS with_mta_sts
FROM   domain_intel
JOIN   your_domains USING (domain);

Every column here is in the free tier.

Exclude parked domains before you count

Parked domains depress every posture rate, and they are rarely what the question is about.

sql
SELECT count(*) FILTER (WHERE dmarc_enforced) * 100.0 / count(*) AS pct_enforcing
FROM   domain_intel
WHERE  NOT is_parked;

is_parked is our assessment from DNS configuration, not a declaration by the domain.

04

Methodology & caveats

A domain that is absent has not been observed yet

Posture is captured by a rolling backfill that began on 2026-08-20 and is still working through the corpus. A domain missing from a release has not been observed yet — it does NOT mean the domain publishes nothing. Do not treat absence as a finding, and do not compute a percentage against your own list without accounting for the rows that are not there. last_observed_at and snapshot_date let you measure the coverage of any release yourself rather than taking a number from us.

Published is not enforced

Every control here is split between whether a record exists and what it says, because the two answer different questions. dmarc_present is true for a domain whose policy is p=none, which asks receivers to take no action at all. spf_qualifier distinguishes a record ending in -all from one ending in ?all. If you are measuring protection rather than adoption, filter on dmarc_enforced and on the qualifier, not on the presence flags.

Absent values mean absent records, not gaps in observation

Most domains do not publish DMARC, SPF or MTA-STS at all. Where a column is empty, the usual reason is that the domain published nothing — that is the finding. Where a domain published something we could not read as valid, we publish nothing rather than guessing: an unrecognised DMARC p= is invalid under RFC 7489, and inventing an intent the domain never declared would be worse than an empty cell. The paid data_completeness column records which of the two happened, per signal, per domain.

dmarc_pct is effective, not raw

RFC 7489 defines an absent pct= as 100, so a DMARC record without one is applying its policy in full. We publish that as 100 rather than as an empty cell, because publishing it raw made full application look like missing data on almost every row. dmarc_pct is empty only where there is no DMARC record. Where the distinction matters, data_completeness records whether the value was stated explicitly or defaulted.

is_parked is our assessment, and it moves

Parking is inferred from the domain's DNS configuration on the snapshot date against a maintained list of indicators. It is not something the domain declares, the indicator list changes as parking services come and go, and a domain can therefore change state between releases without its DNS changing. Treat it as a filter, not as a fact about the registrant.

What this dataset does not contain

There is no ASN, prefix, IP address or hosting-provider column here, and no remediation guidance. primary_mx_host is a hostname and nothing more. If you need the network layer behind a domain, that is IP to ASN Intelligence, and joining the two is your own step.

06

Changelog

  1. Free and paid tiers defined by column. Every domain is in the free tier with 16 of 21 columns; the paid tier adds five columns on the same rows.

  2. first_seen_at renamed posture_first_seen_at. It is the first posture observation, not the first sighting of the domain, and the old name said otherwise.

  3. mta_sts_mode withdrawn. At 99.95% empty it promised a field it did not have; mta_sts (presence) still ships, and the paid data_completeness column still records whether a mode was published.

  4. dmarc_pct is now effective rather than raw: a DMARC record with no pct= reads 100, per RFC 7489, instead of empty. It is empty only where there is no DMARC record.