User Tools

Site Tools


provenance:programming:crawler:webxray:random_sample

Table of Contents

Provenance appendix: webXray ownership accuracy, random sample

The scripts and the unedited output behind the random-sample accuracy measurement of 2026-09-05 — the one that produced the per-list current / stale / granularity / error rates on Programming:Crawler:webXray.

Read the provenance page first: the queries, the denominators, the limits, the corrections and the judgement calls are there, and this page is only the code and the raw output they refer to. Corpus-level caveats are on corpus.

Why this is a separate page. These blocks are 218 kB, and the parent provenance page is already large without them. Raw size alone would not decide it — literature:bibliography is 388 kB and renders fine — but ~60 kB of this is syntax-highlighted Python and JavaScript, which is the expensive kind, and a reader who came to check one denominator would have to scroll past all of it. The exact arithmetic is on the parent page, which is built after this one and can measure both. Splitting the appendix out is a readability call and nothing else: no figure is derived only here. Several are only shown here — the 175-row adjudication table, the per-verdict tables, the concentration test and the raw Wayback output — and the parent page and the content page both send you here for them.

Every block is read from the committed file when this page is generated (scripts/build_webxray_random_sample_page.py), so the code published here is the code that ran. Nothing is retyped, abridged or reflowed. Two transformations are applied and both are disclosed rather than assumed away:

  • trailing newlines are stripped, because DokuWiki discards them inside a block anyway;
  • line endings are normalised to LF. The last column of the table below says, per file, whether that changed a byte. It changes one byte in one file (out/probe_all.txt, which carries a lone CR inside a copyright line scraped from a live site) and nothing in the other twenty-two.

The bytes and SHA-256 in the table are of the file on disk, not of the block, so a reader reconstructing a file from a block must restore the trailing newline — and, for the one flagged file, the CR — before hashing it. If a block disagrees with its file in any other way, the page was hand-edited and should not be trusted.

Section File Bytes on disk SHA-256 (16) of the file Block differs from the file?
A scripts/owner_sample.py 8,324 7a5e85364c37ee65 no
B scripts/owner_probe.sh 2,315 32d007987c13f9e7 no
C out/adj/INSTRUCTIONS.md 4,965 1985026abac3d888 no
D scripts/owner_merge_rows.py 4,572 84ee130f2e8c2310 no
E scripts/owner_verify_sources.py 6,814 b7c45900dc5ed28e no
F scripts/owner_verify_rendered.mjs 2,923 0bf6b4615724e84d no
G scripts/owner_corrections.py 6,847 f145c0908d4bf9a6 no
H scripts/owner_verdict_fixes.py 7,894 2b1bc378b8cb6750 no
I scripts/owner_random_sample.py 17,780 9ff3ddf1dab339c5 no
J scripts/owner_selfname_census.py 3,356 fb51b754b1d4defd no
K scripts/owner_citation_audit.py 4,417 01045f4212b8d247 no
L scripts/check_owner_sample_figures.py 5,221 f12705ff7ba1f0ea no
M scripts/check_owner_sample_figures_mutations.sh 1,886 8d0966c0c3b90131 no
N scripts/owner_reestimate_independent.py 4,646 aeb6db259f0b8489 no
O scripts/check_wrapped_lists.py 4,153 1eb751957508116a no
P scripts/wayback_webxray.sh 2,625 80c3b9a6378508b0 no
Q out/owner_sample-output.txt 1,657 90f34e73b14c797b no
R out/owner_corrections-output.txt 4,830 961e16e7549cd98c no
S out/owner_verdict_fixes-output.txt 4,006 0322ffec6b5dbdbf no
T out/owner_citation_audit-output.txt 1,252 b40a2f1db1afce1d no
U out/owner_selfname_census-output.txt 1,915 0585b93316e985df no
V out/owner_random_sample-output.txt 56,362 738fe1a7a5bca5d5 no
W out/owner_reestimate_independent-output.txt 1,815 ce1a81da3c8afa54 no
X out/wayback_webxray-output.txt 10,502 bc0e9c6770fd3654 no
Y out/check_owner_sample_figures_mutations-output.txt 467 3a175553faf88b25 no
Z out/probe_all.txt 51,227 3def89e0d3fc8a14 yes — one lone CR normalised to LF

A. scripts/owner_sample.py — the frame and the draw

Builds the sampling frame, splits each list's coverage into prevalence quartiles, and draws 24/12/12/12 from them under seed 20260905. It hashes the six input files it read, so a later run that produces different numbers can be told apart from a later run against different data.

owner_sample.py
#!/usr/bin/env python3
"""Draw the probability sample of registrable domains whose ownership is
adjudicated in ``owner_random_sample.py``.
 
``owner_adjudication.py`` settled the 30 highest-prevalence *disagreements*
between webXray, Tracker Radar and Disconnect.  That set is selected exactly
where the lists differ, so it says nothing about how often any one list is
right.  This script draws the sample that can: a stratified random sample of
each list's **own coverage**, so that "of the domains this list names an owner
for, what share name today's owner" is estimable with a confidence interval.
 
Design, and why each choice was made:
 
* **One sample per list, not one shared sample.**  webXray names an owner for
  664 registrable domains in the universe below, Tracker Radar for 5,566.  A
  single sample from the union would leave ~10 webXray rows -- an estimate with
  no useful interval.  Restricting a sample of the union to one list's members
  is still a valid simple random sample of that list, but the *size* is set by
  the sparsest list, so each list is sampled from its own frame instead.  A
  domain drawn for one list is adjudicated once and its verdict recorded for
  all three; verdicts outside a list's own sample are reported separately and
  never merged into its estimate.
 
* **Frame = the ICANN-fold universe of ``owner_dbs.py``.**  Registrable domains
  appearing in Tracker Radar's ``domain_summary.json``, folded with the ICANN
  section of the PSL only, resolved by parent-label lookup.  That is Tracker
  Radar's view of the third-party surface, not a neutral census, and every
  figure inherits that.  Restricting the frame to domains Tracker Radar's crawl
  actually saw is deliberate: an entry for a domain nobody ever requests is not
  a measurement error anybody meets.
 
* **Strata = prevalence quartiles of the list's own coverage.**  The brief asked
  for deciles.  With 60 draws per list, deciles give 6 rows per stratum, which
  supports no stratum-level statement at all; quartiles give 12-24.  The
  deviation is deliberate and is stated on the page.
 
* **Allocation 24/12/12/12, heaviest at the head.**  Equal allocation over
  equal-size strata is just a simple random sample, and would put 15 rows behind
  the ~95% of prevalence mass that sits in the top quartile.  Disproportionate
  allocation is corrected for by stratum weights in the estimator.
 
* **Ties broken by a seeded shuffle.**  Thousands of domains share the floor
  prevalence 0.000007, so a quartile boundary lands inside a tie block.  Sorting
  by prevalence alone would cut it alphabetically, which is not random.
 
    python3 owner_sample.py --cache ./cache --out sample.json
"""
 
import argparse
import hashlib
import json
import os
import random
import sys
 
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
import owner_dbs as od
 
SEED = 20260905
PER_LIST = 60
ALLOC = (24, 12, 12, 12)          # per prevalence quartile, head first
 
 
def build_frame(cache):
    data = {}
    hashes = {}
    for name in od.SOURCES:
        obj, digest, nbytes = od.fetch(name, cache)
        data[name] = obj
        hashes[name] = (digest, nbytes)
    icann, private, exceptions, psl_hash = od.fetch_psl(cache)
    hashes["public_suffix_list"] = (psl_hash, len(icann) + len(private))
 
    wx = data["webxray"]
    wx_by_id = {e["id"]: e for e in wx}
 
    def root_of(e):
        seen = set()
        while e["parent_id"] is not None and e["id"] not in seen:
            seen.add(e["id"])
            e = wx_by_id[e["parent_id"]]
        return e
 
    wx_owner, wx_root = {}, {}
    for e in wx:
        for d in e["domains"]:
            wx_owner[d.lower()] = e["name"]
            wx_root[d.lower()] = root_of(e)["name"]
    tr_owner = {d.lower(): v["entityName"] for d, v in data["tr_domain_map"].items()}
    dc = data["disconnect_entities"]["entities"]
    dc_owner = {}
    for name, v in dc.items():
        for d in v.get("resources", []):
            dc_owner[d.lower()] = name
    for name, v in dc.items():
        for d in v.get("properties", []):
            dc_owner[d.lower()] = name
 
    prev = {}
    for host, v in data["tr_domain_summary"].items():
        host = host.lower()
        if "." not in host:
            continue
        reg = od.registrable(host, icann, exceptions)
        if reg is None:
            continue
        prev[reg] = max(prev.get(reg, 0.0), v["prevalence"])
 
    maps = {"webXray": wx_owner, "Tracker Radar": tr_owner, "Disconnect": dc_owner}
    owner = {lab: {d: od.lookup(d, m)[0] for d in prev} for lab, m in maps.items()}
    owner["webXray-root"] = {d: od.lookup(d, wx_root)[0] for d in prev}
    # Tracker Radar's per-domain category, for context on the adjudication sheet.
    tr_cat = {}
    for d, v in data["tr_domain_map"].items():
        tr_cat[d.lower()] = v.get("categories") or []
    return prev, owner, tr_cat, hashes
 
 
def strata(domains, prev, k=4):
    """Split `domains` into k equal-count strata by prevalence, ties shuffled."""
    rng = random.Random(SEED)
    shuffled = list(domains)
    rng.shuffle(shuffled)                       # breaks prevalence ties at random
    ranked = sorted(shuffled, key=lambda d: -prev[d])
    n = len(ranked)
    out = []
    for h in range(k):
        out.append(ranked[h * n // k:(h + 1) * n // k])
    return out
 
 
def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--cache", default="./cache")
    ap.add_argument("--out", default="owner_sample.json")
    args = ap.parse_args()
 
    prev, owner, tr_cat, hashes = build_frame(args.cache)
    print(f"Frame: {len(prev):,} registrable domains (ICANN fold, parent-label lookup).")
    for k, (h, n) in hashes.items():
        print(f"  {k:22s} sha256:{h}  {n:,}")
    print(f"Seed {SEED}; {PER_LIST} draws per list, allocation {ALLOC} over prevalence quartiles.")
    print()
 
    sample = {}
    for lab in ("webXray", "Tracker Radar", "Disconnect"):
        cov = sorted(d for d in prev if owner[lab][d] is not None)
        st = strata(cov, prev)
        rng = random.Random(SEED + sum(ord(c) for c in lab))
        rows = []
        print(f"{lab}: covers {len(cov):,} of {len(prev):,} frame domains "
              f"({100*len(cov)/len(prev):.1f}%), prevalence mass "
              f"{100*sum(prev[d] for d in cov)/sum(prev.values()):.1f}%")
        for h, (seg, n_h) in enumerate(zip(st, ALLOC)):
            drawn = rng.sample(seg, n_h)
            mass = sum(prev[d] for d in seg)
            print(f"  Q{h+1}: N={len(seg):5,}  prevalence {prev[seg[-1]]:.6f}..{prev[seg[0]]:.6f}"
                  f"  mass {100*mass/sum(prev[d] for d in cov):5.1f}%  n={n_h}")
            for d in drawn:
                rows.append({"domain": d, "stratum": h + 1, "prevalence": prev[d]})
        sample[lab] = {
            "N_total": len(cov),
            "strata_N": [len(s) for s in st],
            "strata_mass": [sum(prev[d] for d in s) for s in st],
            "alloc": list(ALLOC),
            "rows": rows,
        }
    print()
 
    union = sorted({r["domain"] for L in sample.values() for r in L["rows"]})
    print(f"Distinct domains to adjudicate: {len(union)} "
          f"(sum of per-list draws = {3*PER_LIST}; overlap {3*PER_LIST-len(union)})")
    out = {
        "seed": SEED, "per_list": PER_LIST, "alloc": list(ALLOC),
        "frame_size": len(prev),
        "frame_mass": sum(prev.values()),
        "hashes": {k: v[0] for k, v in hashes.items()},
        "lists": sample,
        "union": [{"domain": d,
                   "prevalence": prev[d],
                   "webXray": owner["webXray"][d],
                   "webXray_root": owner["webXray-root"][d],
                   "Tracker Radar": owner["Tracker Radar"][d],
                   "Disconnect": owner["Disconnect"][d],
                   "tr_categories": tr_cat.get(d, []),
                   "in_sample_of": [lab for lab in sample
                                    if any(r["domain"] == d for r in sample[lab]["rows"])]}
                  for d in union],
    }
    with open(args.out, "w") as f:
        json.dump(out, f, indent=1, sort_keys=True)
    print(f"Wrote {args.out}")
    digest = hashlib.sha256(open(args.out, "rb").read()).hexdigest()[:16]
    print(f"sample sha256:{digest}")
    return 0
 
 
if __name__ == "__main__":
    sys.exit(main())

B. scripts/owner_probe.sh — mechanical evidence for one domain

Run for every drawn domain to locate a lead: the TLS subject, the RDAP registrant, and the final URL with its title and copyright line. None of its output is a verdict and none of it is cited on the content page; an OV/EV certificate subject is the one signal here that clears the sourcing bar on its own, and those rows cite tls://<domain>:443.

owner_probe.sh
#!/bin/bash
# Mechanical primary-source evidence for one registrable domain.
#
# Three signals, in decreasing strength as an ownership claim:
#   TLS   Subject O= of the leaf certificate served on :443. On an OV/EV
#         certificate this is an identity a CA validated against a company
#         register, which is a primary source. On a DV certificate the Subject
#         carries only CN, and the field is absent -- that is why the script
#         prints the issuer too, so a reader can tell a validated O= from none.
#   RDAP  registrant organisation from the registry/registrar. Frequently a
#         privacy proxy; printed verbatim so the proxy is visible rather than
#         silently taken as an owner.
#   HTTP  final URL after redirects, plus <title> and any copyright line. A
#         domain that redirects to a corporate site is a self-assertion by the
#         operator, i.e. the domain's own document.
# None of these is accepted alone as the verdict; they locate the lead.
d="$1"
echo "=== $d"
tls=$(timeout 20 openssl s_client -connect "$d:443" -servername "$d" </dev/null 2>/dev/null \
      | openssl x509 -noout -subject -issuer -dates 2>/dev/null)
echo "TLS: ${tls:-<no handshake>}" | tr '\n' '|' ; echo
# RDAP via the IANA bootstrap resolver
rd=$(timeout 25 curl -sL --max-time 25 "https://rdap.org/domain/$d" 2>/dev/null)
if [ -n "$rd" ]; then
  echo "RDAP: $(echo "$rd" | jq -r '[.entities[]? | select(.roles? and (.roles|index("registrant"))) | (.vcardArray[1][]? | select(.[0]=="fn" or .[0]=="org") | .[3])] | unique | join(" / ")' 2>/dev/null)"
  echo "RDAP-registrar: $(echo "$rd" | jq -r '[.entities[]? | select(.roles? and (.roles|index("registrar"))) | (.vcardArray[1][]? | select(.[0]=="fn") | .[3])] | join(" / ")' 2>/dev/null)"
else
  echo "RDAP: <none>"
fi
h=$(timeout 25 curl -sL --max-time 25 -A 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0 Safari/537.36' \
     -w '\nFINAL:%{url_effective} CODE:%{http_code}\n' "https://$d/" 2>/dev/null)
echo "$h" | grep -o 'FINAL:[^ ]* CODE:[0-9]*' | tail -1
echo "TITLE: $(echo "$h" | tr -d '\n' | grep -oiE '<title[^>]*>[^<]{0,200}' | head -1 | sed 's/<[^>]*>//g')"
echo "COPYRIGHT: $(echo "$h" | sed 's/<[^>]*>/ /g' | grep -oiE '(©|copyright|&copy;)[^.<|]{0,90}' | head -3 | tr '\n' '|')"

C. adjudication brief, as given to the sub-agents

Twenty-one batches of 8–9 domains were adjudicated against this brief. It is published verbatim because the verdict vocabulary and the sourcing bar are the study's instrument, and because one of its six verdicts (self-named) turned out to be wrong and was retired mid-run — which is only checkable if the brief that produced it is on the record.

# Adjudicating domain ownership against primary sources

Today is 2026-09-05. You are settling, for each domain below, **which company owns
or operates it today**, and then scoring what each of three published ownership
databases says about it.

## The sourcing bar — this is the whole point of the exercise

A verdict is only allowed if you have an URL you actually fetched, from one of:

  * the company's own newsroom / press release / investor-relations page,
  * an SEC (or other regulator's) filing, e.g. sec.gov EDGAR, a national company
    register, or a listed company's annual/interim report,
  * **the domain's own legal document**: its privacy policy, terms, imprint /
    Impressum, data-processing agreement, cookie policy, or the copyright line
    and legal-entity name on the site the domain serves or redirects to,
  * the acquiring/parent company's own site naming the brand as theirs.

**Never** Wikipedia, Crunchbase, ZoomInfo, PitchBook, Owler, Tracxn, LinkedIn,
"list of acquisitions" pages, SEO listicles, or AI summaries. You may use them to
*locate a lead*, but the URL you record must be one of the primary kinds above.
If you cannot get to a primary source, say so — `unresolved` is a correct and
valuable answer here and is expected for a good fraction of these domains.

Do not trust your own memory for a corporate event: fetch and quote. If a
WebFetch returns a summary rather than text, fetch again or treat it as not
verified — a paraphrase is not a quote.

## Verdict vocabulary, one per list per domain

  * `current`     — the list names the company that owns/operates the domain
                    today. A legal name vs. its trading brand for the *same*
                    company both count as current ("Stripe" / "Stripe, Inc").
  * `stale`       — the list names a real *former* owner, or a former name of the
                    company: ownership or the name has since changed.
  * `granularity` — the list is correct but at a different level of the corporate
                    tree (it names the ultimate parent where a live subsidiary
                    or brand operates the domain, or vice versa). Not an error.
  * `error`       — the list names an entity that was never the owner at any time.
  * `absent`      — the list has no entry for this domain.
  * `self-named`  — the list's "owner" is just the domain itself or its bare label
                    (e.g. entity name "cdnbasket.net" for cdnbasket.net). This is
                    not an ownership claim at all. Use it whenever the entity name
                    is the domain, its label, or a trivial capitalisation of it,
                    EVEN IF a real company of that name exists — but say so in the
                    note when it does.

Prefer `current` over `granularity` when the named entity is a live, correct name
for the business behind the domain. Use `granularity` only when the reader would
actually be misled about *which* company (parent vs operating subsidiary).

## What to return

Return **only** a JSON array, one object per domain, nothing else — no prose
before or after. Schema:

```json
[{
  "domain": "example.com",
  "owner_today": "Legal Name Inc. (Brand)",   // or null if unresolved
  "when_changed": "closed 2022-06-06" | "n/a -- independent" | "UNRESOLVED -- <why>",
  "source": "https://...",                    // the primary-source URL you FETCHED
  "source_kind": "newsroom|filing|legal-doc|register|parent-site",
  "quote": "<= 200 chars copied verbatim from that URL that carries the claim",
  "webXray": "current|stale|granularity|error|absent|self-named",
  "tracker_radar": "...",
  "disconnect": "...",
  "resolution": "resolved" | "unresolved",
  "note": "one sentence: anything a reader checking this row needs"
}]
```

Rules for the JSON:
  * `source` must be a URL **you fetched in this session** and `quote` must appear
    verbatim on it. If you could not fetch it, set `resolution":"unresolved"`.
  * If `resolution` is `unresolved`, still fill the per-list verdicts you are
    confident of ONLY when the verdict is `absent` or `self-named` (both are
    facts about the list, not about the world); otherwise use `"unknown"`.
  * A dead domain that resolves to nothing is still adjudicable if its operator
    is identifiable from a primary source; if not, `unresolved`.
  * Be sceptical of the mechanical probe: a Let's Encrypt certificate carries no
    validated organisation, a registrar name is not an owner, and a parked page
    is not a legal document. An OV/EV certificate's `O =` field IS a validated
    identity and counts as a register-grade source (`source_kind":"register"`) —
    record the exact subject line as the quote and the domain as the source URL
    in the form `tls://<domain>:443`.

Work domain by domain. Budget your effort: obvious cases (gstatic.com is Google)
need one confirming fetch, not five. Spend the time on the ones that are unclear.

D. scripts/owner_merge_rows.py — the gate between adjudication and estimate

Fails loudly on anything the estimator would otherwise swallow: a missing domain, a duplicate, a verdict outside the vocabulary, a resolved row with no source or no quote. It also re-derives every absent verdict from the list files rather than trusting the adjudicator's reading of them.

owner_merge_rows.py
#!/usr/bin/env python3
"""Merge the per-batch adjudication files into one row set, and fail loudly on
anything the estimator would silently swallow: a missing domain, a duplicate, a
verdict outside the vocabulary, a `resolved` row with no source or no quote.
 
    python3 owner_merge_rows.py --sample owner_sample.json --dir adj --out adj_rows.json
"""
import argparse, glob, json, os, sys
 
VERDICTS = {"current", "stale", "granularity", "error", "self-named", "absent", "unresolved", "unknown"}
FIELDS = ("domain", "owner_today", "when_changed", "source", "quote",
          "webXray", "tracker_radar", "disconnect", "resolution", "note")
 
 
def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--sample", required=True)
    ap.add_argument("--dir", required=True)
    ap.add_argument("--out", required=True)
    args = ap.parse_args()
 
    S = json.load(open(args.sample))
    want = {r["domain"] for r in S["union"]}
    claims = {r["domain"]: r for r in S["union"]}
 
    rows, seen, problems = [], {}, []
    for f in sorted(glob.glob(os.path.join(args.dir, "result*.json"))):
        for r in json.load(open(f)):
            d = r["domain"]
            if d in seen:
                problems.append(f"duplicate row for {d} ({seen[d]} and {f})")
                continue
            seen[d] = os.path.basename(f)
            for k in FIELDS:
                if k not in r:
                    problems.append(f"{d}: missing field {k} (from {f})")
                    r.setdefault(k, None)
            for k in ("webXray", "tracker_radar", "disconnect"):
                if r[k] not in VERDICTS:
                    problems.append(f"{d}: verdict {k}={r[k]!r} outside the vocabulary")
            if r["resolution"] == "resolved" and not (r.get("source") and r.get("quote")):
                problems.append(f"{d}: resolution=resolved but source/quote empty")
            r["_batch"] = os.path.basename(f)
            rows.append(r)
 
    # The list claims are in the sample file, not the agent's output: an `absent`
    # verdict is a fact about the file, so it is CHECKED rather than trusted.
    LK = {"webXray": "webXray", "tracker_radar": "Tracker Radar", "disconnect": "Disconnect"}
    fixed = 0
    for r in rows:
        c = claims.get(r["domain"])
        if not c:
            continue
        for k, lab in LK.items():
            has = c[lab] is not None
            if r[k] == "absent" and has:
                problems.append(f"{r['domain']}: {lab} scored absent but the file says {c[lab]!r}")
            if r[k] != "absent" and not has:
                problems.append(f"{r['domain']}: {lab} scored {r[k]!r} but the file has no entry -> forced to absent")
                r[k] = "absent"
                fixed += 1
 
    missing = sorted(want - set(seen))
    extra = sorted(set(seen) - want)
    print(f"batches merged: {len(set(r['_batch'] for r in rows))}, rows: {len(rows)}")
    print(f"sampled domains: {len(want)}; missing rows: {len(missing)}; rows for unsampled domains: {len(extra)}")
    if missing:
        print("  MISSING: " + ", ".join(missing))
    if extra:
        print("  EXTRA:   " + ", ".join(extra))
    print(f"absent-verdicts corrected against the list files: {fixed}")
    if problems:
        print(f"\nPROBLEMS ({len(problems)}):")
        for p in problems:
            print("  " + p)
    json.dump(rows, open(args.out, "w"), indent=1)
    print(f"\nwrote {args.out}")
 
    # Exit non-zero on anything the estimator would otherwise swallow. A
    # `forced to absent` line is not one of those: the script has already
    # corrected it against the list file, which is what it is for, and `fixed`
    # counts them. Everything else is a defect in the merged rows.
    #
    # This used to be `return 1 if missing else 0`, so a duplicate row, an
    # out-of-vocabulary verdict or a resolved row with no source printed a
    # PROBLEM and exited 0 -- while the docstring said it failed loudly on all
    # four. Found by a reviewer who built a synthetic batch with a duplicate and
    # a bogus verdict and watched it exit 0. It did not affect this run (the
    # committed merge has zero problems), but a caller trusting the exit code,
    # as the docstring invites, would have accepted a corrupt merge.
    fatal = [p for p in problems if "-> forced to absent" not in p]
    if fatal or missing or extra:
        print(f"\nFAILED: {len(missing)} missing, {len(extra)} unsampled, "
              f"{len(fatal)} other problem(s)")
        return 1
    return 0
 
 
if __name__ == "__main__":
    sys.exit(main())

E. scripts/owner_verify_sources.py — re-fetch every cited source

Re-fetches each cited URL (or redoes the TLS handshake, for a tls:// source) and looks for the quoted sentence in what comes back. It does not check whether a verdict is right; it checks that the evidence exists and says what the row claims.

owner_verify_sources.py
#!/usr/bin/env python3
"""Re-fetch every primary source cited by the ownership adjudication and check
that the quoted sentence is actually on it.
 
Written because the adjudication was carried out by sub-agents, and the single
failure mode that would invalidate the whole study is a plausible-looking URL
that does not say what the row claims.  This script does not check whether the
verdict is *right*; it checks that the evidence exists and contains the quote.
 
    python3 owner_verify_sources.py --rows adj_rows.json --out verify.json
 
Matching is deliberately lenient about whitespace, quote characters and
hyphenation, and strict about everything else.  Three outcomes:
  OK        the quote (or, for a long quote, a 60-character window of it)
            appears in the fetched bytes after normalisation
  NOTFOUND  the URL fetched but the quote is not on it   <- disqualifying
  FETCHFAIL the URL could not be fetched from this host  <- needs a human look,
            because a paywall or a geo-block is not the same as a bad citation
"""
 
import argparse, hashlib, json, os, re, ssl, subprocess, sys, urllib.request
 
UA = ("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) "
      "Chrome/141.0.0.0 Safari/537.36")
 
 
def norm(s):
    s = s.lower()
    # Modern sites ship their page text inside an escaped JSON payload, so the
    # sentence a reader sees is "\u0026amp;" in the bytes. Decoding first is the
    # difference between verifying the Wayback copy of dnb.com and calling it a
    # fabrication.
    s = re.sub(r"\\u([0-9a-f]{4})", lambda m: chr(int(m.group(1), 16)), s)
    s = s.replace("’", "'").replace("‘", "'")
    s = s.replace("“", '"').replace("”", '"')
    s = s.replace("–", "-").replace("—", "-").replace("‑", "-")
    s = s.replace("&amp;", "&").replace("&nbsp;", " ").replace("&#39;", "'")
    s = s.replace("&quot;", '"').replace("&rsquo;", "'").replace("&ldquo;", '"').replace("&rdquo;", '"')
    s = re.sub(r"<[^>]{0,400}>", " ", s)
    # Every remaining entity becomes a space on BOTH sides, or "&copy;" in the
    # page and "(c)" in the quote normalise to different tokens and a correct
    # citation is reported as a fabrication. Caught on medallia.com.au.
    s = re.sub(r"&(?:#\d{1,6}|#x[0-9a-fA-F]{1,6}|[a-zA-Z]{2,10});", " ", s)
    s = re.sub(r"[^a-z0-9]+", " ", s)
    return re.sub(r"\s+", " ", s).strip()
 
 
def fetch(url, cache):
    key = hashlib.sha256(url.encode()).hexdigest()[:24]
    path = os.path.join(cache, key + ".bin")
    if os.path.exists(path):
        return open(path, "rb").read(), None
    if url.startswith("tls://"):
        host = url[len("tls://"):].split(":")[0]
        try:
            out = subprocess.run(
                ["openssl", "s_client", "-connect", f"{host}:443", "-servername", host],
                input=b"", capture_output=True, timeout=30).stdout
            # -nameopt utf8: without it a Chinese or Cyrillic O= prints as
            # \XX escapes and the quote can never match. Caught on bilibili.com.
            out = subprocess.run(["openssl", "x509", "-noout", "-subject", "-issuer",
                                  "-nameopt", "utf8"],
                                 input=out, capture_output=True, timeout=30).stdout
        except Exception as e:
            return None, f"tls: {e}"
        os.makedirs(cache, exist_ok=True)
        open(path, "wb").write(out)
        return out, None
    # curl rather than urllib: several of these hosts 403 anything that does not
    # look like a browser, and a 403 is not the same finding as a bad citation.
    try:
        proc = subprocess.run(
            ["curl", "-sL", "--compressed", "--max-time", "60", "-A", UA,
             "-H", "Accept: text/html,application/xhtml+xml,application/pdf,*/*",
             "-H", "Accept-Language: en-US,en;q=0.9",
             "-w", "\n__CURL_CODE:%{http_code}", url],
            capture_output=True, timeout=90)
        body = proc.stdout
    except Exception as e:
        return None, f"{type(e).__name__}: {e}"
    m = re.search(rb"__CURL_CODE:(\d+)\s*$", body)
    code = m.group(1).decode() if m else "?"
    body = body[:m.start()] if m else body
    if code not in ("200", "?") and len(body) < 3000:
        return None, f"HTTP {code} ({len(body)} bytes)"
    if body[:5] == b"%PDF-":
        import io
        import pypdf
        text = []
        for page in pypdf.PdfReader(io.BytesIO(body)).pages:
            text.append(page.extract_text())
        body = "\n".join(text).encode("utf8")
    os.makedirs(cache, exist_ok=True)
    open(path, "wb").write(body)
    return body, None
 
 
def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--rows", required=True)
    ap.add_argument("--cache", default="./verify_cache")
    ap.add_argument("--out", default="verify.json")
    args = ap.parse_args()
    rows = json.load(open(args.rows))
 
    results = []
    for r in rows:
        url, quote = r.get("source"), r.get("quote") or ""
        if not url or r.get("resolution") != "resolved":
            results.append({"domain": r["domain"], "status": "NOSOURCE", "url": url})
            continue
        body, err = fetch(url, args.cache)
        if body is None:
            results.append({"domain": r["domain"], "status": "FETCHFAIL",
                            "url": url, "error": err})
            continue
        hay = norm(body.decode("utf8", "replace"))
        nq = norm(quote)
        # A quote the adjudicator elided ("A ... B") is checked fragment by
        # fragment: requiring the literal string would fail every such row and
        # call an honest citation a fabrication.
        frags = [norm(f) for f in re.split(r"\.\.\.|\u2026|\s--\s", quote)]
        frags = [f for f in frags if len(f) >= 12]
        if not nq:
            status = "NOQUOTE"
        elif nq in hay:
            status = "OK"
        elif len(frags) > 1 and all(f in hay for f in frags):
            status = "OK-FRAGMENTS"
        else:
            # long quotes get spliced by boilerplate; try the longest window that fits
            win = next((nq[i:i + 60] for i in range(0, max(1, len(nq) - 59), 10)
                        if nq[i:i + 60] in hay), None)
            status = "OK-WINDOW" if win else "NOTFOUND"
        results.append({"domain": r["domain"], "status": status, "url": url,
                        "quote": quote[:120], "bytes": len(body)})
        print(f"{status:10} {r['domain']:28} {url[:88]}")
 
    tally = {}
    for x in results:
        tally[x["status"]] = tally.get(x["status"], 0) + 1
    print()
    print("Verification of cited primary sources: " +
          ", ".join(f"{k}={v}" for k, v in sorted(tally.items())))
    json.dump(results, open(args.out, "w"), indent=1)
    return 0
 
 
if __name__ == "__main__":
    sys.exit(main())

F. scripts/owner_verify_rendered.mjs — the same check in a browser

A legal-entity name in a footer or an Impressum is frequently client-rendered, so a NOTFOUND from raw bytes is evidence about the instrument, not about the citation. This pass rescued 5 rows that a bytes-only audit would have called broken.

owner_verify_rendered.mjs
// Second-chance verification of the ownership adjudication's primary sources,
// with a real browser.
//
// `owner_verify_sources.py` fetches bytes. A legal-entity name in a footer or an
// Impressum is frequently client-rendered, so a NOTFOUND from raw HTML is not
// evidence that the citation is bad -- it is evidence that curl is the wrong
// instrument. Anything still NOTFOUND after this pass is treated as a failed
// citation and its row is demoted to `unresolved` rather than published.
//
//   node owner_verify_rendered.mjs out/verify.json out/adj_rows.json out/verify_rendered.json
import { chromium } from 'playwright';
import fs from 'fs';
 
const norm = s => s.toLowerCase()
  .replace(/[’‘]/g, "'").replace(/[“”]/g, '"')
  .replace(/[–—‑]/g, '-')
  .replace(/<[^>]{0,400}>/g, ' ')
  .replace(/[^a-z0-9À-￿]+/g, ' ').replace(/\s+/g, ' ').trim();
 
const [verifyPath, rowsPath, outPath] = process.argv.slice(2);
const verify = JSON.parse(fs.readFileSync(verifyPath, 'utf8'));
const rows = Object.fromEntries(JSON.parse(fs.readFileSync(rowsPath, 'utf8')).map(r => [r.domain, r]));
const todo = verify.filter(v => v.status === 'NOTFOUND' || v.status === 'FETCHFAIL');
console.log('re-checking ' + todo.length + ' rows in a browser');
 
const browser = await chromium.launch();
const ctx = await browser.newContext({
  userAgent: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36',
  locale: 'en-US',
});
const out = [];
for (const v of todo) {
  const r = rows[v.domain];
  const url = r.source;
  let status = 'RENDER-FAIL', text = '', err = '';
  if (url.startsWith('tls://')) { out.push({ ...v, rendered: 'SKIP-TLS' }); continue; }
  const page = await ctx.newPage();
  try {
    await page.goto(url, { waitUntil: 'networkidle', timeout: 60000 });
    await page.waitForTimeout(2500);
    text = await page.evaluate(() => document.body.innerText);
    const hay = norm(text);
    const nq = norm(r.quote || '');
    const frags = (r.quote || '').split(/\.\.\.|…|\s--\s/).map(norm).filter(f => f.length >= 12);
    if (nq && hay.includes(nq)) status = 'OK';
    else if (frags.length > 1 && frags.every(f => hay.includes(f))) status = 'OK-FRAGMENTS';
    else {
      let win = null;
      for (let i = 0; i + 60 <= nq.length; i += 10) if (hay.includes(nq.slice(i, i + 60))) { win = 1; break; }
      status = win ? 'OK-WINDOW' : 'NOTFOUND';
    }
  } catch (e) { err = String(e).slice(0, 120); }
  await page.close();
  console.log(status.padEnd(13) + ' ' + v.domain.padEnd(24) + ' ' + err);
  out.push({ ...v, rendered: status, rendered_error: err, rendered_chars: text.length });
}
await browser.close();
fs.writeFileSync(outPath, JSON.stringify(out, null, 1));
const t = {}; for (const o of out) t[o.rendered] = (t[o.rendered] || 0) + 1;
console.log('\nrendered re-check: ' + Object.entries(t).map(([k, v]) => k + '=' + v).join(', '));

G. scripts/owner_corrections.py — the ten citations fixed by hand

Every row a machine flagged and a human then re-checked, with the action taken and why: requote (the claim held, the quote was a paraphrase), resource (wrong page for a right claim), demote (no primary source on a second look; the row leaves every rate).

owner_corrections.py
#!/usr/bin/env python3
"""Corrections applied by hand to the ownership adjudication after
``owner_verify_sources.py`` and ``owner_verify_rendered.mjs`` failed to find the
quoted sentence on the cited page.
 
Every row here is one a machine flagged and a human then re-checked. Two things
happen and both are recorded rather than silently applied:
 
  * ``requote`` -- the claim held, but the "quote" was a paraphrase or a
    re-ordering of the page's own words. The source stays; the quote is replaced
    with text copied out of the fetched page. This is the "a paraphrase inside
    quotation marks" failure, and it happened in 4 of 175 rows despite an
    instruction that said verbatim -- which is the argument for verifying every
    citation by machine rather than trusting the adjudicator.
  * ``resource`` -- the cited URL was the wrong page (a 404 template, a
    JS-only route, a blocked host). A different primary source for the same
    claim replaces it.
  * ``demote``   -- no primary source could be found on a second look. The row
    becomes ``unresolved`` and drops out of every rate, which is the only
    honest outcome and is exactly what the sampling design expects to happen
    more often in the tail.
 
    python3 owner_corrections.py --rows adj_rows.json --out adj_rows_final.json
"""
import argparse, json, sys
 
# domain -> (action, new_source, new_quote, note)
CORRECTIONS = {
    "twiago.com": ("requote",
        "https://www.twiago.com/impressum",
        "twiago GmbH Charlottenstraße 61 51149 Köln",
        "quote was re-ordered ('HRB 81984 (Amtsgericht Köln)'); the page reads "
        "'Handelsregisternummer : Amtsgericht Köln HRB 81984'. Claim unchanged."),
    "glomex.com": ("requote",
        "https://www.glomex.com/de/impressum",
        "glomex GmbH Medienallee 4 85774 Unterföhring Deutschland",
        "quote had punctuation and a '--' the page does not carry; entity, address "
        "and HRB 224542 are all on the page."),
    "wrbm.com": ("requote",
        "https://find-and-update.company-information.service.gov.uk/company/02883992",
        "WILLIAM REED LTD ... Previous company names ... WILLIAM REED BUSINESS MEDIA LTD",
        "quote was a summary of the register page; the three strings are on it."),
    "klarna.app": ("resource",
        "https://www.klarna.com/international/",
        "Copyright © 2005-2026 Klarna Bank AB (publ). Headquarters: Stockholm, Sweden.",
        "https://klarna.com/ geo-redirects and does not carry the footer; the "
        "international landing page does, verbatim."),
    "hearst.com": ("resource",
        "https://www.hearst.com/",
        "© 2026 Hearst Communications, Inc. All Rights Reserved.",
        "the cited SEC browse-edgar URL is a form, not a document. hearst.com's own "
        "footer names the entity. (data.sec.gov/submissions/CIK0001052747.json also "
        "returns name 'HEARST COMMUNICATIONS INC', checked 2026-09-05.)"),
    "medallia.com.au": ("resource",
        "https://medallia.com.au/",
        "Copyright © 2026 Medallia, Inc",
        "medallia.com.au redirects to www.medallia.com, whose footer carries the "
        "entity; citing the sampled domain makes the redirect part of the evidence."),
    "akamaihd.net": ("resource",
        "https://publicsuffix.org/list/public_suffix_list.dat",
        "// Akamai : https://www.akamai.com/ // Submitted by Akamai Team "
        "<publicsuffixlist@akamai.com> akadns.net akamai.net akamai-staging.net "
        "akamaiedge.net akamaiedge-staging.net akamaihd.net",
        "akamaihd.net serves nothing and the Akamai blog 403s every non-browser "
        "client. Akamai's own PSL submission is a primary source that the suffix "
        "is theirs, and it is a file this study already fetches and hashes."),
    "mediaset.es": ("requote",
        "tls://mediaset.es:443",
        'O=GRUPO AUDIOVISUAL MEDIASET ESPAÑA COMUNICACION, SAU, CN=seguro.mediaset.es',
        "the quote was openssl's default escaped form (ESPA\\C3\\91A). Re-quoted from "
        "`-nameopt utf8`, which the verifier now passes; the OV certificate is unchanged."),
    "dnb.com": ("resource",
        "https://web.archive.org/web/20241002130956/https://www.dnb.com/utility-pages/privacy-policy.html",
        "At Dun & Bradstreet (D&B), compliance and ethics begins with human-centered values",
        "dnb.com served the page to a plain curl earlier in the run and then began "
        "returning a ~5.7 kB challenge to every client, browser included. Citing the "
        "Wayback copy keeps the row reproducible; the live page carried the same "
        "sentence when first fetched on 2026-09-05."),
    "cnevids.com": ("demote", None, None,
        "Condé Nast's own privacy policy does not name cnevids.com and the domain "
        "serves nothing. Tracker Radar's 'Sabin, Bermant & Gould LLP' is the "
        "registrant law firm, which is a textbook WHOIS trap, but calling it an "
        "error needs a source naming the real owner and there is none."),
}
 
 
def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--rows", required=True)
    ap.add_argument("--out", required=True)
    args = ap.parse_args()
    rows = json.load(open(args.rows))
    by = {r["domain"]: r for r in rows}
 
    missing = sorted(set(CORRECTIONS) - set(by))
    if missing:
        raise SystemExit(f"FATAL: corrections for domains not in the row set: {missing}")
 
    from collections import Counter
    kinds = Counter(v[0] for v in CORRECTIONS.values())
    print(f"{len(CORRECTIONS)} corrections applied to {len(rows)} rows, after machine "
          f"verification of every cited source: "
          + ", ".join(f"{k}={n}" for k, n in sorted(kinds.items())))
    print()
    for d, (action, src, quote, note) in CORRECTIONS.items():
        r = by[d]
        print(f"{d:22} {action:9} {note}")
        print(f"{'':22} was source: {r['source']}")
        print(f"{'':22} was quote : {(r['quote'] or '')[:140]}")
        r.setdefault("corrections", []).append(
            {"action": action, "old_source": r["source"], "old_quote": r["quote"],
             "note": note})
        if action == "demote":
            r["resolution"] = "unresolved"
            r["when_changed"] = "UNRESOLVED -- no primary source names the owner"
            r["owner_today"] = None
            r["source"] = None
            r["quote"] = None
            for k in ("webXray", "tracker_radar", "disconnect"):
                if r[k] not in ("absent", "self-named"):
                    r[k] = "unknown"
        else:
            r["source"] = src
            r["quote"] = quote
        print(f"{'':22} now source: {r['source']}")
        print()
    json.dump(rows, open(args.out, "w"), indent=1)
    print(f"wrote {args.out}")
    return 0
 
 
if __name__ == "__main__":
    sys.exit(main())

H. scripts/owner_verdict_fixes.py — retiring the ''self-named'' verdict

The methodological correction made during the run, kept rather than smoothed away. Each of the 26 re-scores carries the entity string, the adjudicated owner and the reason.

owner_verdict_fixes.py
#!/usr/bin/env python3
"""Retire the `self-named` verdict and re-score the rows that carried it.
 
This is a methodological correction made during the run, kept in the audit trail
rather than smoothed away.
 
The adjudication brief offered six verdicts, one of them `self-named`, defined as
"the list's owner is just the domain itself or its bare label ... EVEN IF a real
company of that name exists".  That definition is wrong, and the sample shows
exactly how: it caught "TrustArc" for trustarc.com, "Klaviyo" for klaviyo.com and
"Bilibili" for bilibili.com -- names that are the company -- alongside
"cdnbasket.net" for cdnbasket.net, which is not.  It was applied to 26 of 525
(domain, list) verdicts, unevenly: 15 of Disconnect's 60 drawn rows and 4 of
webXray's, which would have moved Disconnect's accuracy denominator by a quarter
for a reason that is about naming style, not about ownership.
 
Two things replace it:
 
  * every row is re-scored on the ownership question alone, into
    current / stale / granularity / error;
  * "the entity name is a domain, not a company" is measured where it belongs --
    as a census over every entry in every file, in ``owner_selfname_census.py``.
    That needs no sample, and it returns 0.8% / 0.7% / 3.2% for webXray /
    Tracker Radar / Disconnect, against the 25% of Disconnect's *sample* the
    verdict was firing on.  The sampled verdict was measuring the adjudicator's
    reading of a name, not a property of the list.
 
Each re-score below carries the entity string, the adjudicated owner, and why.
 
    python3 owner_verdict_fixes.py --rows adj_rows_final.json --out adj_rows_scored.json
"""
import argparse, json, sys
 
# (domain, list-key) -> (new verdict, reason)
RESCORE = {
    ("simpli.fi", "webXray"): ("current",
        "'simpli.fi' is the trading brand of Simplifi Holdings, LLC; the string is "
        "a domain but it names the right company."),
    ("simpli.fi", "disconnect"): ("current", "as above, entity 'Simpli.fi'."),
    ("iqzone.com", "disconnect"): ("current", "'IQZone' vs IQzone Inc.: same company."),
    ("histats.com", "disconnect"): ("current",
        "'Histats' is the product of Wisecode S.r.l.; scored as webXray's 'HiStats' "
        "was on the same row, so the two lists are treated alike."),
    ("trustarc.com", "webXray"): ("current", "'TrustArc' is TrustArc Inc."),
    ("trustarc.com", "disconnect"): ("current", "'TrustARC' is TrustArc Inc."),
    ("spotxchange.com", "webXray"): ("stale",
        "'Spot X Change' is the pre-acquisition brand; Magnite acquired SpotX in "
        "2021 and the domain is Magnite Streaming's."),
    ("amung.us", "webXray"): ("current", "the company is literally 'whos.amung.us Inc.'"),
    ("amung.us", "tracker_radar"): ("current", "entity 'whos.amung.us Inc'."),
    ("amung.us", "disconnect"): ("current", "entity 'whos.amung.us'."),
    ("yieldlove-ad-serving.net", "disconnect"): ("current",
        "the entity string is the domain, but it names Yieldlove GmbH, the operator. "
        "Counted in the domain-as-name census instead of in the verdict."),
    ("glomex.com", "disconnect"): ("current", "'Glomex' is glomex GmbH."),
    ("onecount.net", "webXray"): ("granularity",
        "'ONEcount' is the product; the company is GCN Publishing, Inc."),
    ("accessibe.com", "disconnect"): ("current", "'Accessibe' is accessiBe Inc."),
    ("admarketplace.net", "disconnect"): ("current", "'Admarketplace' is adMarketplace, Inc."),
    ("amazon.de", "disconnect"): ("current", "'Amazon' names the group operating amazon.de."),
    ("bilibili.com", "disconnect"): ("granularity",
        "'Bilibili' is the listed parent; the operator is Shanghai Huandian "
        "Information Technology Co., Ltd. Scored as Tracker Radar's 'BiliBili Inc.' "
        "was on the same row."),
    # Rows whose owner could not be settled: the verdict cannot be anything but
    # unknown, and they are already excluded as unresolved.
    ("govx.com", "tracker_radar"): ("unknown", "row unresolved."),
    ("govx.com", "disconnect"): ("unknown", "row unresolved."),
    ("cdnbasket.net", "disconnect"): ("unknown", "row unresolved."),
    ("acint.net", "disconnect"): ("unknown", "row unresolved."),
    ("htplayground.com", "disconnect"): ("unknown", "row unresolved."),
    ("contentabc.com", "disconnect"): ("unknown", "row unresolved."),
    ("stat-track.com", "disconnect"): ("unknown", "row unresolved."),
    ("km0trk.com", "disconnect"): ("unknown", "row unresolved."),
    ("i.ua", "disconnect"): ("unknown", "row unresolved."),
}
 
# A second correction, from reading the verdicts rather than the vocabulary.
#
# webXray is the only list with a parent tree, so the adjudication brief showed
# both its immediate entity name and the root of the ownership chain. Two rows
# were then scored on the ROOT, which is not the column being measured: every
# other figure on the page, and `owner_dbs.py`'s "webXray" column, use the
# immediate name. The rule is now stated: **webXray is scored on its immediate
# entity name**, and 29 of its 60 drawn rows have a root that differs, so this
# is not a detail. Both re-scores lower webXray's error rate, which is the
# opposite direction from the one this page's earlier draft leaned.
ROOT_RESCORE = {
    ("tqlkg.com", "webXray"): ("error", "stale",
        "scored error because webXray's ROOT is 'Here, There & Everywhere', an "
        "Australian media group unrelated to US Conversant -- a real defect, but "
        "in the tree, not in the entry. The immediate entity 'Conversant Media' is "
        "the company's own former name, superseded by Conversant, LLC: stale."),
    ("addthiscdn.com", "webXray"): ("error", "granularity",
        "scored error on a note that says webXray roots AddThis under Verizon. It "
        "does not: webXray's root for addthiscdn.com is 'Oracle', which is the "
        "correct owner. The immediate entity 'AddThis' names the brand Oracle "
        "acquired in 2016 and shut down in 2023: granularity, not an error."),
}
 
 
def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--rows", required=True)
    ap.add_argument("--out", required=True)
    args = ap.parse_args()
    rows = json.load(open(args.rows))
    by = {r["domain"]: r for r in rows}
 
    held = [(r["domain"], k) for r in rows for k in ("webXray", "tracker_radar", "disconnect")
            if r[k] == "self-named"]
    unlisted = sorted(set(held) - set(RESCORE))
    stale_keys = sorted(set(RESCORE) - set(held))
    if unlisted:
        raise SystemExit(f"FATAL: self-named rows with no re-score: {unlisted}")
    if stale_keys:
        raise SystemExit(f"FATAL: re-scores for rows that are not self-named: {stale_keys}")
 
    print(f"`self-named` retired: {len(held)} (domain, list) verdicts re-scored.")
    print()
    for (d, k), (v, why) in sorted(RESCORE.items()):
        r = by[d]
        r.setdefault("rescored", []).append({"list": k, "from": "self-named", "to": v, "why": why})
        r[k] = v
        print(f"  {d:26} {k:14} self-named -> {v:12} {why}")
    print()
    print("Second correction: rows scored on webXray's ownership-tree root rather "
          "than its entry.")
    for (d, k), (old, new, why) in sorted(ROOT_RESCORE.items()):
        r = by[d]
        if r[k] != old:
            raise SystemExit(f"FATAL: {d}/{k} is {r[k]!r}, expected {old!r}")
        r.setdefault("rescored", []).append({"list": k, "from": old, "to": new, "why": why})
        r[k] = new
        print(f"  {d:26} {k:14} {old:12} -> {new:12} {why}")
    print()
 
    left = [(r["domain"], k) for r in rows for k in ("webXray", "tracker_radar", "disconnect")
            if r[k] == "self-named"]
    print(f"self-named verdicts remaining: {len(left)}")
    json.dump(rows, open(args.out, "w"), indent=1)
    print(f"wrote {args.out}")
    return 0
 
 
if __name__ == "__main__":
    sys.exit(main())

I. scripts/owner_random_sample.py — the estimator

Stratified point estimates with population weights, and stratified percentile-bootstrap intervals over 10,000 resamples. Its docstring carries the design and the denominator rules; read those before reading the arithmetic.

owner_random_sample.py
#!/usr/bin/env python3
"""Per-list accuracy of the three domain-to-company ownership databases,
estimated from a **stratified random sample** of each list's own coverage.
 
    python3 owner_random_sample.py --sample owner_sample.json --rows adj_rows.json
    python3 owner_random_sample.py ... --table        # the full adjudication table
    python3 owner_random_sample.py ... --wiki         # DokuWiki tables
 
Why this exists
---------------
``owner_adjudication.py`` settled the 30 highest-prevalence *disagreements*
between webXray, Tracker Radar and Disconnect.  That set is drawn precisely
where the lists differ, so it characterises the shape of disagreement and
refuses to print an error rate.  This script is the missing measurement: a
probability sample, from which "of the domains this list names an owner for,
what share name today's owner" is estimable with an interval.
 
Design (drawn by ``owner_sample.py``, seed 20260905)
----------------------------------------------------
Frame        registrable domains in Tracker Radar's ``domain_summary.json``,
             ICANN-section PSL fold, parent-label lookup: 32,337 domains.
             Tracker Radar's view of the third-party surface, not a neutral one.
Population   per list L: the N_L frame domains L names an owner for.
Strata       prevalence quartiles of that population, equal count.
Allocation   24 / 12 / 12 / 12, heaviest at the head, corrected by weights.
Adjudication each drawn domain settled against a primary source (company
             newsroom, regulator filing, company register, or the domain's own
             legal document), never Wikipedia or Crunchbase.
 
Denominator rules, which do most of the work
--------------------------------------------
Two verdicts are **not answers about ownership** and are excluded from every
accuracy rate, then reported as rates in their own right:
 
``unresolved``  no primary source could be found.  In the head-selected sample
                this was 2 rows in 30; in a random sample it is much larger,
                because the tail of the third-party surface is domains with no
                newsroom, no filing and often no served page at all.  Counting
                these as anything would be the "sentinels are never answers"
                error.  Excluding them makes every rate below *conditional on
                the entry being adjudicable*, and the exclusion rate rises
                toward the tail, so the tail estimates are the ones to distrust.
 
A `self-named` verdict was tried and **retired mid-run**; see
``owner_verdict_fixes.py``.  "The entity name is a domain, not a company" is a
property of the file, countable over every entry without a sample, and it is
measured that way in ``owner_selfname_census.py`` (0.8% / 0.7% / 3.2% of pairs
for webXray / Tracker Radar / Disconnect).  As a sampled *verdict* it was firing
on names that are the company -- "TrustArc", "Klaviyo", "Bilibili" -- and would
have cut Disconnect's accuracy denominator by a quarter for a reason that has
nothing to do with ownership.
 
Estimator
---------
Stratified, with population weights.  For verdict v and list L::
 
    domain-level     R = sum_h (N_h / N) * p_h        p_h = x_h / m_h
    prevalence-wtd   R = sum_h (M_h / M) * r_h        r_h = sum(prev*y) / sum(prev)
 
over the *eligible* rows m_h in each stratum (a stratum with m_h = 0 is dropped
and the remaining weights renormalised, which is printed).  Intervals are
stratified bootstrap percentiles, 10,000 resamples, because several strata have
0 or 1 in a cell and a normal approximation is meaningless there.
"""
 
import argparse, json, random, sys
from collections import Counter
 
LISTS = ["webXray", "Tracker Radar", "Disconnect"]
KEY = {"webXray": "webXray", "Tracker Radar": "tracker_radar", "Disconnect": "disconnect"}
VERDICTS = ["current", "stale", "granularity", "error", "unresolved", "absent"]
INELIGIBLE = {"unresolved", "absent"}
NBOOT = 10000
SEED = 20260905
 
 
def strat_estimate(units, weights, pick):
    """units[h] = list of (prevalence, verdict); weights = (N_h, M_h) per stratum.
 
    Returns (domain_level, prevalence_weighted) for the indicator `pick`, or
    (None, None) if no stratum has an eligible row.
    """
    live = [h for h in range(len(units)) if units[h]]
    if not live:
        return None, None
    Nsum = sum(weights[h][0] for h in live)
    Msum = sum(weights[h][1] for h in live)
    dom = sum((weights[h][0] / Nsum) * (sum(1 for p, v in units[h] if pick(v)) / len(units[h]))
              for h in live)
    prv = 0.0
    for h in live:
        tot = sum(p for p, v in units[h])
        r = (sum(p for p, v in units[h] if pick(v)) / tot) if tot > 0 else 0.0
        prv += (weights[h][1] / Msum) * r
    return dom, prv
 
 
def bootstrap(units, weights, pick, rng):
    dom, prv = [], []
    for _ in range(NBOOT):
        res = [[u[rng.randrange(len(u))] for _ in u] if u else [] for u in units]
        d, p = strat_estimate(res, weights, pick)
        if d is not None:
            dom.append(d)
            prv.append(p)
    if not dom:
        return (None, None), (None, None)
    dom.sort(); prv.sort()
    lo, hi = int(0.025 * len(dom)), int(0.975 * len(dom)) - 1
    return (dom[lo], dom[hi]), (prv[lo], prv[hi])
 
 
def pct(x):
    return "  n/a " if x is None else f"{100*x:5.1f}%"
 
 
def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--sample", required=True)
    ap.add_argument("--rows", required=True)
    ap.add_argument("--table", action="store_true")
    ap.add_argument("--wiki", action="store_true")
    args = ap.parse_args()
 
    S = json.load(open(args.sample))
    ROWS = {r["domain"]: r for r in json.load(open(args.rows))}
    frame_n = S["frame_size"]
 
    # ---- 0. the sample is complete and the vocabulary is closed ------------
    missing = sorted({r["domain"] for L in S["lists"].values() for r in L["rows"]}
                     - set(ROWS))
    if missing:
        raise SystemExit(f"FATAL: {len(missing)} sampled domains have no adjudication row: {missing}")
    bad = [(d, k, r[k]) for d, r in ROWS.items() for k in KEY.values()
           if r[k] not in VERDICTS and r[k] != "unknown"]
    selfnamed = [(d, k) for d, r in ROWS.items() for k in KEY.values() if r[k] == "self-named"]
    if selfnamed:
        raise SystemExit("FATAL: `self-named` verdicts survive; run owner_verdict_fixes.py")
    if bad:
        raise SystemExit(f"FATAL: verdicts outside the vocabulary: {bad}")
 
    print("=" * 78)
    print("Per-list ownership accuracy from a stratified random sample")
    print("=" * 78)
    print()
    print(f"Frame: {frame_n:,} registrable domains (Tracker Radar domain_summary.json,")
    print("ICANN-section PSL fold, parent-label lookup). Seed "
          f"{S['seed']}, {S['per_list']} draws per list, allocation {tuple(S['alloc'])}")
    print("over prevalence quartiles of each list's own coverage. Adjudicated 2026-09-05.")
    print("Input snapshots: " + ", ".join(f"{k}={v}" for k, v in sorted(S["hashes"].items())))
    print()
 
    # a domain drawn for one list carries a verdict for all three; only its own
    # list's sample is used for that list's estimate.
    union = {r["domain"]: r for r in S["union"]}
 
    # ---- 1. resolution and self-naming, the two denominators ---------------
    print("--- A. What the sample could and could not settle ---------------------")
    print()
    print("Rows are excluded from every accuracy rate below when the primary-source bar")
    print("was not met. In a random sample that is a large share, and it rises toward")
    print("the tail, so it is reported first and per quartile rather than buried.")
    print()
    hdr = f"{'List':14} {'drawn':>6} {'unresolved':>11} {'eligible':>9}   per quartile (eligible/drawn)"
    print(hdr)
    ELIG = {}
    # Domain names positionally aligned with ELIG, so a row can be identified by
    # index rather than by matching its prevalence -- Q4 prevalences are all
    # equal to 0.000007 and matching on the value would pick an arbitrary row.
    ELIG_NAMES = {}
    for lab in LISTS:
        L = S["lists"][lab]
        per_q, tot_u, tot_e = [], 0, 0
        elig = [[] for _ in range(4)]
        names = [[] for _ in range(4)]
        for r in L["rows"]:
            v = ROWS[r["domain"]][KEY[lab]]
            h = r["stratum"] - 1
            if v in ("unresolved", "unknown") or ROWS[r["domain"]]["resolution"] != "resolved":
                tot_u += 1
            elif v in INELIGIBLE:
                tot_u += 1                      # `absent` cannot occur in own sample
            else:
                elig[h].append((r["prevalence"], v))
                names[h].append(r["domain"])
                tot_e += 1
        for h in range(4):
            drawn = sum(1 for r in L["rows"] if r["stratum"] == h + 1)
            per_q.append(f"Q{h+1} {len(elig[h])}/{drawn}")
        ELIG[lab] = elig
        ELIG_NAMES[lab] = names
        print(f"{lab:14} {len(L['rows']):>6} {tot_u:>11} {tot_e:>9}   " + "  ".join(per_q))
    print()
 
    # ---- 2. the estimates --------------------------------------------------
    rng = random.Random(SEED)
    print("--- B. Per-list verdict rates, with 95% bootstrap intervals -----------")
    print()
    print("Denominator: the entries of that list which the sample could settle and which")
    print("make an ownership claim (the 'eligible' column above), scaled to the list's")
    print("whole coverage by stratum weights. 'domain-level' weights every domain the")
    print("list covers equally; 'encounter-weighted' weights by Tracker Radar prevalence,")
    print("i.e. how often a crawl actually meets the domain.")
    print()
    WIKI = {}
    for lab in LISTS:
        L = S["lists"][lab]
        weights = list(zip(L["strata_N"], L["strata_mass"]))
        elig = ELIG[lab]
        n_elig = sum(len(x) for x in elig)
        print(f"{lab}  (covers {L['N_total']:,} of {frame_n:,} frame domains = "
              f"{100*L['N_total']/frame_n:.1f}%; n eligible = {n_elig})")
        empty = [h + 1 for h in range(4) if not elig[h]]
        if empty:
            print(f"  strata with no eligible row, dropped and weights renormalised: "
                  + ", ".join(f"Q{h}" for h in empty))
        print(f"  {'verdict':14} {'domain-level':>13} {'95% CI':>16}   "
              f"{'encounter-wtd':>14} {'95% CI':>16}")
        rows = []
        for v in ("current", "granularity", "stale", "error"):
            d, p = strat_estimate(elig, weights, lambda x, v=v: x == v)
            (dl, dh), (pl, ph) = bootstrap(elig, weights, lambda x, v=v: x == v, rng)
            print(f"  {v:14} {pct(d):>13} {'['+pct(dl)+','+pct(dh)+']':>16}   "
                  f"{pct(p):>14} {'['+pct(pl)+','+pct(ph)+']':>16}")
            rows.append((v, d, dl, dh, p, pl, ph))
        zero = [v for v in ("current", "granularity", "stale", "error")
                if not any(v == y for st in elig for _, y in st)]
        if zero:
            import math
            print(f"  zero cells ({', '.join(zero)}): the bootstrap interval on a cell with no"
                  f" observations is [0,0] and asserts nothing.")
            print(f"  The usable statement is the rule-of-three upper bound: with {n_elig} "
                  f"eligible rows and 0 seen, the true rate is below "
                  f"{100*3/n_elig:.1f}% at 95% confidence.")
        for label, f in (("current+gran.", lambda x: x in ("current", "granularity")),
                         ("stale+error", lambda x: x in ("stale", "error"))):
            d, p = strat_estimate(elig, weights, f)
            (dl, dh), (pl, ph) = bootstrap(elig, weights, f, rng)
            print(f"  {label:14} {pct(d):>13} {'['+pct(dl)+','+pct(dh)+']':>16}   "
                  f"{pct(p):>14} {'['+pct(pl)+','+pct(ph)+']':>16}")
            rows.append((label, d, dl, dh, p, pl, ph))
        WIKI[lab] = rows
        print()
 
    # ---- 3. coverage is a census, not an estimate --------------------------
    print("--- C. Coverage is not estimated: it is counted --------------------")
    print()
    print("'absent' needs no sample. Each list either has an entry for a frame domain or")
    print("it does not, and both can be counted over all "
          f"{frame_n:,} of them.")
    print(f"  {'List':14} {'domains named':>14} {'of frame':>9} {'prevalence-weighted':>21}")
    for lab in LISTS:
        L = S["lists"][lab]
        print(f"  {lab:14} {L['N_total']:>14,} {100*L['N_total']/frame_n:>8.1f}% "
              f"{100*sum(L['strata_mass'])/S['frame_mass']:>20.1f}%")
    print()
 
    # ---- 3b. how much of the encounter-weighted estimate is one domain ----
    # The encounter-weighted column is a ratio estimator, and its weights are
    # Tracker Radar prevalences, which span five orders of magnitude. That makes
    # it possible for a single drawn domain to carry most of a list's estimate --
    # and a point estimate that rests on one observation should say so next to
    # itself, not only inside a bootstrap interval a reader has to interpret.
    print("--- C2. Concentration: how much of the encounter-weighted estimate is one row ---")
    print()
    print("Share of the encounter-weighted estimate contributed by each list's single")
    print("heaviest eligible row, and what the 'current' rate becomes if that one row's")
    print("verdict is flipped to stale. This is a sensitivity check, not a result: the")
    print("flipped figure is what the estimate WOULD be, not a claim that it is.")
    print()
    for lab in LISTS:
        L = S["lists"][lab]
        weights = list(zip(L["strata_N"], L["strata_mass"]))
        elig = ELIG[lab]
        names = ELIG_NAMES[lab]
        Msum = sum(weights[h][1] for h in range(4) if elig[h])
        contrib = []
        for h in range(4):
            tot = sum(p for p, v in elig[h])
            if tot <= 0:
                continue
            for i, (p, v) in enumerate(elig[h]):
                contrib.append((weights[h][1] / Msum * p / tot, h, i, v, names[h][i]))
        contrib.sort(reverse=True)
        share, h0, i0, v0, name = contrib[0]
        flipped = [[(p, ("stale" if (h == h0 and i == i0) else v))
                    for i, (p, v) in enumerate(elig[h])] for h in range(4)]
        _, cur_p = strat_estimate(elig, weights, lambda x: x == "current")
        _, cur_f = strat_estimate(flipped, weights, lambda x: x == "current")
        print(f"  {lab:14} heaviest row {name:24} verdict {v0:11} "
              f"carries {100*share:5.1f}% of the estimate")
        print(f"  {'':14}   encounter-weighted 'current' {100*cur_p:5.1f}%  ->  "
              f"{100*cur_f:5.1f}% if that one row were stale")
        print(f"  {'':14}   top three rows together carry "
              f"{100*sum(c[0] for c in contrib[:3]):5.1f}%")
    print()
 
    # ---- 4. cross-list verdicts on shared rows, reported not merged --------
    print("--- D. Verdicts on domains drawn for another list (NOT in any estimate) ---")
    print()
    print("Each drawn domain was adjudicated once and the verdict recorded for all three")
    print("lists. Only a list's own sample enters its estimate above; these are the rest,")
    print("printed so the discarded observations are visible rather than silently dropped.")
    for lab in LISTS:
        own = {r["domain"] for r in S["lists"][lab]["rows"]}
        other = Counter(ROWS[d][KEY[lab]] for d in ROWS if d not in own)
        print(f"  {lab:14} " + "  ".join(f"{k}={v}" for k, v in sorted(other.items())))
    print()
 
    # ---- 5. residue --------------------------------------------------------
    print("--- E. Residue: every row excluded from an estimate --------------------")
    print()
    for lab in LISTS:
        for r in S["lists"][lab]["rows"]:
            row = ROWS[r["domain"]]
            v = row[KEY[lab]]
            if v in INELIGIBLE or row["resolution"] != "resolved":
                print(f"  {lab:14} Q{r['stratum']} {r['domain']:32} {v:11} "
                      f"{row['resolution']:10} {(row.get('note') or '')[:78]}")
    print()
 
    if args.table or args.wiki:
        print("--- F. The adjudication table ---------------------------------------")
        print()
        if args.wiki:
            print("^ Domain ^ Prev. ^ Owner today ^ When it changed ^ webXray ^ Tracker Radar ^ Disconnect ^ Primary source ^")
            for d in sorted(union, key=lambda x: -union[x]["prevalence"]):
                r = ROWS[d]
                src = f"[[{r['source']}|{r.get('source_kind','source')}]]" if r.get("source") else "//none//"
                print(f"| ''{d}'' | {union[d]['prevalence']:.5f} | {r.get('owner_today') or '//unresolved//'} | "
                      f"{r.get('when_changed','')} | {r['webXray']} | {r['tracker_radar']} | "
                      f"{r['disconnect']} | {src} |")
        else:
            for d in sorted(union, key=lambda x: -union[x]["prevalence"]):
                r = ROWS[d]
                print(f"{d:32} {union[d]['prevalence']:.5f} {(r.get('owner_today') or 'UNRESOLVED')[:40]:40} "
                      f"{r['webXray']:11} {r['tracker_radar']:11} {r['disconnect']:11} {r.get('source','')}")
        print()
 
    if args.wiki:
        print("--- G. DokuWiki rate tables -----------------------------------------")
        print()
        for lab in LISTS:
            print(f"=== {lab} ===")
            print("^ Verdict ^ Domain-level ^ 95% CI ^ Encounter-weighted ^ 95% CI ^")
            for v, d, dl, dh, p, pl, ph in WIKI[lab]:
                print(f"| {v} | {pct(d).strip()} | {pct(dl).strip()}–{pct(dh).strip()} | "
                      f"{pct(p).strip()} | {pct(pl).strip()}–{pct(ph).strip()} |")
            print()
    return 0
 
 
if __name__ == "__main__":
    sys.exit(main())

J. scripts/owner_selfname_census.py — the census that needs no sample

Counts entities whose name is the domain over every pair in every file. This is what replaced the retired self-named verdict.

owner_selfname_census.py
#!/usr/bin/env python3
"""Census of entities whose "owner" name is just a domain.
 
The random-sample adjudication first carried a `self-named` verdict for these.
That was a mistake and is recorded as one: whether "Simpli.fi" is a company name
or a domain string is a judgement, and putting it in the verdict vocabulary
mixed a judgement about the world into what is a **property of the file** --
and one that needs no sample at all, because it can be counted over every entry
in every list.
 
Two counts per list, both over the whole file:
  identical  the entity name, lowercased with non-alphanumerics stripped, equals
             one of the domains it covers, TLD included ("cdnbasket.net")
  label-only the entity name equals the domain's label without its TLD
             ("Klaviyo" for klaviyo.com) -- usually the company really is called
             that, so this is NOT a defect; it is printed to show how much of
             the first count is the same phenomenon one character shorter
 
    python3 owner_selfname_census.py --cache ./cache
"""
import argparse, os, re, sys
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
import owner_dbs as od
 
n = lambda s: re.sub(r"[^a-z0-9]", "", (s or "").lower())
 
 
def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--cache", default="./cache")
    args = ap.parse_args()
    data = {k: od.fetch(k, args.cache)[0] for k in od.SOURCES}
 
    wx = {}
    for e in data["webxray"]:
        for d in e["domains"]:
            wx[d.lower()] = e["name"]
    tr = {d.lower(): v["entityName"] for d, v in data["tr_domain_map"].items()}
    dc = {}
    for name, v in data["disconnect_entities"]["entities"].items():
        for d in v.get("resources", []) + v.get("properties", []):
            dc[d.lower()] = name
 
    print("Entities whose name is a domain rather than a company name")
    print("(census over every DOMAIN in each file, not a sample. The maps are keyed")
    print("on the lowercased domain, so this counts distinct domains: webXray has")
    print("3,224 domain->owner pairs but 3,215 distinct domains, three of them")
    print("carrying a trailing slash in the file.)")
    print()
    print(f"{'List':16} {'domains':>8} {'identical':>11} {'share':>7} {'label-only':>11} {'share':>7}")
    for lab, m in (("webXray", wx), ("Tracker Radar", tr), ("Disconnect", dc)):
        ident = [d for d, o in m.items() if n(o) == n(d)]
        label = [d for d, o in m.items() if n(o) != n(d) and n(o) == n(d.split(".")[0])]
        print(f"{lab:16} {len(m):>8,} {len(ident):>11,} {100*len(ident)/len(m):>6.1f}% "
              f"{len(label):>11,} {100*len(label)/len(m):>6.1f}%")
    print()
    for lab, m in (("webXray", wx), ("Tracker Radar", tr), ("Disconnect", dc)):
        ident = sorted(d for d, o in m.items() if n(o) == n(d))
        print(f"{lab}: first 12 identical entries -> " + ", ".join(
            f"{d}={m[d]!r}" for d in ident[:12]))
    print()
    print("A name identical to the domain tells a measurement nothing it did not")
    print("already have. A name identical to the domain's label usually does -- the")
    print("company is called Klaviyo -- so only the first column is a defect, and")
    print("the second is printed so the first cannot be inflated by conflating them.")
    return 0
 
 
if __name__ == "__main__":
    sys.exit(main())

K. scripts/owner_citation_audit.py — where every row's citation landed

Reads the three verification artefacts and states, per row, whether its citation was confirmed by bytes, by a browser, or not at all. Written because the final bytes-only pass still reports three failures and the answer to “are three figures uncited?” lived in three separate files.

owner_citation_audit.py
#!/usr/bin/env python3
"""Close the loop on the ownership adjudication's citations: every one of the
175 rows must end in a state a reader can check.
 
Three machine passes ran over the rows, in this order:
 
  1. ``owner_verify_sources.py`` -- re-fetch the cited URL with ``curl``-grade
     HTTP (or, for a ``tls://`` source, redo the handshake) and look for the
     quoted sentence in the bytes.
  2. ``owner_verify_rendered.mjs`` -- re-check whatever pass 1 could not find,
     in a real browser. A legal-entity name in a footer or an Impressum is
     frequently client-rendered, so a NOTFOUND from raw HTML is evidence about
     the instrument, not about the citation.
  3. ``owner_corrections.py`` -- by hand, for what survived pass 2: requote,
     re-source, or demote the row to ``unresolved``.
 
This script states where each row landed, so "every citation was verified" is a
countable claim rather than an assertion. It reads only the committed artefacts
and computes nothing new.
 
    python3 owner_citation_audit.py
 
Written 2026-09-05 because a reviewer asked the obvious question -- 'the final
verify run still reports three failures, so are three figures on the page
uncited?' -- and the answer was in three separate JSON files.
"""
import json
from collections import Counter
 
ROWS = "out/adj_rows_scored.json"
VERIFY_FIRST = "out/verify.json"          # pass 1, before corrections
VERIFY_FINAL = "out/verify_final.json"    # pass 1 re-run, after corrections
RENDERED = "out/verify_rendered.json"     # pass 2
OK = {"OK", "OK-WINDOW", "OK-FRAGMENTS"}
 
 
def main():
    rows = {r["domain"]: r for r in json.load(open(ROWS))}
    first = {r["domain"]: r for r in json.load(open(VERIFY_FIRST))}
    final = {r["domain"]: r for r in json.load(open(VERIFY_FINAL))}
    rendered = {r["domain"]: r for r in json.load(open(RENDERED))}
 
    print("Citation audit of the 175 adjudicated rows")
    print("=" * 78)
    print()
    print("A row is CITED only if the quoted sentence was found on the cited")
    print("source by a machine -- bytes, a browser, or a re-done TLS handshake.")
    print("An `unresolved` row makes no ownership claim and enters no rate, so it")
    print("needs no citation; it is counted separately rather than as a pass.")
    print()
 
    state, detail = {}, {}
    for d, r in rows.items():
        if r["resolution"] == "unresolved":
            state[d] = "no claim (unresolved)"
            continue
        f = final[d]["status"]
        if f in OK:
            state[d] = "cited (bytes)"
            detail[d] = f
            continue
        rr = rendered.get(d, {}).get("rendered")
        if rr in OK:
            state[d] = "cited (browser)"
            detail[d] = rr
            continue
        state[d] = "UNCITED"
        detail[d] = "%s / %s" % (f, rr)
 
    for k, n in sorted(Counter(state.values()).items(), key=lambda kv: -kv[1]):
        print("  %-24s %3d" % (k, n))
    print("  %-24s %3d" % ("total", len(rows)))
    print()
 
    uncited = [d for d, s in state.items() if s == "UNCITED"]
    print("UNCITED rows (each one would be a figure with no checkable source): %d" % len(uncited))
    for d in sorted(uncited):
        print("   %-24s %s" % (d, detail[d]))
    print()
 
    print("Rows whose citation only survives because a browser was used, i.e.")
    print("the ones a bytes-only audit would wrongly call broken:")
    for d in sorted(d for d, s in state.items() if s == "cited (browser)"):
        print("   %-24s curl=%-10s browser=%s  %s"
              % (d, final[d]["status"], rendered[d]["rendered"], rows[d]["source"][:64]))
    print()
 
    moved = [d for d in rows if first[d]["status"] in OK and final[d]["status"] not in OK]
    print("Rows that passed pass 1 and fail it after the corrections: %d" % len(moved))
    for d in sorted(moved):
        print("   %-24s %s -> %s" % (d, first[d]["status"], final[d]["status"]))
    print()
 
    print("Source kinds actually cited, over the %d rows that make a claim:"
          % sum(1 for r in rows.values() if r["resolution"] == "resolved"))
    kinds = Counter()
    for r in rows.values():
        if r["resolution"] != "resolved":
            continue
        s = r["source"]
        kinds["TLS certificate subject" if s.startswith("tls://") else "HTTP(S) document"] += 1
    for k, n in kinds.most_common():
        print("   %-26s %3d" % (k, n))
 
 
if __name__ == "__main__":
    main()

L. scripts/check_owner_sample_figures.py — the page-versus-estimator guard

Asserts that every random-sample figure on the content page is present in and equal to the estimator's own output, and fails if a figure has been deleted as well as if it disagrees. It compares the page to the tool and therefore cannot see a bug inside the tool, nor a correct figure attached to the wrong sentence; its own limits are in its docstring.

check_owner_sample_figures.py
#!/usr/bin/env python3
"""Assert that every random-sample figure on ``programming:crawler:webxray``
matches the estimator's own output.
 
    python3 check_owner_sample_figures.py --page pages/wx_new.txt \
        --output out/owner_random_sample-output.txt
 
**What this does not do.** It compares the page to the tool. A bug inside
``owner_random_sample.py`` passes every assertion here, and so does a figure
that is arithmetically right and attached to the wrong sentence. It catches one
thing only: a page figure drifting from the script that produced it, which is
what happens when a script is re-run and the page is not. Read the prose by hand
as well.
 
It is written to fail if the page stops containing a figure, not only if the
figure disagrees -- a guard that passes because the string it was looking for
was deleted is a guard that asserts nothing.
"""
import argparse, re, sys
 
# (label, regex over the estimator output, list of strings that must be on the
#  page verbatim, built from the captured groups)
CHECKS = []
 
 
def parse_wiki_tables(out):
    """Section G of the estimator prints one DokuWiki table per list."""
    tables, cur = {}, None
    for line in out.splitlines():
        m = re.match(r"=== (.+) ===$", line)
        if m:
            cur = m.group(1)
            tables[cur] = {}
            continue
        if cur and line.startswith("| "):
            cells = [c.strip() for c in line.strip("|").split("|")]
            if len(cells) == 5:
                tables[cur][cells[0]] = cells[1:]
    return tables
 
 
def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--page", required=True)
    ap.add_argument("--output", required=True)
    args = ap.parse_args()
 
    page = open(args.page, encoding="utf8").read()
    out = open(args.output, encoding="utf8").read()
    tables = parse_wiki_tables(out)
    if set(tables) != {"webXray", "Tracker Radar", "Disconnect"}:
        sys.exit(f"FATAL: estimator output has tables for {sorted(tables)}; "
                 "section G is missing or renamed, so nothing below was checked")
 
    fails, checked = [], 0
 
    # 1. the headline table: domain-level and encounter-weighted `current`
    for lab in ("webXray", "Tracker Radar", "Disconnect"):
        dom, dom_ci, enc, enc_ci = tables[lab]["current"]
        for val in (dom, enc):
            checked += 1
            if val not in page:
                fails.append(f"{lab} current {val!r} is not on the page")
        for ci in (dom_ci, enc_ci):
            checked += 1
            # the page writes 55.5-83.1% where the script writes 55.5%-83.1%
            lo, hi = ci.split("–")
            pat = re.escape(lo.rstrip("%")) + r"–?[–-]?" + re.escape(hi.rstrip("%"))
            if not re.search(lo.rstrip("%") + r"[–-]" + hi.rstrip("%"), page):
                fails.append(f"{lab} current interval {ci!r} is not on the page")
 
    # 2. current+granularity, quoted in the paragraph under the table
    for lab in ("webXray", "Tracker Radar", "Disconnect"):
        dom = tables[lab]["current+gran."][0]
        checked += 1
        if dom not in page:
            fails.append(f"{lab} current+gran. {dom!r} is not on the page")
 
    # 3. webXray's stale rate, quoted in the recommendation table
    checked += 1
    if tables["webXray"]["stale"][0] not in page:
        fails.append(f"webXray stale {tables['webXray']['stale'][0]!r} is not on the page")
 
    # 4. eligible counts and coverage, from sections A and C of the output
    m = re.search(r"^webXray\s+60\s+(\d+)\s+(\d+)\s", out, re.M)
    tr = re.search(r"^Tracker Radar\s+60\s+(\d+)\s+(\d+)\s", out, re.M)
    dc = re.search(r"^Disconnect\s+60\s+(\d+)\s+(\d+)\s", out, re.M)
    if not (m and tr and dc):
        sys.exit("FATAL: section A of the estimator output did not parse")
    for lab, mm in (("webXray", m), ("Tracker Radar", tr), ("Disconnect", dc)):
        checked += 1
        if f"**{mm.group(2)}, " not in page and f"| {mm.group(2)} |" not in page:
            fails.append(f"{lab} eligible count {mm.group(2)} is not on the page")
 
    for lab, n, pct in re.findall(
            r"^  (webXray|Tracker Radar|Disconnect)\s+([\d,]+)\s+(\d+\.\d)%", out, re.M):
        checked += 2
        if n not in page:
            fails.append(f"{lab} coverage count {n} is not on the page")
        if pct + "%" not in page:
            fails.append(f"{lab} coverage share {pct}% is not on the page")
 
    # 5. the concentration figures added in section C2
    for lab, dom, share in re.findall(
            r"^  (webXray|Tracker Radar|Disconnect)\s+heaviest row (\S+)\s+verdict \w+\s+"
            r"carries\s+(\d+\.\d)% of the estimate", out, re.M):
        checked += 2
        if dom not in page:
            fails.append(f"{lab} heaviest row {dom} is not on the page")
        if share + "%" not in page:
            fails.append(f"{lab} concentration {share}% is not on the page")
 
    print(f"checked {checked} figures from {args.output} against {args.page}")
    if fails:
        for f in fails:
            print("  FAIL " + f)
        sys.exit(f"\n{len(fails)} figure(s) on the page do not match the estimator")
    print("all present and matching")
 
 
if __name__ == "__main__":
    main()

M. scripts/check_owner_sample_figures_mutations.sh — proving the guard bites

Ten corruptions of the page, one figure each, asserting the guard rejects every one. A guard that has never been seen to fail asserts nothing, and this repository has published one that did not.

check_owner_sample_figures_mutations.sh
#!/bin/bash
# Mutation test for check_owner_sample_figures.py.
#
# A guard that passes tells you nothing until you have seen it fail. This
# corrupts one figure on the page at a time and asserts the guard rejects each
# corruption; if any mutation survives, the guard is not checking what its name
# claims and the exit code says so.
#
#   bash scripts/check_owner_sample_figures_mutations.sh
set -u
PAGE=pages/wx_new.txt
OUT=out/owner_random_sample-output.txt
TMP=$(mktemp -d)
fails=0
 
mutate () {                     # $1 = label, $2 = sed expression
  sed "$2" "$PAGE" > "$TMP/p.txt"
  if cmp -s "$PAGE" "$TMP/p.txt"; then
    echo "SURVIVED  $1  <- mutation changed nothing; the guard was never exercised"
    fails=$((fails+1)); return
  fi
  if python3 scripts/check_owner_sample_figures.py --page "$TMP/p.txt" --output "$OUT" >/dev/null 2>&1; then
    echo "SURVIVED  $1  <- the guard accepted a corrupted page"
    fails=$((fails+1))
  else
    echo "caught    $1"
  fi
}
 
mutate "webXray domain-level 69.9% -> 70.9%"        's/69\.9%/70.9%/g'
mutate "Disconnect domain-level 94.4% -> 95.4%"     's/94\.4%/95.4%/g'
mutate "webXray encounter-weighted 93.9% -> 92.9%"  's/93\.9%/92.9%/g'
mutate "coverage count 5,566 -> 5,567"              's/5,566/5,567/g'
mutate "coverage share 17.2% -> 17.3%"              's/17\.2%/17.3%/g'
mutate "Disconnect CI 86.9-100.0 -> 87.9-100.0"     's/86\.9–100\.0/87.9–100.0/g'
mutate "concentration 39.4% -> 41.0%"               's/39\.4%/41.0%/g'
mutate "current+gran. 80.2% -> 81.2%"               's/80\.2%/81.2%/g'
mutate "webXray stale 19.8% -> 18.8%"               's/19\.8%/18.8%/g'
mutate "heaviest row gstatic.com -> gstaticx.com"   's/gstatic\.com/gstaticx.com/g'
 
rm -rf "$TMP"
echo
if [ "$fails" -gt 0 ]; then
  echo "$fails mutation(s) survived: the guard does not check what it claims."
  exit 1
fi
echo "all mutations caught."

N. scripts/owner_reestimate_independent.py — the estimator, written twice

A second implementation of the stratified estimator that imports nothing from the first. Every other guard here compares a page to a tool's output, so a bug inside the tool passes all of them; this is the only check that closes that. It agrees with owner_random_sample.py on all 24 figures the content page publishes. It does not re-implement the bootstrap intervals, and says so.

owner_reestimate_independent.py
#!/usr/bin/env python3
"""A second, independent implementation of the stratified estimator.
 
Every guard in this repository compares a **page** to a **tool's output**. A bug
inside the tool passes all of them: the page matches the script, the script
matches its committed output, and the number is wrong. The only check that
closes that is a second implementation that shares no code with the first.
 
So this reads ``owner_sample.json`` and ``adj_rows_scored.json`` and nothing
else — it does **not** import ``owner_random_sample.py``, ``owner_dbs.py`` or
``owner_sample.py`` — recomputes the figures the content page publishes, and
prints them beside the estimator's own committed output for comparison.
 
It deliberately does not re-implement the bootstrap intervals. Those remain
checked only by the estimator itself, and the pages say so.
 
    python3 owner_reestimate_independent.py
 
Written 2026-09-05.
"""
import json
 
SAMPLE = "out/owner_sample.json"
ROWS = "out/adj_rows_scored.json"
KEY = {"webXray": "webXray", "Tracker Radar": "tracker_radar", "Disconnect": "disconnect"}
ELIGIBLE = {"current", "stale", "granularity", "error"}
ORDER = ["webXray", "Tracker Radar", "Disconnect"]
 
# What owner_random_sample.py printed, transcribed by hand from its committed
# output. If the two disagree, one of them is wrong and this script says which
# figure -- it does not silently prefer either.
EXPECTED = {
    #                current  stale  cur+gran  error   enc-current  heaviest        share   flipped
    "webXray":       (69.9,   19.8,  80.2,     0.0,    93.9,        "gstatic.com",  39.4,   54.4),
    "Tracker Radar": (73.7,   22.1,  76.5,     1.5,    68.6,        "omtrdc.net",   24.9,   43.7),
    "Disconnect":    (94.4,    1.2,  98.8,     0.0,    83.1,        "id5-sync.com", 16.7,   66.4),
}
 
 
def main():
    S = json.load(open(SAMPLE))
    R = {r["domain"]: r for r in json.load(open(ROWS))}
    bad = []
 
    for lab in ORDER:
        L = S["lists"][lab]
        k = KEY[lab]
        strata = {h: [] for h in range(4)}
        for r in L["rows"]:
            row = R[r["domain"]]
            v = row[k]
            if v in ELIGIBLE and row["resolution"] == "resolved":
                strata[r["stratum"] - 1].append((r["domain"], r["prevalence"], v))
        live = [h for h in range(4) if strata[h]]
 
        # domain-level: weight each stratum by its share of the list's coverage
        Nsum = sum(L["strata_N"][h] for h in live)
 
        def dom(pick):
            return sum(L["strata_N"][h] / Nsum
                       * sum(1 for _, _, v in strata[h] if pick(v)) / len(strata[h])
                       for h in live)
 
        # encounter-weighted: ratio estimator inside each stratum, strata weighted
        # by prevalence mass
        Msum = sum(L["strata_mass"][h] for h in live)
        share = {}
        enc = 0.0
        for h in live:
            tot = sum(p for _, p, _ in strata[h])
            for d, p, v in strata[h]:
                share[d] = L["strata_mass"][h] / Msum * p / tot
                if v == "current":
                    enc += share[d]
        heavy = max(share, key=share.get)
        flipped = sum(c for d, c in share.items() if d != heavy and R[d][k] == "current")
 
        got = (round(100 * dom(lambda v: v == "current"), 1),
               round(100 * dom(lambda v: v == "stale"), 1),
               round(100 * dom(lambda v: v in ("current", "granularity")), 1),
               round(100 * dom(lambda v: v == "error"), 1),
               round(100 * enc, 1),
               heavy,
               round(100 * share[heavy], 1),
               round(100 * flipped, 1))
        want = EXPECTED[lab]
        names = ("current", "stale", "current+gran.", "error", "encounter-current",
                 "heaviest row", "its share", "flipped")
        print(f"{lab}  (n eligible = {sum(len(strata[h]) for h in live)})")
        for n, g, w in zip(names, got, want):
            mark = "ok " if g == w else "MISMATCH"
            if g != w:
                bad.append(f"{lab} {n}: independent {g}, estimator {w}")
            unit = "" if isinstance(g, str) else "%"
            print(f"  {mark} {n:20} independent {g}{unit:1}   estimator {w}{unit:1}")
        print()
 
    if bad:
        for b in bad:
            print("  FAIL " + b)
        raise SystemExit(f"{len(bad)} figure(s) disagree between the two implementations")
    print("Both implementations agree on every figure the content page publishes.")
    print("Not covered here: the bootstrap confidence intervals, which are")
    print("computed only by owner_random_sample.py.")
 
 
if __name__ == "__main__":
    main()

O. scripts/check_wrapped_lists.py — the guard that saved both pages

Not a measurement script. It detects DokuWiki list items whose text is wrapped onto an indented following line — which ends the list and renders everything after it, including the next bullets, as a preformatted block. The drafts of these pages carried 46 and 82 of them and every other check passed. Published because the provenance page describes its behaviour and its controls at length, and a description of a guard is worth nothing without the guard.

check_wrapped_lists.py
#!/usr/bin/env python3
"""Fail on DokuWiki list items whose text is wrapped onto a following line.
 
Verified empirically against the live wiki on 2026-09-05 (written to
``playground:playground``, rendered through ``core.getPageHTML``, reverted).
Given::
 
      * **A bullet.** This is the
        second line, indented four spaces.
        A third line, same indent.
      * A second bullet.
 
DokuWiki renders the first line as the list item, the **second** line as a
separate paragraph outside the list, and the third line onwards as a
``<pre class="code">`` block -- swallowing every following bullet as literal
text. One wrapped bullet therefore destroys the rest of the list, and the page
source looks perfectly reasonable.
 
The rule is simply: **a list item is one line.** This checker enforces it, and
``--fix`` rewrites the file by joining continuations back onto their item.
 
    python3 check_wrapped_lists.py pages/foo.txt [--fix]
 
``<code>``, ``<file>`` and ``%%..%%`` regions are exempt: text inside them is
verbatim and indentation there means nothing.
"""
import argparse, re, sys
 
LIST = re.compile(r"^(\s+)([*-])\s")
INDENTED = re.compile(r"^\s+\S")
 
 
def spans_to_skip(text):
    """Line indices inside <code>/<file> blocks."""
    skip, depth = set(), 0
    for i, ln in enumerate(text.split("\n")):
        opening = re.match(r"^<(code|file)\b", ln)
        closing = re.match(r"^</(code|file)>", ln)
        if opening:
            depth += 1
            skip.add(i)
            continue
        if closing:
            skip.add(i)
            depth = max(0, depth - 1)
            continue
        if depth:
            skip.add(i)
    return skip
 
 
def scan(text):
    """Return [(line_no, item_line, continuation_line)] for every wrapped item."""
    lines = text.split("\n")
    skip = spans_to_skip(text)
    bad, in_list = [], False
    for i, ln in enumerate(lines):
        if i in skip:
            in_list = False
            continue
        if LIST.match(ln):
            in_list = True
            continue
        if in_list and INDENTED.match(ln) and ln.strip():
            bad.append((i + 1, lines[i - 1].strip()[:70], ln.strip()[:70]))
            # stay in_list: consecutive continuations are all part of the defect
            continue
        if not ln.strip():
            in_list = False
    return bad
 
 
def fix(text):
    """Join every continuation line back onto its list item."""
    lines = text.split("\n")
    skip = spans_to_skip(text)
    out, in_list = [], False
    for i, ln in enumerate(lines):
        if i in skip:
            in_list = False
            out.append(ln)
            continue
        if LIST.match(ln):
            in_list = True
            out.append(ln)
            continue
        if in_list and INDENTED.match(ln) and ln.strip():
            out[-1] = out[-1].rstrip() + " " + ln.strip()
            continue
        if not ln.strip():
            in_list = False
        out.append(ln)
    return "\n".join(out)
 
 
def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("files", nargs="+")
    ap.add_argument("--fix", action="store_true")
    args = ap.parse_args()
 
    total = 0
    for f in args.files:
        text = open(f, encoding="utf8").read()
        bad = scan(text)
        if args.fix and bad:
            new = fix(text)
            open(f, "w", encoding="utf8").write(new)
            left = scan(new)
            if left:
                sys.exit(f"FATAL: {f}: {len(left)} wrapped item(s) survived --fix")
            print(f"{f}: joined {len(bad)} continuation line(s)")
            continue
        if bad:
            print(f"{f}: {len(bad)} wrapped list continuation(s) -- each one ends "
                  f"the list and turns what follows into a code block")
            for n, item, cont in bad[:8]:
                print(f"   line {n}: item {item!r}")
                print(f"             cont {cont!r}")
            if len(bad) > 8:
                print(f"   ... and {len(bad) - 8} more")
            total += len(bad)
        else:
            print(f"{f}: OK")
    sys.exit(1 if total else 0)
 
 
if __name__ == "__main__":
    main()

P. scripts/wayback_webxray.sh — the CDX queries

The six Wayback CDX queries that date webXray's disappearance. Query 3 exists because collapse=digest hides how many captures there were: every transition found with it is re-queried uncollapsed before a date is published.

wayback_webxray.sh
#!/bin/bash
# Date webXray's disappearance from the Wayback Machine's CDX index.
#
# The 2026-08-17 run recorded both questions below as *unknown*: web.archive.org
# returned 502/503 all day, nine attempts over ~30 minutes on two fetch paths.
# The Archive was up on 2026-09-05 and answers both -- as BOUNDS, not dates,
# because it has no capture inside either window.
#
# `collapse=digest` returns one row per distinct response body, which is what
# makes a 200 -> 404 transition visible in a handful of lines. It also HIDES how
# many captures there were, so every transition found this way is re-queried
# uncollapsed over a narrow window before any date is published (query 3).
#
#   bash scripts/wayback_webxray.sh
set -u
CDX=https://web.archive.org/cdx/search/cdx
q() { echo; echo "### $1"; echo "\$ curl -s '$2'"; timeout 120 curl -s --max-time 120 "$2"; }
 
q "1. github.com/timlib/webXray -- one row per distinct body" \
  "$CDX?url=github.com%2Ftimlib%2FwebXray&fl=timestamp,statuscode,digest&collapse=digest"
 
q "2. github.com/timlib/webXray_Domain_Owner_List -- same" \
  "$CDX?url=github.com%2Ftimlib%2FwebXray_Domain_Owner_List&fl=timestamp,statuscode,digest&collapse=digest"
 
q "3. github.com/timlib/webXray -- UNCOLLAPSED across the 200->404 transition.
     Two rows here means there is no capture between them and the window
     cannot be narrowed; more rows would mean the collapse hid something." \
  "$CDX?url=github.com%2Ftimlib%2FwebXray&fl=timestamp,statuscode,length&from=20230101&to=20240601"
 
q "4. github.com/timlib -- the profile, in case it brackets either window" \
  "$CDX?url=github.com%2Ftimlib&fl=timestamp,statuscode,digest&collapse=digest"
 
q "5. webxray.org -- every distinct body, 2010 to now" \
  "$CDX?url=webxray.org&fl=timestamp,statuscode,digest,length&collapse=digest"
 
q "6. webxray.org -- UNCOLLAPSED over 2024, where the demo died" \
  "$CDX?url=webxray.org&fl=timestamp,statuscode,digest,length&from=20240101&to=20241231"
 
# Added 2026-09-05 after review: queries 5 and 6 stop in 2024, so the published
# output did not contain the 2026 capture that the "301 to webxray.ai until at
# least 2026-02-05" bound rests on. A bound whose evidence is not in the output
# is an uncited figure, however true it is.
q "7. webxray.org -- UNCOLLAPSED over 2025-2026. This is what bounds the end of
     the webxray.ai redirect: the last capture here still carries the 301
     digest OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU, and the Archive has no capture of
     the placeholder that is served today." \
  "$CDX?url=webxray.org&fl=timestamp,statuscode,digest,length&from=20250101&to=20261231"

Q. Unedited output: scripts/owner_sample.py

Run as python3 scripts/owner_sample.py.

Frame: 32,337 registrable domains (ICANN fold, parent-label lookup).
  webxray                sha256:e53760188e6dc9aa  1,023,079
  tr_entity_map          sha256:c4c3f97dbea6cb1e  4,741,528
  tr_domain_map          sha256:a11bc2580f664544  10,442,377
  tr_domain_summary      sha256:19f7a5a6a839ec87  16,347,575
  disconnect_entities    sha256:93e4f54036de1b39  412,191
  public_suffix_list     sha256:aef8fb81d63232da  10,313
Seed 20260905; 60 draws per list, allocation (24, 12, 12, 12) over prevalence quartiles.

webXray: covers 664 of 32,337 frame domains (2.1%), prevalence mass 57.9%
  Q1: N=  166  prevalence 0.005377..0.578843  mass  96.5%  n=24
  Q2: N=  166  prevalence 0.000390..0.005117  mass   3.3%  n=12
  Q3: N=  166  prevalence 0.000034..0.000390  mass   0.2%  n=12
  Q4: N=  166  prevalence 0.000007..0.000034  mass   0.0%  n=12
Tracker Radar: covers 5,566 of 32,337 frame domains (17.2%), prevalence mass 83.9%
  Q1: N=1,391  prevalence 0.000185..0.578843  mass  99.0%  n=24
  Q2: N=1,392  prevalence 0.000027..0.000185  mass   0.7%  n=12
  Q3: N=1,391  prevalence 0.000007..0.000027  mass   0.2%  n=12
  Q4: N=1,392  prevalence 0.000007..0.000007  mass   0.1%  n=12
Disconnect: covers 2,264 of 32,337 frame domains (7.0%), prevalence mass 79.9%
  Q1: N=  566  prevalence 0.001767..0.450522  mass  96.5%  n=24
  Q2: N=  566  prevalence 0.000192..0.001754  mass   3.1%  n=12
  Q3: N=  566  prevalence 0.000021..0.000185  mass   0.3%  n=12
  Q4: N=  566  prevalence 0.000007..0.000021  mass   0.1%  n=12

Distinct domains to adjudicate: 175 (sum of per-list draws = 180; overlap 5)
Wrote out/owner_sample.json
sample sha256:b9acc0cb20cf7ff3

R. Unedited output: scripts/owner_corrections.py

Run as python3 scripts/owner_corrections.py –rows out/adj_rows.json –out out/adj_rows_final.json.

10 corrections applied to 175 rows, after machine verification of every cited source: demote=1, requote=4, resource=5

twiago.com             requote   quote was re-ordered ('HRB 81984 (Amtsgericht Köln)'); the page reads 'Handelsregisternummer : Amtsgericht Köln HRB 81984'. Claim unchanged.
                       was source: https://www.twiago.com/impressum
                       was quote : twiago GmbH, Charlottenstraße 61, 51149 Köln ... HRB 81984 (Amtsgericht Köln)
                       now source: https://www.twiago.com/impressum

glomex.com             requote   quote had punctuation and a '--' the page does not carry; entity, address and HRB 224542 are all on the page.
                       was source: https://www.glomex.com/de/impressum
                       was quote : glomex GmbH, Medienallee 4, 85774 Unterföhring, Deutschland -- Registergericht AG München, HRB 224542
                       now source: https://www.glomex.com/de/impressum

wrbm.com               requote   quote was a summary of the register page; the three strings are on it.
                       was source: https://find-and-update.company-information.service.gov.uk/company/02883992
                       was quote : Previous name: WILLIAM REED BUSINESS MEDIA LTD (31 Dec 2007 - 09 Feb 2022); current name WILLIAM REED LTD, status Active
                       now source: https://find-and-update.company-information.service.gov.uk/company/02883992

klarna.app             resource  https://klarna.com/ geo-redirects and does not carry the footer; the international landing page does, verbatim.
                       was source: https://klarna.com/
                       was quote : Copyright © 2005-2026 Klarna Bank AB (publ). Headquarters: Stockholm, Sweden.
                       now source: https://www.klarna.com/international/

hearst.com             resource  the cited SEC browse-edgar URL is a form, not a document. hearst.com's own footer names the entity. (data.sec.gov/submissions/CIK0001052747.json also returns name 'HEARST COMMUNICATIONS INC', checked 2026-09-05.)
                       was source: https://www.sec.gov/cgi-bin/browse-edgar?action=getcompany&CIK=0001052747&type=10-K&dateb=&owner=include&count=40
                       was quote : HEARST COMMUNICATIONS INC, CIK 0001052747, 300 West 57th Street, New York, NY 10019
                       now source: https://www.hearst.com/

medallia.com.au        resource  medallia.com.au redirects to www.medallia.com, whose footer carries the entity; citing the sampled domain makes the redirect part of the evidence.
                       was source: https://www.medallia.com/
                       was quote : Copyright © 2026 Medallia, Inc. All rights reserved.
                       now source: https://medallia.com.au/

akamaihd.net           resource  akamaihd.net serves nothing and the Akamai blog 403s every non-browser client. Akamai's own PSL submission is a primary source that the suffix is theirs, and it is a file this study already fetches and hashes.
                       was source: https://www.akamai.com/blog/developers/adding-akamai-shared-domains-to-the-public-suffix-list
                       was quote : akamaihd.net
                       now source: https://publicsuffix.org/list/public_suffix_list.dat

mediaset.es            requote   the quote was openssl's default escaped form (ESPA\C3\91A). Re-quoted from `-nameopt utf8`, which the verifier now passes; the OV certificate is unchanged.
                       was source: tls://mediaset.es:443
                       was quote : O = "GRUPO AUDIOVISUAL MEDIASET ESPA\C3\91A COMUNICACION, SAU", CN = seguro.mediaset.es
                       now source: tls://mediaset.es:443

dnb.com                resource  dnb.com served the page to a plain curl earlier in the run and then began returning a ~5.7 kB challenge to every client, browser included. Citing the Wayback copy keeps the row reproducible; the live page carried the same sentence when first fetched on 2026-09-05.
                       was source: https://www.dnb.com/
                       was quote : © Dun & Bradstreet, Inc. 2000 - 2026. All rights reserved.
                       now source: https://web.archive.org/web/20241002130956/https://www.dnb.com/utility-pages/privacy-policy.html

cnevids.com            demote    Condé Nast's own privacy policy does not name cnevids.com and the domain serves nothing. Tracker Radar's 'Sabin, Bermant & Gould LLP' is the registrant law firm, which is a textbook WHOIS trap, but calling it an error needs a source naming the real owner and there is none.
                       was source: https://player.cnevids.com/
                       was quote : Condé Nast Entertainment
                       now source: None

wrote out/adj_rows_final.json

S. Unedited output: scripts/owner_verdict_fixes.py

Run as python3 scripts/owner_verdict_fixes.py –rows out/adj_rows_final.json –out out/adj_rows_scored.json.

`self-named` retired: 26 (domain, list) verdicts re-scored.

  accessibe.com              disconnect     self-named -> current      'Accessibe' is accessiBe Inc.
  acint.net                  disconnect     self-named -> unknown      row unresolved.
  admarketplace.net          disconnect     self-named -> current      'Admarketplace' is adMarketplace, Inc.
  amazon.de                  disconnect     self-named -> current      'Amazon' names the group operating amazon.de.
  amung.us                   disconnect     self-named -> current      entity 'whos.amung.us'.
  amung.us                   tracker_radar  self-named -> current      entity 'whos.amung.us Inc'.
  amung.us                   webXray        self-named -> current      the company is literally 'whos.amung.us Inc.'
  bilibili.com               disconnect     self-named -> granularity  'Bilibili' is the listed parent; the operator is Shanghai Huandian Information Technology Co., Ltd. Scored as Tracker Radar's 'BiliBili Inc.' was on the same row.
  cdnbasket.net              disconnect     self-named -> unknown      row unresolved.
  contentabc.com             disconnect     self-named -> unknown      row unresolved.
  glomex.com                 disconnect     self-named -> current      'Glomex' is glomex GmbH.
  govx.com                   disconnect     self-named -> unknown      row unresolved.
  govx.com                   tracker_radar  self-named -> unknown      row unresolved.
  histats.com                disconnect     self-named -> current      'Histats' is the product of Wisecode S.r.l.; scored as webXray's 'HiStats' was on the same row, so the two lists are treated alike.
  htplayground.com           disconnect     self-named -> unknown      row unresolved.
  i.ua                       disconnect     self-named -> unknown      row unresolved.
  iqzone.com                 disconnect     self-named -> current      'IQZone' vs IQzone Inc.: same company.
  km0trk.com                 disconnect     self-named -> unknown      row unresolved.
  onecount.net               webXray        self-named -> granularity  'ONEcount' is the product; the company is GCN Publishing, Inc.
  simpli.fi                  disconnect     self-named -> current      as above, entity 'Simpli.fi'.
  simpli.fi                  webXray        self-named -> current      'simpli.fi' is the trading brand of Simplifi Holdings, LLC; the string is a domain but it names the right company.
  spotxchange.com            webXray        self-named -> stale        'Spot X Change' is the pre-acquisition brand; Magnite acquired SpotX in 2021 and the domain is Magnite Streaming's.
  stat-track.com             disconnect     self-named -> unknown      row unresolved.
  trustarc.com               disconnect     self-named -> current      'TrustARC' is TrustArc Inc.
  trustarc.com               webXray        self-named -> current      'TrustArc' is TrustArc Inc.
  yieldlove-ad-serving.net   disconnect     self-named -> current      the entity string is the domain, but it names Yieldlove GmbH, the operator. Counted in the domain-as-name census instead of in the verdict.

Second correction: rows scored on webXray's ownership-tree root rather than its entry.
  addthiscdn.com             webXray        error        -> granularity  scored error on a note that says webXray roots AddThis under Verizon. It does not: webXray's root for addthiscdn.com is 'Oracle', which is the correct owner. The immediate entity 'AddThis' names the brand Oracle acquired in 2016 and shut down in 2023: granularity, not an error.
  tqlkg.com                  webXray        error        -> stale        scored error because webXray's ROOT is 'Here, There & Everywhere', an Australian media group unrelated to US Conversant -- a real defect, but in the tree, not in the entry. The immediate entity 'Conversant Media' is the company's own former name, superseded by Conversant, LLC: stale.

self-named verdicts remaining: 0
wrote out/adj_rows_scored.json

T. Unedited output: scripts/owner_citation_audit.py

Run as python3 scripts/owner_citation_audit.py.

Citation audit of the 175 adjudicated rows
==============================================================================

A row is CITED only if the quoted sentence was found on the cited
source by a machine -- bytes, a browser, or a re-done TLS handshake.
An `unresolved` row makes no ownership claim and enters no rate, so it
needs no citation; it is counted separately rather than as a pass.

  cited (bytes)            132
  no claim (unresolved)     40
  cited (browser)            3
  total                    175

UNCITED rows (each one would be a figure with no checkable source): 0

Rows whose citation only survives because a browser was used, i.e.
the ones a bytes-only audit would wrongly call broken:
   flashtalking.com         curl=FETCHFAIL  browser=OK-WINDOW  https://www.mediaocean.com/press-releases/2025/03/17/innovid-uni
   fontawesome.com          curl=NOTFOUND   browser=OK-WINDOW  https://fontawesome.com/tos
   force.com                curl=NOTFOUND   browser=OK  https://investor.salesforce.com/news/news-details/2022/Salesforc

Rows that passed pass 1 and fail it after the corrections: 0

Source kinds actually cited, over the 135 rows that make a claim:
   HTTP(S) document           118
   TLS certificate subject     17

U. Unedited output: scripts/owner_selfname_census.py

Run as python3 scripts/owner_selfname_census.py.

Entities whose name is a domain rather than a company name
(census over every DOMAIN in each file, not a sample. The maps are keyed
on the lowercased domain, so this counts distinct domains: webXray has
3,224 domain->owner pairs but 3,215 distinct domains, three of them
carrying a trailing slash in the file.)

List              domains   identical   share  label-only   share
webXray             3,215          25    0.8%         937   29.1%
Tracker Radar      38,368         250    0.7%       1,744    4.5%
Disconnect          7,850         250    3.2%       2,155   27.5%

webXray: first 12 identical entries -> 51.la='51La', 56.com='56.com', affec.tv='Affectv', ask.com='Ask.com', clearstream.tv='Clearstream.TV', cross.tv='Cross TV', dictionary.com='Dictionary.com', digitru.st='DigiTrust', drawbrid.ge='Drawbridge', ethn.io='Ethnio', fonts.com='Fonts.com', grade.us='Grade Us'
Tracker Radar: first 12 identical entries -> 1stdibs.com='1stdibs.com', 4icu.org='4icu.org', 7gra.us='7Graus', 83net.jp='83net.jp', about.me='about.me', acloud.guru='A Cloud Guru', adrock.tv='adrock.tv', advanced-people-search.com='Advanced-People-Search.com', adxxx.com='AdXXX.com', affec.tv='Affectv', airportparkingreservations.com='AirportParkingReservations.com', allbookstores.com='AllBookstores.com'
Disconnect: first 12 identical entries -> 1film.to='1film.to', 23trgaaddg.com='23trgaaddg.com', 2leep.com='2leep.com', 360.cn='360.cn', 7ool.net='7ool.net', 8d8.biz='8d8.biz', a4cdn.org='a4cdn.org', aaaacdn.com='Aaaacdn.com', acredo.space='acredo.space', addin1.name='addin1.name', adless.io='adless.io', adnetwork.net='AdNetwork.net'

A name identical to the domain tells a measurement nothing it did not
already have. A name identical to the domain's label usually does -- the
company is called Klaviyo -- so only the first column is a defect, and
the second is printed so the first cannot be inflated by conflating them.

V. Unedited output: scripts/owner_random_sample.py — every figure, and the 175-row table

Run as python3 scripts/owner_random_sample.py –sample out/owner_sample.json –rows out/adj_rows_scored.json –table –wiki.

==============================================================================
Per-list ownership accuracy from a stratified random sample
==============================================================================

Frame: 32,337 registrable domains (Tracker Radar domain_summary.json,
ICANN-section PSL fold, parent-label lookup). Seed 20260905, 60 draws per list, allocation (24, 12, 12, 12)
over prevalence quartiles of each list's own coverage. Adjudicated 2026-09-05.
Input snapshots: disconnect_entities=93e4f54036de1b39, public_suffix_list=aef8fb81d63232da, tr_domain_map=a11bc2580f664544, tr_domain_summary=19f7a5a6a839ec87, tr_entity_map=c4c3f97dbea6cb1e, webxray=e53760188e6dc9aa

--- A. What the sample could and could not settle ---------------------

Rows are excluded from every accuracy rate below when the primary-source bar
was not met. In a random sample that is a large share, and it rises toward
the tail, so it is reported first and per quartile rather than buried.

List            drawn  unresolved  eligible   per quartile (eligible/drawn)
webXray            60          11        49   Q1 20/24  Q2 10/12  Q3 7/12  Q4 12/12
Tracker Radar      60          13        47   Q1 17/24  Q2 9/12  Q3 11/12  Q4 10/12
Disconnect         60          18        42   Q1 20/24  Q2 7/12  Q3 7/12  Q4 8/12

--- B. Per-list verdict rates, with 95% bootstrap intervals -----------

Denominator: the entries of that list which the sample could settle and which
make an ownership claim (the 'eligible' column above), scaled to the list's
whole coverage by stratum weights. 'domain-level' weights every domain the
list covers equally; 'encounter-weighted' weights by Tracker Radar prevalence,
i.e. how often a crawl actually meets the domain.

webXray  (covers 664 of 32,337 frame domains = 2.1%; n eligible = 49)
  verdict         domain-level           95% CI    encounter-wtd           95% CI
  current                69.9%  [ 55.5%, 83.1%]            93.9%  [ 80.9%, 98.8%]
  granularity            10.2%  [  2.1%, 20.9%]             0.2%  [  0.0%,  0.8%]
  stale                  19.8%  [  9.2%, 32.3%]             5.9%  [  1.0%, 19.1%]
  error                   0.0%  [  0.0%,  0.0%]             0.0%  [  0.0%,  0.0%]
  zero cells (error): the bootstrap interval on a cell with no observations is [0,0] and asserts nothing.
  The usable statement is the rule-of-three upper bound: with 49 eligible rows and 0 seen, the true rate is below 6.1% at 95% confidence.
  current+gran.          80.2%  [ 67.7%, 90.8%]            94.1%  [ 81.4%, 99.0%]
  stale+error            19.8%  [  9.0%, 32.6%]             5.9%  [  1.1%, 19.4%]

Tracker Radar  (covers 5,566 of 32,337 frame domains = 17.2%; n eligible = 47)
  verdict         domain-level           95% CI    encounter-wtd           95% CI
  current                73.7%  [ 60.8%, 85.8%]            68.6%  [ 29.3%, 97.0%]
  granularity             2.8%  [  0.0%,  8.3%]             0.1%  [  0.0%,  0.4%]
  stale                  22.1%  [ 10.5%, 35.1%]            26.8%  [  0.4%, 64.6%]
  error                   1.5%  [  0.0%,  4.4%]             4.5%  [  0.0%, 19.3%]
  current+gran.          76.5%  [ 63.5%, 88.0%]            68.7%  [ 29.2%, 97.7%]
  stale+error            23.5%  [ 11.7%, 36.1%]            31.3%  [  2.9%, 71.2%]

Disconnect  (covers 2,264 of 32,337 frame domains = 7.0%; n eligible = 42)
  verdict         domain-level           95% CI    encounter-wtd           95% CI
  current                94.4%  [ 86.9%,100.0%]            83.1%  [ 53.7%,100.0%]
  granularity             4.4%  [  0.0%, 11.2%]            16.5%  [  0.0%, 45.8%]
  stale                   1.2%  [  0.0%,  3.8%]             0.4%  [  0.0%,  1.5%]
  error                   0.0%  [  0.0%,  0.0%]             0.0%  [  0.0%,  0.0%]
  zero cells (error): the bootstrap interval on a cell with no observations is [0,0] and asserts nothing.
  The usable statement is the rule-of-three upper bound: with 42 eligible rows and 0 seen, the true rate is below 7.1% at 95% confidence.
  current+gran.          98.8%  [ 96.2%,100.0%]            99.6%  [ 98.5%,100.0%]
  stale+error             1.2%  [  0.0%,  3.8%]             0.4%  [  0.0%,  1.5%]

--- C. Coverage is not estimated: it is counted --------------------

'absent' needs no sample. Each list either has an entry for a frame domain or
it does not, and both can be counted over all 32,337 of them.
  List            domains named  of frame   prevalence-weighted
  webXray                   664      2.1%                 57.9%
  Tracker Radar           5,566     17.2%                 83.9%
  Disconnect              2,264      7.0%                 79.9%

--- C2. Concentration: how much of the encounter-weighted estimate is one row ---

Share of the encounter-weighted estimate contributed by each list's single
heaviest eligible row, and what the 'current' rate becomes if that one row's
verdict is flipped to stale. This is a sensitivity check, not a result: the
flipped figure is what the estimate WOULD be, not a claim that it is.

  webXray        heaviest row gstatic.com              verdict current     carries  39.4% of the estimate
                   encounter-weighted 'current'  93.9%  ->   54.4% if that one row were stale
                   top three rows together carry  53.1%
  Tracker Radar  heaviest row omtrdc.net               verdict current     carries  24.9% of the estimate
                   encounter-weighted 'current'  68.6%  ->   43.7% if that one row were stale
                   top three rows together carry  64.9%
  Disconnect     heaviest row id5-sync.com             verdict current     carries  16.7% of the estimate
                   encounter-weighted 'current'  83.1%  ->   66.4% if that one row were stale
                   top three rows together carry  46.0%

--- D. Verdicts on domains drawn for another list (NOT in any estimate) ---

Each drawn domain was adjudicated once and the verdict recorded for all three
lists. Only a list's own sample enters its estimate above; these are the rest,
printed so the discarded observations are visible rather than silently dropped.
  webXray        absent=96  current=12  granularity=1  stale=5  unknown=1
  Tracker Radar  absent=18  current=58  error=1  granularity=6  stale=16  unknown=16
  Disconnect     absent=49  current=44  granularity=8  unknown=14

--- E. Residue: every row excluded from an estimate --------------------

  webXray        Q1 adgrx.com                        unknown     unresolved Strong secondary-source consensus (Netify, press coverage) that adgrx.com is S
  webXray        Q1 company-target.com               unknown     unresolved Domain has live DNS (CloudFront IP range) but TLS handshake fails and no page 
  webXray        Q1 1rx.io                           unknown     unresolved Nexxen's own privacy-policy pages (nexxen.com/services-privacy-policy/, nexxen
  webXray        Q1 agkn.com                         unknown     unresolved Secondary reporting (not fetched as primary) traces a chain Aggregate Knowledg
  webXray        Q2 yceml.net                        unknown     unresolved Domain itself had no TLS handshake at probe time. Conversant LLC (webXray/Trac
  webXray        Q2 blogblog.com                     unknown     unresolved Domain 404s and only serves a DV *.blogger.com wildcard cert (Google Trust Ser
  webXray        Q3 awltovhc.com                     unknown     unresolved Long-recognized Conversant/ValueClick-style cookie-sync domain. RDAP shows an 
  webXray        Q3 mmstat.com                       unknown     unresolved Registrar is Alibaba Cloud Computing (Beijing) Co., Ltd. with ns3/4/5.aliyun.c
  webXray        Q3 lduhtrp.net                      unknown     unresolved Same Conversant/ValueClick-style cookie-sync domain family as awltovhc.com, wi
  webXray        Q3 collective-media.net             unknown     unresolved 'Collective, Inc.' (the ad network) split its ad-network division into 'Compas
  webXray        Q3 wishabi.com                      unknown     unresolved wishabi.com's TLS handshake serves Flipp's certificate (CN=flipp.com) and Flip
  Tracker Radar  Q1 app-us1.com                      unknown     unresolved app-us1.com serves no browsable page (CODE 000); ActiveCampaign's own fetched 
  Tracker Radar  Q1 travelpayouts.com                unknown     unresolved Homepage confirms the operating brand 'Travelpayouts' but not the legal entity
  Tracker Radar  Q1 acint.net                        unknown     unresolved Site self-describes as 'Acint (Artificial Computation Intelligence)' with only
  Tracker Radar  Q1 cdnbasket.net                    unknown     unresolved bounceexchange.com 302-redirects to wunderkind.co today, and Wunderkind's fetc
  Tracker Radar  Q1 spot.im                          unknown     unresolved OpenWeb's own privacy policy confirms 'Open Web Technologies Ltd.' is a real, 
  Tracker Radar  Q1 cnevids.com                      unknown     unresolved cnevids.com itself no longer resolves, but its own player.cnevids.com subdomai
  Tracker Radar  Q1 marphezis.com                    unknown     unresolved Tracker Radar's claim (Online Media Solutions Ltd. dba Brightcom) is plausible
  Tracker Radar  Q2 hqseek.com                       unknown     unresolved hqseek.com redirects to the adult site hqporn.pics; WebFetch of both was refus
  Tracker Radar  Q2 contentabc.com                   unknown     unresolved Disconnect's entity 'ContentABC' is a trivial capitalisation of the domain lab
  Tracker Radar  Q2 trustpilot.net                   unknown     unresolved Separately confirmed via https://corporate.trustpilot.com/legal/for-reviewers/
  Tracker Radar  Q3 cratecamera.com                  unknown     unresolved pgl.yoyo.org's blocklist tags cratecamera.com's category as 'admiral', consist
  Tracker Radar  Q4 cjponyparts.com                  unknown     unresolved 'CJ Pony Parts, Inc.' is a real, independent Mustang-parts retailer (not a sel
  Tracker Radar  Q4 cedscdn.it                       unknown     unresolved Third-party WHOIS aggregators attribute registration to CED Digital & Servizi 
  Disconnect     Q1 govx.com                         unknown     unresolved GOVX is a real San Diego company per secondary sources (BBB listing, LinkedIn)
  Disconnect     Q1 cdnbasket.net                    unknown     unresolved bounceexchange.com 302-redirects to wunderkind.co today, and Wunderkind's fetc
  Disconnect     Q1 agkn.com                         unknown     unresolved Secondary reporting (not fetched as primary) traces a chain Aggregate Knowledg
  Disconnect     Q1 opti-digital.com                 unknown     unresolved opti-digital.com fails to resolve at all (curl: could not resolve host); a liv
  Disconnect     Q2 at-o.net                         unknown     unresolved at-o.net has no DNS/TLS response; AT Internet's (now Piano's) own data-protect
  Disconnect     Q2 mapixl.com                       unknown     unresolved Searches for a link between Disconnect's claimed 'MarketingArchitects' (a Minn
  Disconnect     Q2 ksearchnet.com                   unknown     unresolved Klevu's own SDK README (klevultd GitHub org, now branded Athos Commerce per kl
  Disconnect     Q2 gssprt.jp                        unknown     unresolved webXray, Tracker Radar and Disconnect all agree on Geniee, and third-party WHO
  Disconnect     Q2 kameleoon.io                     unknown     unresolved Kameleoon SAS's own legal notice confirms it operates kameleoon.com/app.kamele
  Disconnect     Q3 stat-track.com                   unknown     unresolved Disconnect's 'StackTrack' is a near-verbatim mangling of the domain label 'sta
  Disconnect     Q3 sa-as.com                        unknown     unresolved Domain does not resolve over TLS and no primary source (newsroom/filing/legal-
  Disconnect     Q3 stripst.com                      unknown     unresolved stripst.com returned HTTP 522 on every fetch attempt (both root and a guessed 
  Disconnect     Q3 htplayground.com                 unknown     unresolved Disconnect's entry is literally the string 'htplayground.com', identical to th
  Disconnect     Q3 pages02.net                      unknown     unresolved Leads (non-primary) indicate pages0X.net domains are Silverpop/IBM Watson Mark
  Disconnect     Q4 globo.com                        unknown     unresolved Public secondary sources describe Globo Comunicação e Participações S.A. (form
  Disconnect     Q4 offshoregeology.com              unknown     unresolved Disconnect's 'Admiral' claim could not be verified against a primary source; a
  Disconnect     Q4 i.ua                             unknown     unresolved RDAP lists registrant 'Digital Ventures LLC' and registrar 'Internet Invest LL
  Disconnect     Q4 km0trk.com                       unknown     unresolved Disconnect's entry name is simply the domain itself (km0trk.com), which is sel

--- F. The adjudication table ---------------------------------------

^ Domain ^ Prev. ^ Owner today ^ When it changed ^ webXray ^ Tracker Radar ^ Disconnect ^ Primary source ^
| ''gstatic.com'' | 0.40160 | Google LLC | n/a -- independent, Google-operated since inception | current | current | current | [[https://docs.cloud.google.com/docs/get-started/required-domains|parent-site]] |
| ''id5-sync.com'' | 0.09586 | ID5 Technology Ltd | n/a -- independent | current | current | current | [[https://id5.io/trust/privacy-policy|legal-doc]] |
| ''crwdcntrl.net'' | 0.09475 | Epsilon Data Management, LLC (operating under the Lotame name; a Publicis Groupe company) | merged 2025-10-01 -- Lotame Solutions, Inc. merged into Epsilon Data Management, LLC; Publicis Groupe announced its agreement to acquire Lotame on 2025-03-06 | current | stale | granularity | [[https://www.lotame.com/privacy/services-privacy-notice/|legal-doc]] |
| ''liadm.com'' | 0.08019 | LiveIntent, Inc. (a Zeta Global company) | closed 2024-10-21 -- Zeta Global completed its acquisition of LiveIntent (announced 2024-10-08) | current | current | granularity | [[https://privacy.liadm.com/api-guide|legal-doc]] |
| ''smartadserver.com'' | 0.07333 | Equativ SAS (RCS Paris 487 613 481) | renamed 2023 -- Smart Adserver / Smartadserver S.A.S. became Equativ after its merger with DAX | stale | stale | current | [[https://www.equativ.com/legal-mentions|legal-doc]] |
| ''lijit.com'' | 0.06419 | Sovrn Holdings, Inc. | n/a -- Sovrn Holdings, Inc. operates lijit.com today | current | current | current | [[https://lijit.com/|legal-doc]] |
| ''bidr.io'' | 0.05861 | Beeswax Inc. (a FreeWheel / Comcast company) | closed ~2021-01 -- FreeWheel (Comcast) agreed 2020-12-17 to acquire Beeswax | current | current | granularity | [[https://www.beeswax.com/privacy/|legal-doc]] |
| ''1rx.io'' | 0.05313 | //unresolved// | UNRESOLVED -- domain is dead (no TLS handshake, no HTTP response) and no primary source fetched this session ties 1rx.io itself to RhythmOne or Nexxen | unknown | unknown | unknown | //none// |
| ''simpli.fi'' | 0.05248 | Simplifi Holdings, LLC (GTCR-backed, privately held) | n/a -- privately held, longstanding GTCR portfolio company | current | granularity | current | [[https://simpli.fi/website-privacy-policy|legal-doc]] |
| ''gumgum.com'' | 0.05151 | GumGum, Inc. | n/a -- independent | current | current | current | [[https://gumgum.com/terms-and-policies/privacy-policy|legal-doc]] |
| ''quantserve.com'' | 0.04428 | Quantcast Corporation (Quantcast) | n/a -- independent | current | current | current | [[https://legal.quantcast.com/|legal-doc]] |
| ''criteo.net'' | 0.04208 | Criteo Corp. (Criteo) | n/a -- independent | current | current | current | [[https://www.criteo.com/privacy/|legal-doc]] |
| ''klaviyo.com'' | 0.04172 | Klaviyo, Inc. | n/a -- independent | absent | current | current | [[https://www.klaviyo.com/de/|legal-doc]] |
| ''loopme.me'' | 0.04039 | LoopMe Ltd (LoopMe) | n/a -- independent | current | error | current | [[https://legal.loopme.com/privacy-center|legal-doc]] |
| ''fontawesome.com'' | 0.03873 | Fonticons, Inc. | n/a -- independent | current | current | absent | [[https://fontawesome.com/tos|legal-doc]] |
| ''agkn.com'' | 0.03580 | //unresolved// | UNRESOLVED -- domain is dead today (NXDOMAIN/no TLS handshake) though RDAP shows it remains registered (not expired, locked, registrar GoDaddy Corporate Domains) with no disclosed registrant org; could not reach any current primary source naming an operator | unknown | unknown | unknown | //none// |
| ''wp.com'' | 0.02694 | Automattic, Inc. (WordPress.com) | n/a -- independent, operated by Automattic since founding (2005) | current | current | current | [[https://automattic.com/|parent-site]] |
| ''eyeota.net'' | 0.02519 | Eyeota, a Dun & Bradstreet company | acquired by Dun & Bradstreet, announced 2021-11-04 (Eyeota retains its own brand as a D&B subsidiary) | current | current | granularity | [[https://www.eyeota.com/blog/eyeota-is-now-a-dun-bradstreet-company|newsroom]] |
| ''newrelic.com'' | 0.02217 | New Relic, Inc. | n/a -- independent, unchanged | current | current | current | [[https://newrelic.com/termsandconditions/terms|legal-doc]] |
| ''emxdgt.com'' | 0.01923 | Cadent, LLC | 2023-05 -- Cadent acquired EMX's SSP technology in a bankruptcy auction after EMX's parent Big Village collapsed | stale | stale | current | [[https://www.cadent.com/terms-of-use|legal-doc]] |
| ''go-mpulse.net'' | 0.01818 | Akamai Technologies, Inc. | 2017-04-07 -- Akamai completed its acquisition of SOASTA | stale | current | current | [[https://www.prnewswire.com/news-releases/akamai-completes-acquisition-of-soasta-300436365.html|newsroom]] |
| ''hs-analytics.net'' | 0.01764 | HubSpot, Inc. | n/a -- independent, unchanged | current | current | current | [[https://knowledge.hubspot.com/reports/how-do-i-know-if-my-hubspot-tracking-code-is-working|parent-site]] |
| ''hs-scripts.com'' | 0.01716 | HubSpot, Inc. | n/a -- independent, unchanged | current | current | current | [[https://developers.hubspot.com/docs/api-reference/latest/account/settings/tracking-code/overview|parent-site]] |
| ''omtrdc.net'' | 0.01662 | Adobe Inc. | n/a -- Adobe acquired Omniture in 2009; domain retained since | current | current | current | [[https://experienceleague.adobe.com/en/docs/analytics-learn/tutorials/implementation/implementation-basics/how-to-identify-your-analytics-tracking-server-and-report-suites|parent-site]] |
| ''primis.tech'' | 0.01623 | McCann Disciplines Ltd. (trading as Primis; part of Universal McCann / IPG) | n/a -- same operating entity since Sekindo's 2018 rebrand as Primis (McCann acquired Sekindo in 2012) | absent | current | current | [[https://www.primis.tech/wp-content/uploads/2020/01/Primis-Privacy-Policy.pdf|legal-doc]] |
| ''flashtalking.com'' | 0.01412 | Mediaocean LLC (brand unified as Innovid since March 2025; domain now redirects to innovid.com) | 2021-07 Mediaocean acquired Flashtalking; 2025-03-17 brand merged into unified 'Innovid' name | stale | current | current | [[https://www.mediaocean.com/press-releases/2025/03/17/innovid-unified-brand-global-ad-tech|newsroom]] |
| ''ctnsnet.com'' | 0.01392 | Crimtan Holdings Limited | n/a -- independent, unchanged | current | current | current | [[https://find-and-update.company-information.service.gov.uk/company/07810698|register]] |
| ''sharethis.com'' | 0.01349 | Predactiv, Inc. (ShareThis) | n/a -- ShareThis currently operates as a division of Predactiv, Inc.; the date this structure began was not sourced | granularity | granularity | current | [[https://sharethis.com/privacy/|legal-doc]] |
| ''mountain.com'' | 0.01288 | MNTN, Inc. | renamed 2022-06-14 (MNTN Digital, Inc. -> MNTN, Inc.), per SEC EDGAR | absent | stale | current | [[https://data.sec.gov/submissions/CIK0001891027.json|filing]] |
| ''spot.im'' | 0.01101 | //unresolved// | UNRESOLVED -- spot.im is dead (TLS handshake failure on both spot.im and www.spot.im, which also 502s); no primary source found tying the domain itself to a current operator | absent | unknown | unknown | [[https://www.openweb.com/legal-and-privacy/privacy/|legal-doc]] |
| ''cloudfront.net'' | 0.01081 | Amazon Web Services, Inc. (Amazon) | n/a -- Amazon since inception | current | granularity | current | [[https://aws.amazon.com/privacy/|legal-doc]] |
| ''hotjar.io'' | 0.01015 | Contentsquare | UNRESOLVED -- exact Hotjar acquisition date not sourced this session; current state confirmed via redirect + copyright | stale | stale | current | [[https://contentsquare.com/hotjar/?utm_campaign=exp__hj_hp_redirection|parent-site]] |
| ''stripe.com'' | 0.00967 | Stripe, LLC | UNRESOLVED -- exact date of the Stripe, Inc. -> Stripe, LLC change not sourced; current name confirmed via site footer + EV TLS cert | absent | stale | current | [[https://stripe.com/de-ch/legal/consumer|legal-doc]] |
| ''azure.com'' | 0.00960 | Microsoft Corporation | n/a -- Microsoft since inception | absent | current | current | [[tls://azure.microsoft.com:443|register]] |
| ''company-target.com'' | 0.00897 | //unresolved// | UNRESOLVED -- domain resolves to CloudFront-range IPs but TLS handshake fails (alert 552) and HTTP returns 403/no response; no content or primary source reachable | unknown | unknown | unknown | //none// |
| ''paypal.com'' | 0.00751 | PayPal, Inc. | n/a -- independent, no ownership change found | absent | current | current | [[https://www.paypal.com/us/legalhub/paypal/privacy-full|legal-doc]] |
| ''adgrx.com'' | 0.00681 | //unresolved// | UNRESOLVED -- news coverage says AdGear Technologies (acquired by Samsung Electronics Canada, 2016) operates adgrx.com as part of Samsung Ads, but no fetch reached a primary source naming adgrx.com: samsungads.ca/en/privacy/ has an expired TLS certificate, help.samsungads.com/docs/samsung-ad-manager-privacy-notice failed TLS handshake, and samsung.com's general ads privacy page names no subsidiary or domain. adgrx.com itself has no TLS handshake and no RDAP. | unknown | unknown | unknown | //none// |
| ''marphezis.com'' | 0.00666 | //unresolved// | UNRESOLVED -- domain does not resolve (no TLS handshake, no RDAP, HTTP code 000); Brightcom's own homepage and privacy policy (brightcom.com) make no mention of marphezis.com or any operated-domains list. | absent | unknown | absent | //none// |
| ''iqzone.com'' | 0.00663 | IQzone Inc. | n/a -- independent, live and self-operated; no ownership change found | absent | current | current | [[https://iqzone.com/|legal-doc]] |
| ''histats.com'' | 0.00650 | Wisecode S.r.l. Unipersonale (Histats) | n/a -- Wisecode operates Histats.com directly; no ownership change found | current | current | current | [[https://www.histats.com/|legal-doc]] |
| ''adition.com'' | 0.00612 | Virtual Minds GmbH (Adition) | ADITION technologies AG merged into the Virtual Minds group (~2013); Virtual Minds AG converted its legal form to Virtual Minds GmbH (name/legal-form change, ~2021); Adition is now marketed as a Virtual Minds GmbH product | stale | stale | current | [[https://virtualminds.com/adition/|parent-site]] |
| ''trustarc.com'' | 0.00555 | TrustArc Inc. | n/a -- independent, live and self-operated; no ownership change found | current | current | current | [[https://trustarc.com/|legal-doc]] |
| ''spotxchange.com'' | 0.00538 | Magnite, Inc. (Magnite Streaming, formerly SpotX/SpotXchange) | Magnite acquired SpotX from RTL Group, deal announced 2021-02-04 and closed 2021-04-30; the SpotX brand was itself retired into 'Magnite Streaming' effective 2023-10-02 | stale | stale | current | [[https://www.sec.gov/Archives/edgar/data/1595974/000138713121001803/ex99-1.htm|filing]] |
| ''akamaihd.net'' | 0.00460 | Akamai Technologies, Inc. | n/a -- Akamai's own shared CDN domain since inception; no ownership change found | current | current | absent | [[https://publicsuffix.org/list/public_suffix_list.dat|newsroom]] |
| ''forter.com'' | 0.00419 | Forter Ltd. (Israel; affiliates include Forter, Inc. — US, Forter Solutions UK Ltd., Forter Pte Ltd.) | n/a -- independent | absent | current | current | [[https://www.forter.com/privacy-policy/|legal-doc]] |
| ''zoominfo.com'' | 0.00405 | ZoomInfo Technologies LLC (ZoomInfo) | n/a -- current operating entity per live privacy policy; 'Zoom Information, Inc.' was a company ZoomInfo acquired in Feb 2019, since folded into the ZoomInfo corporate structure | absent | stale | current | [[https://www.zoominfo.com/privacy-policy|legal-doc]] |
| ''braze.com'' | 0.00353 | Braze, Inc. | n/a -- independent, publicly traded (NASDAQ: BRZE) | current | current | current | [[https://www.braze.com/privacy|legal-doc]] |
| ''app-us1.com'' | 0.00351 | //unresolved// | UNRESOLVED -- could not fetch a primary source naming the operator of this specific domain | absent | unknown | unknown | //none// |
| ''govx.com'' | 0.00330 | //unresolved// | UNRESOLVED -- every fetch of govx.com returned only the homepage title, no legal-entity document reached | absent | unknown | unknown | //none// |
| ''visualstudio.com'' | 0.00325 | Microsoft Corporation | n/a -- Microsoft has always operated this domain (Visual Studio product site) | absent | current | current | [[tls://visualstudio.com:443|register]] |
| ''cdnbasket.net'' | 0.00305 | //unresolved// | UNRESOLVED -- domain is dead (no TLS handshake, CODE 000); only a third-party WHOIS aggregator ties it historically to Bounce Exchange, not a primary source | absent | unknown | unknown | //none// |
| ''elfsight.com'' | 0.00303 | Elfsight, SL | n/a -- current operator per live Terms of Service and About page | absent | error | current | [[https://elfsight.com/terms-of-service/|legal-doc]] |
| ''ispot.tv'' | 0.00293 | iSpot.tv, Inc. | n/a -- independent | absent | current | current | [[https://www.ispot.tv/privacy|legal-doc]] |
| ''reson8.com'' | 0.00239 | Resonate Networks, Inc. (Resonate) | n/a -- current, per live privacy policy naming reson8.com URLs as its own opt-out/tracking infrastructure | current | current | current | [[https://www.resonate.com/privacy-policy/|legal-doc]] |
| ''opti-digital.com'' | 0.00211 | //unresolved// | UNRESOLVED -- domain does not resolve (DNS failure, no TLS handshake) as of 2026-09-05 | absent | unknown | unknown | [[https://optidigital.com/legal-notice/|legal-doc]] |
| ''nofraud.com'' | 0.00205 | Wyllo LLC (rebranded from NoFraud) | rebranded NoFraud -> Wyllo; exact rebrand date UNRESOLVED (current privacy policy dated 2026-03-19) | absent | stale | stale | [[https://wyllo.ai/privacy/|legal-doc]] |
| ''zopim.com'' | 0.00200 | Zendesk, Inc. | acquired by Zendesk 2014-04-10 | current | current | current | [[https://www.zendesk.com/company/press/zendesk-acquires-live-chat-leader-zopim/|newsroom]] |
| ''mparticle.com'' | 0.00192 | mParticle, Inc. (a Rokt company, post-merger) | merged into Rokt, announced 2025-01-16 (~US$300M deal) | absent | current | granularity | [[https://www.mparticle.com/news/rokt-and-mparticle-merge/|newsroom]] |
| ''disquscdn.com'' | 0.00185 | Disqus, Inc. (a Zeta Global affiliate) | Disqus acquired by Zeta Global 2017-12-05 | current | current | current | [[https://help.disqus.com/en/articles/1717103-disqus-privacy-policy|legal-doc]] |
| ''brightcove.net'' | 0.00175 | Brightcove, Inc. | n/a -- independent, publicly traded (NASDAQ: BCOV) | current | current | current | [[https://www.brightcove.com/en/legal/privacy-policy/|legal-doc]] |
| ''squarecdn.com'' | 0.00153 | Block, Inc. | Square, Inc. renamed to Block, Inc. 2021-12-10 | absent | current | absent | [[https://squareup.com/us/en/legal/general/privacy|legal-doc]] |
| ''sendtonews.com'' | 0.00144 | Minute Media (via its STN Video subsidiary/brand, formerly SendtoNews) | acquired by Minute Media, announced 2024-01 (~US$150M, per STN Video's own archived press release) | absent | absent | current | [[https://web.archive.org/web/20240718175821/https://www.stnvideo.com/press/minute-media-acquires-stn-video/|newsroom]] |
| ''amung.us'' | 0.00143 | whos.amung.us Inc. | n/a -- independent | current | current | current | [[https://whos.amung.us/legal/terms/|legal-doc]] |
| ''ksearchnet.com'' | 0.00129 | //unresolved// | UNRESOLVED -- no qualifying primary source found | absent | absent | unknown | [[https://github.com/klevultd/frontend-sdk/blob/master/packages/klevu-core/README.md|other (non-qualifying: SDK docs on GitHub, not a newsroom/filing/legal-doc/register/parent-site)]] |
| ''everestjs.net'' | 0.00121 | Adobe Inc. | n/a -- long-standing Adobe Advertising infrastructure domain | current | current | current | [[https://experienceleague.adobe.com/en/docs/id-service/using/reference/csp|parent-site]] |
| ''kameleoon.io'' | 0.00108 | //unresolved// | UNRESOLVED -- domain is dead (no TLS handshake, no HTTP response) and no fetched source names kameleoon.io specifically | absent | absent | unknown | [[https://www.kameleoon.com/legal-notice|legal-doc]] |
| ''aralego.com'' | 0.00105 | ucfunnel | n/a -- ucfunnel operates aralego.com as its publisher/buyer dashboard domain | absent | current | current | [[https://dashboard.aralego.com/|legal-doc]] |
| ''govdelivery.com'' | 0.00105 | Granicus, LLC | merged 2016-10-25 (GovDelivery merged with Granicus, majority-backed by Vista Equity Partners) | granularity | current | absent | [[https://granicus.com/blog/granicus-govdelivery-announce-merger/|newsroom]] |
| ''cookiefirst.com'' | 0.00104 | Digital Data Solutions B.V. | n/a -- long-standing operator | absent | current | absent | [[https://cookiefirst.com/privacy-policy/|legal-doc]] |
| ''gssprt.jp'' | 0.00101 | //unresolved// | UNRESOLVED -- domain unreachable in probe (no TLS handshake, no RDAP) and no fetched Geniee source names gssprt.jp | unknown | unknown | unknown | [[https://en.geniee.co.jp/privacy/|legal-doc]] |
| ''researchnow.com'' | 0.00097 | Dynata, LLC | renamed 2019-01-15 (Research Now SSI rebranded as Dynata); ownership itself changed again 2024-07-02 when lienholders took 100% equity in a court-approved restructuring | current | stale | current | [[https://www.dynata.com/why-dynata/about-dynata/press/research-now-and-ssi-merger-successfully-completed/|newsroom]] |
| ''vidazoo.com'' | 0.00078 | Perion Network Ltd. | acquired 2021-10-04 | absent | stale | current | [[https://www.sec.gov/Archives/edgar/data/1338940/000117891321003077/exhibit_99-1.htm|filing]] |
| ''tmdb.org'' | 0.00075 | TiVo Platform Technologies LLC (a subsidiary of Xperi Inc.) | changed -- Fanhattan LLC acquired TMDB circa 2016; exact date of the subsequent transition to TiVo Platform Technologies LLC / Xperi Inc. not verified this session | absent | stale | absent | [[https://www.themoviedb.org/terms-of-use|legal-doc]] |
| ''tns-counter.ru'' | 0.00071 | AO ADFACT / JSC ADFACT (Cyrillic АО «ЭДФАКТ»), a subsidiary of AO Mediascope | n/a -- ADFACT has run under the Mediascope brand since Mediascope's 2017 rebrand from TNS Russia | current | current | granularity | [[https://www.mediascope.net/about/|parent-site]] |
| ''owneriq.net'' | 0.00067 | Inmar, Inc. | acquired 2019-10-22 | stale | current | current | [[https://www.globenewswire.com/news-release/2019/10/22/1933083/0/en/Inmar-Acquires-ownerIQ-Adding-A-Critical-Data-and-Media-Solution-to-Inmar-s-Newly-Launched-Innovator-Ecosystem.html|newsroom]] |
| ''acint.net'' | 0.00065 | //unresolved// | UNRESOLVED -- no primary source (company filing, legal doc with a real legal name, or parent site) identifies an operator; the only registrant lead is an individual's WHOIS record, which is not an admissible primary source | absent | unknown | unknown | [[https://acint.net/|legal-doc]] |
| ''force.com'' | 0.00064 | Salesforce, Inc. | n/a -- current; salesforce.com, inc. formally renamed to Salesforce, Inc. effective 2022-04-04 | absent | stale | current | [[https://investor.salesforce.com/news/news-details/2022/Salesforce-Changes-Legal-Name-to-Salesforce-Inc/default.aspx|newsroom]] |
| ''yceml.net'' | 0.00062 | //unresolved// | UNRESOLVED -- structural evidence (conversantmedia.com now 301-redirects to www.epsilon.com, and its /legal/privacy path redirects to legal.epsilon.com) points to Conversant now sitting under Epsilon/Publicis Groupe, but no fetched page carried on-page text naming that relationship, so it does not clear the quote bar | unknown | unknown | unknown | [[https://www.conversantmedia.com/|parent-site]] |
| ''conviva.com'' | 0.00049 | Conviva | n/a -- independent, current | current | current | current | [[https://www.conviva.ai/|legal-doc]] |
| ''travelpayouts.com'' | 0.00049 | //unresolved// | UNRESOLVED -- privacy-policy/terms pages 403'd or 404'd on every URL tried this session; only the homepage was fetchable | absent | unknown | absent | [[https://www.travelpayouts.com/|legal-doc]] |
| ''newsmemory.com'' | 0.00044 | Tecnavia | n/a -- independent, current | absent | current | absent | [[https://www.tecnavia.com/about-us|newsroom]] |
| ''solarwinds.com'' | 0.00043 | SolarWinds Worldwide, LLC (operating entity); ultimate parent Turn/River Capital | 2025-04-16 -- Turn/River Capital completed take-private acquisition | stale | current | current | [[https://www.solarwinds.com/company/newsroom/press-releases/turnriver-completes-acquisition-of-solarwinds|newsroom]] |
| ''blogblog.com'' | 0.00041 | //unresolved// | UNRESOLVED -- no primary source names this specific domain | unknown | unknown | absent | //none// |
| ''blogspot.com'' | 0.00034 | Google LLC (Blogger; EEA/Switzerland: Google Ireland Limited) | n/a -- long-standing Google/Blogger property | current | current | current | [[https://policies.google.com/privacy|legal-doc]] |
| ''snapengage.com'' | 0.00034 | SnapEngage, LLC (subsidiary of TeamSupport LLC) | 2021-05-20 -- TeamSupport acquired SnapEngage (per public reporting); ownership confirmed current via SnapEngage's own privacy policy | absent | stale | current | [[https://snapengage.com/privacy-policy|legal-doc]] |
| ''yieldlove-ad-serving.net'' | 0.00034 | Yieldlove GmbH (majority-owned by Ströer SE & Co. KGaA) | 2017-10-04 -- Ströer acquired a majority shareholding in Yieldlove GmbH | absent | current | current | [[https://www.stroeer.de/en/newsroom/press/expansion-of-technological-platform-marketing-stroeer-acquires-programmatic-platform-and-header-bidding-specialists-yieldlove/|newsroom]] |
| ''ibb.co'' | 0.00029 | ImgBB | n/a -- independent, brand-operated service | absent | current | absent | [[https://imgbb.com/tos|legal-doc]] |
| ''at-o.net'' | 0.00027 | //unresolved// | UNRESOLVED -- domain does not resolve; no operator identifiable from a primary source | absent | absent | unknown | //none// |
| ''cnevids.com'' | 0.00026 | //unresolved// | UNRESOLVED -- no primary source names the owner | absent | unknown | absent | //none// |
| ''pushnami.com'' | 0.00024 | Pushnami, LLC | n/a -- independent, no ownership change found | absent | current | current | [[https://pushnami.com/privacy-policy/|legal-doc]] |
| ''mapixl.com'' | 0.00022 | //unresolved// | UNRESOLVED -- site returns Cloudflare 403, no TLS org identity, no RDAP/registrant data, and no primary source ties any company to this domain | absent | absent | unknown | //none// |
| ''responsiveads.com'' | 0.00018 | ResponsiveAds, Inc. | n/a -- independent, no ownership change known | absent | current | absent | [[https://responsiveads.com/|legal-doc]] |
| ''crsspxl.com'' | 0.00016 | Cross Pixel Media, Inc. | n/a -- independent, no ownership change known | current | current | current | [[https://crosspixel.net/privacy-policy/|legal-doc]] |
| ''cudasvc.com'' | 0.00016 | Barracuda Networks, Inc. | n/a -- independent, no ownership change known | absent | current | current | [[https://campus.barracuda.com/product/campus/doc/89096320/required-outbound-connections-for-barracuda-networks-appliances/|parent-site]] |
| ''htplayground.com'' | 0.00016 | //unresolved// | UNRESOLVED -- domain unreachable (no TLS handshake, no HTTP response), WHOIS/RDAP registrant is a privacy-protection proxy, and the only archived content is a 2015 Wayback snapshot with no operator identification | absent | absent | unknown | //none// |
| ''userzoom.com'' | 0.00016 | UserTesting, Inc. (brand: UserTesting; formerly independent UserZoom, Inc.) | merged 2023-04-03 (Thoma Bravo portfolio companies UserTesting and UserZoom merged and now operate under the UserTesting name) | absent | stale | absent | [[https://www.thomabravo.com/press-releases/usertesting-and-userzoom-merge-to-help-organizations-build-human-centered-experiences-for-all|newsroom]] |
| ''cnzz.com'' | 0.00014 | Alibaba (China) Technology Co., Ltd. (Alibaba Group; operates as part of the Umeng+ / CNZZ analytics brand) | n/a -- CNZZ merged with Umeng and Diyuanxin into Umeng+ in 2016 under Alibaba; ownership unchanged since | current | granularity | granularity | [[tls://cnzz.com:443|register]] |
| ''yahooapis.com'' | 0.00014 | Yahoo Inc. (majority owned by Apollo Funds/Apollo Global Management; Verizon retains a 10% stake) | changed 2021-09-01 (Apollo Funds completed acquisition of Yahoo, formerly Verizon Media) | stale | current | current | [[https://www.apollo.com/insights-news/pressreleases/2021/09/apollo-funds-complete-acquisition-of-yahoo-161530593|newsroom]] |
| ''cnn.com'' | 0.00012 | Warner Bros. Discovery, Inc. | changed 2022-04-08 (WarnerMedia-Discovery merger formed Warner Bros. Discovery, Inc.) | absent | current | current | [[tls://cnn.com:443|register]] |
| ''contentabc.com'' | 0.00012 | //unresolved// | UNRESOLVED -- domain does not resolve (NXDOMAIN on direct fetch, probe CODE:000, no TLS handshake); WebSearch leads (urlscan, whois, Aylo's own brands page) point to Aylo but Aylo's brands page (https://www.aylo.com/brands/) does NOT name contentabc.com, and no privacy policy/legal page naming the domain could be fetched | absent | unknown | unknown | //none// |
| ''glomex.com'' | 0.00012 | glomex GmbH | n/a -- current, confirmed via own Impressum fetched 2026-09-05 | absent | absent | current | [[https://www.glomex.com/de/impressum|legal-doc]] |
| ''pages02.net'' | 0.00012 | //unresolved// | UNRESOLVED -- could not fetch a primary source tying pages02.net specifically to a current operator | absent | unknown | unknown | //none// |
| ''tqlkg.com'' | 0.00012 | Conversant, LLC (Epsilon Data Management, LLC; ultimate parent Publicis Groupe S.A.) | 2019-07 -- Publicis Groupe completed acquisition of Epsilon (including its Conversant business) from Alliance Data Systems | stale | current | granularity | [[https://www.publicisgroupe.com/en/news/press-releases/publicis-groupe-to-acquire-epsilon|newsroom]] |
| ''appspot.com'' | 0.00011 | Google LLC (Alphabet Inc.) | n/a -- Google since appspot.com's 2008 launch as Google App Engine | current | current | absent | [[https://policies.google.com/terms|legal-doc]] |
| ''stat-track.com'' | 0.00011 | //unresolved// | UNRESOLVED -- domain does not resolve (probe CODE:000, no TLS); no primary source found | absent | absent | unknown | //none// |
| ''trustpilot.net'' | 0.00010 | //unresolved// | UNRESOLVED -- domain does not serve content under its own hostname; TLS cert covers only *.trustpilot.com (mismatch on direct fetch) and carries no validated-organisation (O=) field, so it does not meet the register-grade bar | absent | unknown | absent | //none// |
| ''atgsvcs.com'' | 0.00008 | Oracle Corporation (successor to Art Technology Group, Inc.) | 2011-01-05 -- Oracle completed its acquisition; Art Technology Group, Inc. became a wholly owned subsidiary of Oracle | absent | current | current | [[https://www.sec.gov/Archives/edgar/data/1086195/000095012311000543/b83864e8vk.htm|filing]] |
| ''juicer.cc'' | 0.00008 | Logly, Inc. | n/a -- current; product rebranded from 'Juicer' to 'LOGLY Audience Analytics' but still Logly-operated | absent | current | absent | [[https://juicer.cc/|legal-doc]] |
| ''richrelevance.com'' | 0.00008 | RichRelevance, Inc. (brand of Algonomy, which is now part of ADA) | changed 2021-01-19 (RichRelevance merged with Manthan Software to form Algonomy); Algonomy itself now shown as part of ADA per algonomy.com (exact date unconfirmed) | current | current | granularity | [[tls://richrelevance.com:443|register]] |
| ''medallia.com.au'' | 0.00008 | Medallia, Inc. | n/a -- independent | absent | absent | current | [[https://medallia.com.au/|legal-doc]] |
| ''medchatapp.com'' | 0.00008 | Medchat, LLC | n/a -- independent | current | absent | absent | [[https://medchatapp.com/site/|legal-doc]] |
| ''awltovhc.com'' | 0.00007 | //unresolved// | UNRESOLVED -- domain dead (no TLS handshake, HTTP 000) and no primary source names this exact domain | unknown | unknown | unknown | [[n/a -- no primary source located|n/a]] |
| ''collective-media.net'' | 0.00007 | //unresolved// | UNRESOLVED -- no confirmed current owner found | unknown | unknown | unknown | [[n/a -- no primary source located|n/a]] |
| ''mmstat.com'' | 0.00007 | //unresolved// | UNRESOLVED -- no primary source located | unknown | unknown | unknown | [[n/a -- no primary source located|n/a]] |
| ''compass-fit.jp'' | 0.00006 | MicroAd, Inc. | n/a -- no ownership change found; product appears discontinued (domain unreachable, product page now 404) but no other owner was ever named | absent | current | current | [[https://www.microad.co.jp/news/detail/1185/|newsroom]] |
| ''lduhtrp.net'' | 0.00006 | //unresolved// | UNRESOLVED -- domain dead (no TLS handshake, HTTP 000) and no primary source names this exact domain | unknown | unknown | unknown | [[n/a -- no primary source located|n/a]] |
| ''cedexis.com'' | 0.00005 | Cloud Software Group, Inc. | changed 2018-02-12 (Citrix Systems acquired Cedexis); changed again 2022 (Citrix combined with TIBCO into Cloud Software Group) | stale | stale | current | [[tls://cedexis.com:443|register]] |
| ''hqseek.com'' | 0.00005 | //unresolved// | UNRESOLVED -- could not fetch a primary source | absent | unknown | absent | //none// |
| ''sparkasse.de'' | 0.00005 | S-Communication Services GmbH (S-Com) | renamed 2022-09, effective 2023-01-01 -- formerly Sparkassen-Finanzportal GmbH | absent | stale | absent | [[https://www.sparkasse.de/impressum.html|legal-doc]] |
| ''stripst.com'' | 0.00005 | //unresolved// | UNRESOLVED -- site unreachable in this session | absent | absent | unknown | //none// |
| ''wishabi.com'' | 0.00005 | //unresolved// | UNRESOLVED -- no fetchable primary source naming wishabi.com | unknown | unknown | unknown | //none// |
| ''twiago.com'' | 0.00004 | twiago GmbH | n/a -- independent, no ownership change found | absent | current | absent | [[https://www.twiago.com/impressum|legal-doc]] |
| ''wrbm.com'' | 0.00004 | William Reed Ltd | renamed 2022-02-09 -- formerly William Reed Business Media Ltd | absent | stale | absent | [[https://find-and-update.company-information.service.gov.uk/company/02883992|register]] |
| ''hitslink.com'' | 0.00003 | Net Applications, Inc. | n/a -- no ownership change found | absent | absent | current | [[https://hitslink.com/|legal-doc]] |
| ''klarna.app'' | 0.00003 | Klarna Bank AB (publ) | n/a -- no ownership change found | absent | current | absent | [[https://www.klarna.com/international/|legal-doc]] |
| ''onecount.net'' | 0.00003 | GCN Publishing, Inc. (d/b/a GCN Media Services; product: ONEcount) | n/a -- domain defunct (TLS cert expired 2022, no longer resolving); product now served from one-count.com by the same operator | granularity | current | current | [[https://www.one-count.com/privacy-policy/|parent-site]] |
| ''sa-as.com'' | 0.00003 | //unresolved// | UNRESOLVED -- no primary source located; site has no TLS handshake and no title/copyright to check | absent | absent | unknown | //none// |
| ''chango.com'' | 0.00003 | Chango & Co. LLC | UNRESOLVED exact date -- domain has been resold/repurposed to an unrelated interior design business; the ad-tech company 'Chango' (acquired by Rubicon Project, later renamed Magnite) no longer operates here | stale | stale | absent | [[https://www.chango.com/|legal-doc]] |
| ''google.nl'' | 0.00003 | Google LLC (subsidiary of Alphabet Inc.) | n/a -- longstanding | granularity | current | current | [[https://policies.google.com/privacy|legal-doc]] |
| ''americanexpress.com'' | 0.00002 | American Express Company | n/a -- longstanding | absent | current | current | [[tls://americanexpress.com:443|register]] |
| ''amperwave.net'' | 0.00002 | Audacy, Inc. | 2021-10-20 -- Audacy acquired WideOrbit's WO Streaming technology/operations and rebranded the platform AmperWave | absent | current | absent | [[https://audacyinc.com/press/audacy-announces-acquisition-of-wideorbit-digital-audio-streaming-technology-and-operations/|newsroom]] |
| ''cartfulsolutions.com'' | 0.00002 | Cartful Solutions, Inc. (Cartful) | n/a -- independent, same company | absent | current | current | [[https://cartful.com/privacy-policy|legal-doc]] |
| ''comcast.com'' | 0.00002 | Comcast Corporation | n/a -- longstanding | current | current | current | [[https://corporate.comcast.com/|newsroom]] |
| ''hearst.com'' | 0.00002 | Hearst Communications, Inc. (Hearst) | n/a -- longstanding | current | current | current | [[https://www.hearst.com/|filing]] |
| ''heraldcorp.com'' | 0.00002 | Herald Corporation Inc. (헤럴드 / Herald Corporation) | n/a -- longstanding | absent | current | absent | [[https://company.heraldcorp.com/content.php?lang=eng|legal-doc]] |
| ''makaira.io'' | 0.00002 | Makaira GmbH | marmalade GmbH merged into Makaira GmbH, effective 2026-08-25 | absent | stale | absent | [[https://www.makaira.io/de/impressum|legal-doc]] |
| ''20min.ch'' | 0.00001 | TX Group AG | Tamedia AG renamed TX Group AG, 2019/2020 | absent | stale | absent | [[https://www.20min.ch/impressum|legal-doc]] |
| ''accessibe.com'' | 0.00001 | accessiBe Inc. | n/a -- independent | absent | current | current | [[https://accessibe.com/|legal-doc]] |
| ''addthiscdn.com'' | 0.00001 | Oracle Corporation | Oracle terminated all AddThis services 2023-05-31; addthis.com now redirects to oracle.com | granularity | current | current | [[http://web.archive.org/web/20241003135046/https://www.addthis.com/|legal-doc]] |
| ''admarketplace.net'' | 0.00001 | adMarketplace, Inc. | n/a -- independent | absent | current | current | [[https://www.admarketplace.com/privacy-policy|legal-doc]] |
| ''amazon.de'' | 0.00001 | Amazon Europe Core S.à r.l. / Amazon EU S.à r.l. (Amazon.com, Inc. group) | n/a -- longstanding Amazon EU operating structure | absent | granularity | current | [[http://web.archive.org/web/20240317112829/https://www.amazon.de/gp/help/customer/display.html?nodeId=505048|legal-doc]] |
| ''atwola.com'' | 0.00001 | Yahoo Inc. | Verizon sold AOL/Yahoo (as Verizon Media/Oath) to Apollo Global Management, renamed Yahoo Inc., 2021 | stale | current | current | [[https://legal.aol.com/privacy/index.html|legal-doc]] |
| ''bestbuy.com'' | 0.00001 | Best Buy Co., Inc. | n/a -- independent | absent | current | absent | [[tls://bestbuy.com:443|register]] |
| ''bilibili.com'' | 0.00001 | 上海幻电信息科技有限公司 (Shanghai Huandian Information Technology Co., Ltd.), operating subsidiary of Bilibili Inc. (NASDAQ: BILI) | n/a -- longstanding | absent | granularity | granularity | [[tls://bilibili.com:443|register]] |
| ''britishairways.com'' | 0.00001 | British Airways Plc | n/a -- independent operating subsidiary (part of International Airlines Group since 2011 merger; no change to the domain's operating entity) | absent | current | absent | [[tls://britishairways.com:443|register]] |
| ''cratecamera.com'' | 0.00001 | //unresolved// | UNRESOLVED -- domain 404s and carries only a DV Let's Encrypt cert (no validated organisation); no reachable newsroom/legal-doc/register source | absent | unknown | unknown | [[n/a|n/a]] |
| ''cxt.ms'' | 0.00001 | Taboola, Inc. (operating Connexity) | acquired 2021-09-01 -- Taboola completed its acquisition of Connexity | stale | stale | absent | [[https://www.taboola.com/press-releases/taboola-closes-connexity-acquisition/|newsroom]] |
| ''domdex.com'' | 0.00001 | Deloitte Digital (Deloitte Consulting LLP) | acquired 2018-09-10 -- Deloitte acquired Magnetic Media Online, Inc.'s AI/ad-tech platform business | current | stale | current | [[https://www.prnewswire.com/news-releases/deloitte-acquires-magnetics-artificial-intelligence-platform-business-300709565.html|newsroom]] |
| ''globo.com'' | 0.00001 | //unresolved// | UNRESOLVED -- WebFetch could not reach any globo.com/politicas.globo.com/privacidade.globo.com page to quote a legal-entity statement | absent | unknown | unknown | [[n/a|n/a]] |
| ''hitc.com'' | 0.00001 | GRV Media Ltd | n/a -- independent, GRV Media Ltd has operated HITC since rebranding from Here Is The City in 2015 | absent | current | absent | [[https://grv.media/privacy/|legal-doc]] |
| ''km0trk.com'' | 0.00001 | //unresolved// | UNRESOLVED -- domain gives no TLS handshake and no reachable content; operator could not be identified from any primary source | absent | absent | unknown | [[n/a|n/a]] |
| ''mediaset.es'' | 0.00001 | Grupo Audiovisual Mediaset España Comunicación, S.A.U. (subsidiary of MFE-MediaForEurope) | renamed/reorganized 2023-03-15 -- Mediaset España Comunicación, S.A. segregated its entire business to Grupo Audiovisual Mediaset España Comunicación, S.A.U. (BORME-C-2023-1010) | absent | stale | absent | [[tls://mediaset.es:443|register]] |
| ''ml.com'' | 0.00001 | Bank of America Corporation (Merrill Lynch) | n/a -- Merrill Lynch has been a Bank of America subsidiary since the 2009 acquisition; no recent change | absent | current | absent | [[tls://ml.com:443|register]] |
| ''offshoregeology.com'' | 0.00001 | //unresolved// | UNRESOLVED -- domain is dead (404), no primary source ties it to any current operator | absent | absent | unknown | [[NONE -- no primary source reached|n/a]] |
| ''qbox.me'' | 0.00001 | Shanghai Qiniu Information Technology Co., Ltd. (Qiniu Cloud) | n/a -- independent, no ownership change found | current | current | absent | [[https://www-static.qbox.me/en/company|legal-doc]] |
| ''report-uri.io'' | 0.00001 | Report-URI Ltd. | n/a -- independent, no ownership change found | absent | current | absent | [[https://find-and-update.company-information.service.gov.uk/company/10943557|register]] |
| ''vg.hu'' | 0.00001 | Mediaworks Hungary Zrt. | n/a -- independent, no ownership change found | absent | absent | current | [[https://www.vg.hu/impresszum|legal-doc]] |
| ''webmd.com'' | 0.00001 | WebMD LLC (an Internet Brands company; Internet Brands is a KKR portfolio company) | closed 2017-09 -- Internet Brands (KKR) completed its tender offer acquisition of WebMD Health Corp | current | current | absent | [[https://www.webmd.com/|legal-doc]] |
| ''99static.com'' | 0.00001 | 99designs Pty Ltd (99designs by Vista; a Cimpress plc subsidiary) | n/a -- currently a Cimpress plc subsidiary; historical acquisition date not verified against a primary source this session | absent | current | absent | [[https://www.sec.gov/Archives/edgar/data/0001262976/000126297626000027/ex211subsidiariesofcimpres.htm|filing]] |
| ''adrta.com'' | 0.00001 | Pixalate, Inc. | n/a -- independent, no ownership change found | current | current | current | [[tls://adrta.com:443|register]] |
| ''cedscdn.it'' | 0.00001 | //unresolved// | UNRESOLVED -- domain does not resolve (no TLS handshake); no primary source ties it to any current operator | absent | unknown | absent | [[NONE -- no primary source reached|n/a]] |
| ''cjponyparts.com'' | 0.00001 | //unresolved// | UNRESOLVED -- site returns HTTP 403 (Cloudflare challenge) on every page fetched this session | absent | unknown | absent | [[NONE -- no primary source reached|n/a]] |
| ''coverartarchive.org'' | 0.00001 | MetaBrainz Foundation, Inc. | n/a -- unchanged since inception; run jointly with Internet Archive | absent | current | absent | [[https://metabrainz.org/projects|parent-site]] |
| ''dnb.com'' | 0.00001 | Dun & Bradstreet, Inc. | n/a -- operating/trading name unchanged; ultimate parent went private via an investor consortium in Feb 2022 | current | current | absent | [[https://web.archive.org/web/20241002130956/https://www.dnb.com/utility-pages/privacy-policy.html|legal-doc]] |
| ''experian.com'' | 0.00001 | Experian Information Solutions, Inc. (brand: Experian; ultimate parent: Experian plc, LSE-listed) | n/a -- long-standing corporate structure | current | granularity | current | [[tls://experian.com:443|register]] |
| ''farfetch-contents.com'' | 0.00001 | Farfetch UK Limited (part of the Coupang, Inc. group since its Jan 2024 acquisition of Farfetch Holdings) | Farfetch Holdings acquired by Coupang, Inc. 2024-01-30; Farfetch UK Limited (no. 06400760, formerly Farfetch.com Limited) remains an active UK subsidiary | absent | current | absent | [[https://find-and-update.company-information.service.gov.uk/company/06400760|register]] |
| ''i.ua'' | 0.00001 | //unresolved// | UNRESOLVED -- no primary legal document reachable; site is a JS-rendered shell with no static footer/legal text, and /legal returned 404 | absent | absent | unknown | //none// |
| ''jdpower.com'' | 0.00001 | J.D. Power | n/a -- current | absent | current | current | [[tls://jdpower.com:443|register]] |
| ''jobs2careers.com'' | 0.00001 | Talroo, Inc. | n/a -- Jobs2Careers is an active Talroo brand/channel, not a former or renamed entity | absent | current | absent | [[https://www.talroo.com/|parent-site]] |
| ''myaccountaccess.com'' | 0.00001 | U.S. Bank National Association | n/a -- current | absent | current | absent | [[tls://myaccountaccess.com:443|register]] |
| ''radio-canada.ca'' | 0.00001 | Canadian Broadcasting Corporation (French legal/trading name: Société Radio-Canada) | n/a -- current, unchanged bilingual Crown corporation | absent | current | absent | [[https://ici.radio-canada.ca/conditions-utilisation|legal-doc]] |
| ''sapo.io'' | 0.00001 | MEO – Serviços de Comunicações e Multimédia, S.A. (SAPO) | n/a -- SAPO has operated under the MEO/Altice Portugal group; no ownership change identified | absent | current | absent | [[https://ajuda.sapo.pt/politica-de-privacidade-7675|legal-doc]] |
| ''tu-dresden.de'' | 0.00001 | Technische Universität Dresden | n/a -- independent public university, no ownership change | absent | current | absent | [[tls://tu-dresden.de:443|register]] |
| ''tvtime.com'' | 0.00001 | Whip Media Group, Inc. | renamed c.2016-2018 (Whipclip → Whip Media, per secondary sources only, not independently verified); TV Time app/site discontinued 2026-07-15 | absent | stale | absent | [[https://whipmedia.com/news/whip-media-group-parent-to-tv-show-tracking-app-tv-time-raises-50m/|newsroom]] |
| ''viralize.com'' | 0.00001 | ShowHeroes SE (brand: MAX; ShowHeroes Group) | acquired 2020-12 (per trade press only, ShowHeroes Group acquisition of Viralize, not independently verified on a primary source); rebranded to MAX 2024-05 | absent | absent | current | [[https://showheroes.com/imprint/|legal-doc]] |

--- G. DokuWiki rate tables -----------------------------------------

=== webXray ===
^ Verdict ^ Domain-level ^ 95% CI ^ Encounter-weighted ^ 95% CI ^
| current | 69.9% | 55.5%–83.1% | 93.9% | 80.9%–98.8% |
| granularity | 10.2% | 2.1%–20.9% | 0.2% | 0.0%–0.8% |
| stale | 19.8% | 9.2%–32.3% | 5.9% | 1.0%–19.1% |
| error | 0.0% | 0.0%–0.0% | 0.0% | 0.0%–0.0% |
| current+gran. | 80.2% | 67.7%–90.8% | 94.1% | 81.4%–99.0% |
| stale+error | 19.8% | 9.0%–32.6% | 5.9% | 1.1%–19.4% |

=== Tracker Radar ===
^ Verdict ^ Domain-level ^ 95% CI ^ Encounter-weighted ^ 95% CI ^
| current | 73.7% | 60.8%–85.8% | 68.6% | 29.3%–97.0% |
| granularity | 2.8% | 0.0%–8.3% | 0.1% | 0.0%–0.4% |
| stale | 22.1% | 10.5%–35.1% | 26.8% | 0.4%–64.6% |
| error | 1.5% | 0.0%–4.4% | 4.5% | 0.0%–19.3% |
| current+gran. | 76.5% | 63.5%–88.0% | 68.7% | 29.2%–97.7% |
| stale+error | 23.5% | 11.7%–36.1% | 31.3% | 2.9%–71.2% |

=== Disconnect ===
^ Verdict ^ Domain-level ^ 95% CI ^ Encounter-weighted ^ 95% CI ^
| current | 94.4% | 86.9%–100.0% | 83.1% | 53.7%–100.0% |
| granularity | 4.4% | 0.0%–11.2% | 16.5% | 0.0%–45.8% |
| stale | 1.2% | 0.0%–3.8% | 0.4% | 0.0%–1.5% |
| error | 0.0% | 0.0%–0.0% | 0.0% | 0.0%–0.0% |
| current+gran. | 98.8% | 96.2%–100.0% | 99.6% | 98.5%–100.0% |
| stale+error | 1.2% | 0.0%–3.8% | 0.4% | 0.0%–1.5% |

W. Unedited output: scripts/owner_reestimate_independent.py

Run as python3 scripts/owner_reestimate_independent.py.

webXray  (n eligible = 49)
  ok  current              independent 69.9%   estimator 69.9%
  ok  stale                independent 19.8%   estimator 19.8%
  ok  current+gran.        independent 80.2%   estimator 80.2%
  ok  error                independent 0.0%   estimator 0.0%
  ok  encounter-current    independent 93.9%   estimator 93.9%
  ok  heaviest row         independent gstatic.com    estimator gstatic.com 
  ok  its share            independent 39.4%   estimator 39.4%
  ok  flipped              independent 54.4%   estimator 54.4%

Tracker Radar  (n eligible = 47)
  ok  current              independent 73.7%   estimator 73.7%
  ok  stale                independent 22.1%   estimator 22.1%
  ok  current+gran.        independent 76.5%   estimator 76.5%
  ok  error                independent 1.5%   estimator 1.5%
  ok  encounter-current    independent 68.6%   estimator 68.6%
  ok  heaviest row         independent omtrdc.net    estimator omtrdc.net 
  ok  its share            independent 24.9%   estimator 24.9%
  ok  flipped              independent 43.7%   estimator 43.7%

Disconnect  (n eligible = 42)
  ok  current              independent 94.4%   estimator 94.4%
  ok  stale                independent 1.2%   estimator 1.2%
  ok  current+gran.        independent 98.8%   estimator 98.8%
  ok  error                independent 0.0%   estimator 0.0%
  ok  encounter-current    independent 83.1%   estimator 83.1%
  ok  heaviest row         independent id5-sync.com    estimator id5-sync.com 
  ok  its share            independent 16.7%   estimator 16.7%
  ok  flipped              independent 66.4%   estimator 66.4%

Both implementations agree on every figure the content page publishes.
Not covered here: the bootstrap confidence intervals, which are
computed only by owner_random_sample.py.

X. Unedited output: scripts/wayback_webxray.sh

Run as bash scripts/wayback_webxray.sh.

### 1. github.com/timlib/webXray -- one row per distinct body
$ curl -s 'https://web.archive.org/cdx/search/cdx?url=github.com%2Ftimlib%2FwebXray&fl=timestamp,statuscode,digest&collapse=digest'
20180611003641 200 L4766INHV6M7T7ALEFS2UJ3I74MM5EDJ
20181126144737 200 G5WOQI2HYKUKWAAGRUO42WUDOXY2VU6S
20190826055440 200 W46OAI7KLP2FGD6Y245ULOOSXHC2IBL6
20211015064132 200 TU36LI3FDFRQPM4EZMXMARHIBGDIGYPN
20211016224755 200 AJZI67R2HS4YGQUU3CSCG54T55257TZY
20211210122612 200 FHE2WAMB36FY5XK3CGM4T5ASTQF6FUKM
20220123045726 200 5IOOFLCOBHEJX6OEDHYVN3AFEP3LK6A6
20220127164048 200 E6X7G3GILQDHQ4KMH3I2JCXEUOS6SE4Z
20220223160839 200 VMN74YETBRBG2JCX2HYA2J3Q7NVFEJ5F
20220513083135 200 CMNBFLMLFRZXDRLBLY7XFPYMCC5PWCNR
20221108014826 200 5GLQQOWUODOL4X5B7SILPGY2LH7VB3TU
20221230045425 200 BB7EUFXI632AYNICMMNWX2UUTUPPXZLI
20230331144433 200 DMONPBL4MNAKGSXSW5FCS2ZI242LIWXT
20231115075841 404 G5PZS7SXVGWI5U63S2MXU7U3XQRH5XBT
20241218173005 404 C4Z5AVA3ELZH2OQULRACXFTWILUSMRKR
20251008113829 404 UIYYQ4UACBLLXSRRDMBQ2XW3HRRHFKQO

### 2. github.com/timlib/webXray_Domain_Owner_List -- same
$ curl -s 'https://web.archive.org/cdx/search/cdx?url=github.com%2Ftimlib%2FwebXray_Domain_Owner_List&fl=timestamp,statuscode,digest&collapse=digest'
20200604200840 200 DVB4FZM2AGW3TL5NSDLINWM7U4JXVTYZ
20210104201222 200 LUYI3Z4SIOG5YELAFB4LBS2S2ND5KRIS
20210715231334 200 G5YIQOX2Z2N5RD6TUD7PZU5LDSOMYGUZ
20220124035813 200 YSOXRKA4R4LSCR4QM3SULY4ZKZJKLJHF
20220125001631 200 H7NOFQFKTCUDLHCPNOCGGPPGNBIMT56E
20220125152835 200 NFFL44KNMGY5XZICPZWDSA4ROOME2DTY
20220430105749 200 NB6URHUH43YPGLCCEY2TEG54YMAN2WX7
20221006015001 200 EDEN2PL2BKAJTG73MZYFHCZ5KSJ3H4I5
20250118193856 404 3NQF2VBVKTZMWZ3LHNLY7MEDXWO5F7A2
20250417205226 404 YLJTONQVVO32HNHMNJHPLBRVBASRA3GO

### 3. github.com/timlib/webXray -- UNCOLLAPSED across the 200->404 transition.
     Two rows here means there is no capture between them and the window
     cannot be narrowed; more rows would mean the collapse hid something.
$ curl -s 'https://web.archive.org/cdx/search/cdx?url=github.com%2Ftimlib%2FwebXray&fl=timestamp,statuscode,length&from=20230101&to=20240601'
20230331144433 200 32709
20231115075841 404 112514

### 4. github.com/timlib -- the profile, in case it brackets either window
$ curl -s 'https://web.archive.org/cdx/search/cdx?url=github.com%2Ftimlib&fl=timestamp,statuscode,digest&collapse=digest'
20220513083147 200 HIPVFVVM33SZFQ2M5WC2EU5KGJWRPIHZ
20220717044003 200 5WNFXTCXVFY2C2UWRRFQ6EOS77WEX34U
20221006020557 200 FG2NQ7UGUNZ6XLIAKIKQKB3QTADETCXV
20221006030159 200 JXFJVLGXHBDYQGEPOTFSKVKFRDFFCCUK
20221027212759 200 6QR4LQJIJTIYEEFQCX5UZ3C4XVO2WRQL
20250816154150 200 MGOSKB6I2FBFP3UFG6CVLEI4VRRWJYWP
20260802003721 200 O75CQE2ZOPQJQRGR6X2EIVAR5VIAEUR6

### 5. webxray.org -- every distinct body, 2010 to now
$ curl -s 'https://web.archive.org/cdx/search/cdx?url=webxray.org&fl=timestamp,statuscode,digest,length&collapse=digest'
20101008070114 200 M4Q7W3F4C5MP5Z2EZNTH6EIF6KGCPYYB 1280
20101108204354 200 BWVG6IL2T2TAHPH5ZXCNQBUFQZ4JVAT5 2496
20101129054311 200 DAMIK3EBZTFYDWXEM4D7U3LHKXQZQMUZ 2514
20101221102845 200 OACMXOKI5QJJCVAS7NJJCN6CQFGEAGZR 2412
20110113182011 200 45DMG3UZ2B7BNTAUMVVLWAXS37V2UTHP 2418
20110223190119 200 MMCAIZV6YX2LGDKIKHS3GS3GRJJ5YP4X 2636
20110326053453 200 U2VFEFPPSX2TS4PBEV7W2P2IFYOPWOOS 2565
20110425164812 200 DHRUWQZMUZRBDOZ7SMIA4II4GEYWFNYZ 2154
20110526085510 200 UASX5A5FNKD6CYQPTOUDVH5YRSHVV3BF 2193
20110625162305 200 7E375OZBNRBKJ4EHBNPPWFZ4RRZJLFGH 2452
20110726084229 200 RFBMOQYPUAUYCZ6QWK7QVGDYYFRICDOJ 2500
20110825223614 200 IZVC3LF2XDD33FIGJDDKKHKQGRQUGZLB 2459
20110902035356 200 5B7AAOCWZVP6VMHTNYQ2UM3Q4GVMDA4M 2388
20110907081359 301 Y6HHPE3DHZI6NIOGDOXUN7AB5AGT64O6 518
20110925050310 200 XM4DBQDCU5SELGOZB56VGRAT6O3HMBX4 2450
20110927093221 200 AYJNJGXQM3WUXBZ47SK3P7G6ADKPINS3 2346
20141218144346 200 LDQU434SDOHMESCY6R2XY7VBWHC5P7HY 2492
20150227145030 200 EHM7PQD4QAT6A76J2OHXS2RLABUTLATA 2629
20150530080456 200 HGMW5VYQ2TM7IJYFMHOWHBHYXRY6UL4J 4974
20150925031445 200 AY5E3OQ6NT4Z2FG5F563LCE4DMDSHKCL 4930
20151108015237 200 3CYPT6PM7ITUOL7OJ5V7VBLLV7JY7J3E 5119
20160110154816 200 OXJVOH24XMLXPHC7DDZXY7BEMBSQKXRH 5372
20170925140045 200 66PIGSVID5IGISILVPEMVGXQSFRYCVJ7 746
20180323123403 301 ULYVP4RPSEA2TZP5F6T2QYLZWPANXVMU 562
20180515085339 200 CK644HC56OFWMARF6AEPCTEBYFIYBPCA 6811
20180809120108 301 ULYVP4RPSEA2TZP5F6T2QYLZWPANXVMU 545
20180816013146 200 52AM2EZKQ2ZPJBU52PJST7PVU3OUKVB7 6960
20181002135018 200 IVHC265IC3EIE7GIOCFXVXTYNBR63WCN 6958
20181113013040 301 ULYVP4RPSEA2TZP5F6T2QYLZWPANXVMU 544
20181126144739 200 IVHC265IC3EIE7GIOCFXVXTYNBR63WCN 7126
20181209103302 - ULYVP4RPSEA2TZP5F6T2QYLZWPANXVMU 481
20190308074733 200 4UJAWJMPIHEUROFHZHKWDS4NVNUE2H36 7029
20190419100800 - ULYVP4RPSEA2TZP5F6T2QYLZWPANXVMU 484
20190419100801 - 4UJAWJMPIHEUROFHZHKWDS4NVNUE2H36 531
20190424014049 - ULYVP4RPSEA2TZP5F6T2QYLZWPANXVMU 483
20190424014050 - 4UJAWJMPIHEUROFHZHKWDS4NVNUE2H36 533
20190508040320 301 ULYVP4RPSEA2TZP5F6T2QYLZWPANXVMU 543
20190508093443 - 4UJAWJMPIHEUROFHZHKWDS4NVNUE2H36 523
20190718120934 200 TG7Y6EDLBSDJIFL6WEI3BPUXGNC3KPI6 5707
20190919093041 301 ULYVP4RPSEA2TZP5F6T2QYLZWPANXVMU 631
20190919093042 200 Q7L6RYPN2FOHITXJJAQAWARKDNZHU7I3 6073
20190922084320 200 WVP3ELF2M46VW5OUCQH2ULOHV6ZRS6S4 5806
20201031034454 301 ULYVP4RPSEA2TZP5F6T2QYLZWPANXVMU 698
20201031034456 200 WVP3ELF2M46VW5OUCQH2ULOHV6ZRS6S4 5974
20201108113345 301 ULYVP4RPSEA2TZP5F6T2QYLZWPANXVMU 317
20201108113346 200 WVP3ELF2M46VW5OUCQH2ULOHV6ZRS6S4 5309
20210106163830 200 ULAXEPUHK7SSLQO3BCDSMGFAIXQ2J4U2 5882
20210419141609 301 ULYVP4RPSEA2TZP5F6T2QYLZWPANXVMU 544
20220123045404 200 JL4BTLDOP5TAURYMJWP323SXL7PGRYSS 16549
20220123045432 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 327
20220123045433 200 JL4BTLDOP5TAURYMJWP323SXL7PGRYSS 16548
20220123045617 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 352
20220123045618 200 JL4BTLDOP5TAURYMJWP323SXL7PGRYSS 16573
20220331121357 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 439
20220513090151 200 JL4BTLDOP5TAURYMJWP323SXL7PGRYSS 17251
20221006015824 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 331
20221130063816 200 JL4BTLDOP5TAURYMJWP323SXL7PGRYSS 17390
20230302130342 - OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 620
20230323081741 200 5HHWIRAESDR22RFZEN7ANFAMRP2LSX3T 19611
20230604164347 200 JL4BTLDOP5TAURYMJWP323SXL7PGRYSS 17386
20230807011114 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 610
20230807011119 200 JL4BTLDOP5TAURYMJWP323SXL7PGRYSS 17328
20230811200840 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 570
20230924214123 200 JL4BTLDOP5TAURYMJWP323SXL7PGRYSS 17400
20231101090946 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 566
20231101090954 200 5HHWIRAESDR22RFZEN7ANFAMRP2LSX3T 19611
20231115075745 200 JL4BTLDOP5TAURYMJWP323SXL7PGRYSS 17254
20231211044509 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 606
20231211044510 200 JL4BTLDOP5TAURYMJWP323SXL7PGRYSS 17325
20231219214433 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 336
20231219215114 200 JL4BTLDOP5TAURYMJWP323SXL7PGRYSS 16657
20231228151651 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 562
20240110232139 200 JL4BTLDOP5TAURYMJWP323SXL7PGRYSS 17334
20240121113649 200 5HHWIRAESDR22RFZEN7ANFAMRP2LSX3T 19611
20240523052429 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 568
20240524194734 401 DJVSW75BWDEIPQGRO5K5443TPNEOO3IZ 600
20240524194835 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 568
20240524194836 401 DJVSW75BWDEIPQGRO5K5443TPNEOO3IZ 598
20240724105426 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 569

### 6. webxray.org -- UNCOLLAPSED over 2024, where the demo died
$ curl -s 'https://web.archive.org/cdx/search/cdx?url=webxray.org&fl=timestamp,statuscode,digest,length&from=20240101&to=20241231'
20240110232138 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 617
20240110232139 200 JL4BTLDOP5TAURYMJWP323SXL7PGRYSS 17334
20240121113649 200 5HHWIRAESDR22RFZEN7ANFAMRP2LSX3T 19611
20240229061811 200 5HHWIRAESDR22RFZEN7ANFAMRP2LSX3T 19611
20240229061830 - 5HHWIRAESDR22RFZEN7ANFAMRP2LSX3T 668
20240328005456 200 5HHWIRAESDR22RFZEN7ANFAMRP2LSX3T 19611
20240523052429 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 568
20240523052649 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 569
20240524194734 401 DJVSW75BWDEIPQGRO5K5443TPNEOO3IZ 600
20240524194835 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 568
20240524194836 401 DJVSW75BWDEIPQGRO5K5443TPNEOO3IZ 598
20240724105426 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 569
20240724105427 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 564
20240724174916 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 563
20240725012711 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 603
20240728115338 - OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 466
20240728115352 - OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 471
20240826100319 - OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 473
20240826100322 - OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 478
20240922063016 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 560
20240922063016 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 561
20240922063016 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 570
20240922063016 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 565
20240922063016 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 570
20240922063016 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 570
20240922063016 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 572
20241122060812 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 563
20241122060813 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 571
20241219230649 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 564
20241229053438 - OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 475
20241229053442 - OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 478

### 7. webxray.org -- UNCOLLAPSED over 2025-2026. This is what bounds the end of
     the webxray.ai redirect: the last capture here still carries the 301
     digest OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU, and the Archive has no capture of
     the placeholder that is served today.
$ curl -s 'https://web.archive.org/cdx/search/cdx?url=webxray.org&fl=timestamp,statuscode,digest,length&from=20250101&to=20261231'
20250113205351 - OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 476
20250113205354 - OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 479
20250119095437 - OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 478
20250119095503 - OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 481
20250121123937 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 567
20250124181930 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 270
20250217020733 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 559
20250217020745 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 564
20250321213408 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 565
20250321213409 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 565
20250419102348 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 565
20250822114103 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 568
20250822114112 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 572
20260205035830 301 OM6ALWQTEGJ5NTY5RYSC2EXCKJOAHOVU 565

Y. Unedited output: scripts/check_owner_sample_figures_mutations.sh

Run as bash scripts/check_owner_sample_figures_mutations.sh.

caught    webXray domain-level 69.9% -> 70.9%
caught    Disconnect domain-level 94.4% -> 95.4%
caught    webXray encounter-weighted 93.9% -> 92.9%
caught    coverage count 5,566 -> 5,567
caught    coverage share 17.2% -> 17.3%
caught    Disconnect CI 86.9-100.0 -> 87.9-100.0
caught    concentration 39.4% -> 41.0%
caught    current+gran. 80.2% -> 81.2%
caught    webXray stale 19.8% -> 18.8%
caught    heaviest row gstatic.com -> gstaticx.com

all mutations caught.

Z. Unedited output: scripts/owner_probe.sh, all 175 domains

Run as for d in $(jq -r '.union[].domain' out/owner_sample.json); do bash scripts/owner_probe.sh “$d”; done.

=== 1rx.io
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://1rx.io/ CODE:000
TITLE: 
COPYRIGHT: 

=== 20min.ch
TLS: subject=CN = 20min.ch|issuer=C = US, O = Google Trust Services, CN = WE1|notBefore=Jul 19 08:31:34 2026 GMT|notAfter=Oct 17 09:31:21 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.20min.ch/ CODE:200
TITLE: 20 Minuten: Aktuelle Nachrichten, Schlagzeilen - News von Jetzt
COPYRIGHT: 

=== 99static.com
TLS: <no handshake>|
RDAP: 
RDAP-registrar: MarkMonitor Inc.
FINAL:https://99static.com/ CODE:000
TITLE: 
COPYRIGHT: 

=== accessibe.com
TLS: subject=CN = accessibe.com|issuer=C = US, O = Let's Encrypt, CN = YE2|notBefore=Jun 17 22:41:15 2026 GMT|notAfter=Sep 15 22:41:14 2026 GMT|
RDAP: 
RDAP-registrar: eNom, LLC
FINAL:https://accessibe.com/ CODE:200
TITLE: Web Accessibility Platform for WCAG
COPYRIGHT: &copy; 2026 - accessiBe Inc|

=== acint.net
TLS: subject=CN = *.acint.net|issuer=C = US, O = Let's Encrypt, CN = YE1|notBefore=Jul 16 23:34:51 2026 GMT|notAfter=Oct 14 23:34:50 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://acint.net/ CODE:200
TITLE: Acint
COPYRIGHT: 

=== addthiscdn.com
TLS: <no handshake>|
RDAP: 
RDAP-registrar: MarkMonitor Inc.
FINAL:https://addthiscdn.com/ CODE:000
TITLE: 
COPYRIGHT: 

=== adgrx.com
TLS: <no handshake>|
RDAP: 
RDAP-registrar: Amazon Registrar, Inc.
FINAL:https://adgrx.com/ CODE:000
TITLE: 
COPYRIGHT: 

=== adition.com
TLS: subject=CN = virtualminds.com|issuer=C = US, O = Let's Encrypt, CN = YR2|notBefore=Jul 29 07:33:07 2026 GMT|notAfter=Oct 27 07:33:06 2026 GMT|
RDAP: 
RDAP-registrar: InterNetX GmbH
FINAL:https://adition.com/ CODE:000
TITLE: 
COPYRIGHT: 

=== admarketplace.net
TLS: subject=CN = admarketplace.net|issuer=C = US, O = Amazon, CN = Amazon RSA 2048 M04|notBefore=Feb 18 00:00:00 2026 GMT|notAfter=Mar 19 23:59:59 2027 GMT|
RDAP: 
RDAP-registrar: MarkMonitor Inc.
FINAL:https://www.admarketplace.com/ CODE:200
TITLE: adMarketplace | Relevant Ads for AI Discovery
COPYRIGHT: © 2026|

=== adrta.com
TLS: subject=C = US, ST = Virginia, L = McLean, O = "Pixalate, Inc.", CN = *.adrta.com|issuer=C = US, O = DigiCert Inc, CN = DigiCert Global G2 TLS RSA SHA256 2020 CA1|notBefore=Jul 27 00:00:00 2026 GMT|notAfter=Feb 10 23:59:59 2027 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://adrta.com/ CODE:200
TITLE: Pixalate
COPYRIGHT: 

=== agkn.com
TLS: <no handshake>|
RDAP: 
RDAP-registrar: GoDaddy Corporate Domains, LLC
FINAL:https://agkn.com/ CODE:000
TITLE: 
COPYRIGHT: 

=== akamaihd.net
TLS: <no handshake>|
RDAP: 
RDAP-registrar: MarkMonitor Inc.
FINAL:https://akamaihd.net/ CODE:000
TITLE: 
COPYRIGHT: 

=== amazon.de
TLS: subject=CN = *.peg.a2z.com|issuer=C = US, O = DigiCert Inc, OU = www.digicert.com, CN = GeoTrust TLS RSA CA G1|notBefore=May  5 00:00:00 2026 GMT|notAfter=Nov 18 23:59:59 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.amazon.de/ CODE:202
TITLE: 
COPYRIGHT: 

=== americanexpress.com
TLS: subject=C = US, ST = New York, L = New York, O = American Express Company, CN = www.americanexpress.com|issuer=C = US, O = DigiCert Inc, CN = DigiCert Global G2 TLS RSA SHA256 2020 CA1|notBefore=Sep 30 00:00:00 2025 GMT|notAfter=Sep 29 23:59:59 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.americanexpress.com/ CODE:200
TITLE: American Express Credit Cards, Rewards &amp; Banking
COPYRIGHT: © 2026 American Express|copyright\",[\"~#iL\",[[\"~#iM\",[\"message\",\"All users of our online services are subject to our|© {Year} American Express|

=== amperwave.net
TLS: subject=CN = amperwave.net|issuer=C = US, O = Amazon, CN = Amazon RSA 2048 M04|notBefore=Aug  5 00:00:00 2026 GMT|notAfter=Feb 18 23:59:59 2027 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://amperwave.net/ CODE:403
TITLE: 
COPYRIGHT: 

=== amung.us
TLS: subject=CN = amung.us|issuer=C = US, O = Google Trust Services, CN = WE1|notBefore=Aug 14 00:47:14 2026 GMT|notAfter=Nov 12 01:47:02 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://whos.amung.us/ CODE:200
TITLE: whos.amung.us - free real-time stats!
COPYRIGHT: © 2007-2026 &#8211; whos|

=== app-us1.com
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://app-us1.com/ CODE:000
TITLE: 
COPYRIGHT: 

=== appspot.com
TLS: subject=CN = *.appspot.com|issuer=C = US, O = Google Trust Services, CN = WR2|notBefore=Aug 10 08:37:16 2026 GMT|notAfter=Nov  2 08:37:15 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://accounts.google.com/v3/signin/identifier?continue=https://console.cloud.google.com/appengine&followup=https://console.cloud.google.com/appengine&osid=1&passive=1209600&service=cloudconsole&flowName=GlifWebSignIn&flowEntry=ServiceLogin&dsh=S-1475384970:1788618242082018 CODE:200
TITLE: Google Cloud Platform
COPYRIGHT: Copyright The Closure Library Authors|Copyright 2024 Google, Inc|Copyright Google LLC',\n' SPDX-License-Identifier: Apache-2|

=== aralego.com
TLS: subject=CN = *.aralego.com|issuer=C = US, O = DigiCert Inc, OU = www.digicert.com, CN = Thawte TLS RSA CA G1|notBefore=Dec 23 00:00:00 2025 GMT|notAfter=Jan 23 23:59:59 2027 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://aralego.com/ CODE:403
TITLE: 403 Forbidden
COPYRIGHT: 

=== at-o.net
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://at-o.net/ CODE:000
TITLE: 
COPYRIGHT: 

=== atgsvcs.com
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://atgsvcs.com/ CODE:000
TITLE: 
COPYRIGHT: 

=== atwola.com
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://atwola.com/ CODE:000
TITLE: 
COPYRIGHT: 

=== awltovhc.com
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://awltovhc.com/ CODE:000
TITLE: 
COPYRIGHT: 

=== azure.com
TLS: subject=C = US, ST = WA, L = Redmond, O = Microsoft Corporation, CN = gamedev.microsoft.com|issuer=C = US, O = Microsoft Corporation, CN = Microsoft TLS G2 RSA CA OCSP 10|notBefore=Sep  3 11:47:29 2026 GMT|notAfter=Dec 12 10:47:29 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://azure.microsoft.com/en-us CODE:200
TITLE: Cloud Computing Services | Microsoft Azure
COPYRIGHT: 

=== bestbuy.com
TLS: subject=jurisdictionC = US, jurisdictionST = Minnesota, businessCategory = Private Organization, serialNumber = 1K-1056, C = US, ST = Minnesota, L = Richfield, O = "Best Buy Co., Inc.", CN = www.bestbuy.com|issuer=C = US, O = DigiCert Inc, CN = DigiCert Global G3 TLS ECC SHA384 2020 CA1|notBefore=Feb 11 00:00:00 2026 GMT|notAfter=Feb 11 23:59:59 2027 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.bestbuy.com/ CODE:301
TITLE: 
COPYRIGHT: 

=== bidr.io
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://bidr.io/ CODE:000
TITLE: 
COPYRIGHT: 

=== bilibili.com
TLS: subject=C = CN, ST = \E4\B8\8A\E6\B5\B7, L = \E4\B8\8A\E6\B5\B7, O = \E4\B8\8A\E6\B5\B7\E5\B9\BB\E7\94\B5\E4\BF\A1\E6\81\AF\E7\A7\91\E6\8A\80\E6\9C\89\E9\99\90\E5\85\AC\E5\8F\B8, CN = *.bilibili.com|issuer=C = BE, O = GlobalSign nv-sa, CN = GlobalSign RSA OV SSL CA 2018|notBefore=Nov 11 08:11:28 2025 GMT|notAfter=Dec 13 08:11:27 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.bilibili.com/ CODE:200
TITLE: 哔哩哔哩 (゜-゜)つロ 干杯~-bilibili
COPYRIGHT: copyright:e,pic:"http:\u002F\u002Fi0|copyright:e,pic:"http:\u002F\u002Fi2|

=== blogblog.com
TLS: subject=CN = *.blogger.com|issuer=C = US, O = Google Trust Services, CN = WR2|notBefore=Aug 10 08:37:21 2026 GMT|notAfter=Nov  2 08:37:20 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.blogblog.com/ CODE:404
TITLE: Error 404 (Not Found)!!1
COPYRIGHT: 

=== blogspot.com
TLS: subject=CN = misc-sni.blogspot.com|issuer=C = US, O = Google Trust Services, CN = WR2|notBefore=Aug 10 08:38:45 2026 GMT|notAfter=Nov  2 08:38:44 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.blogger.com/about/?bpli=1 CODE:200
TITLE: Blogger.com - Create a unique and beautiful blog easily.
COPYRIGHT: 

=== braze.com
TLS: subject=CN = braze.com|issuer=C = US, O = Let's Encrypt, CN = YE2|notBefore=Aug  7 07:18:12 2026 GMT|notAfter=Nov  5 07:18:11 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.braze.com/ CODE:200
TITLE: Braze Customer Engagement Platform
COPYRIGHT: ©  2026  Braze  All Rights Reserved   Cookies   Privacy Policy  Preference Center  Sitemap |© \",2026,\" Braze\"]}],[\"$\",\"div\",null,{\"className\":\"text-xs font-normal text-gray-|© \",2026,\" Braze\"]}],[\"$\",\"div\",null,{\"className\":\"text-xs font-normal text-gray-|

=== brightcove.net
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://brightcove.net/ CODE:000
TITLE: 
COPYRIGHT: 

=== britishairways.com
TLS: subject=businessCategory = Private Organization, serialNumber = 01777777, jurisdictionC = GB, C = GB, ST = Greater London, L = Harmondsworth, O = British Airways plc, CN = www.britishairways.com|issuer=C = BE, O = GlobalSign nv-sa, CN = GlobalSign GCC R3 EV TLS CA 2025|notBefore=Oct 30 08:56:05 2025 GMT|notAfter=Dec  1 08:56:04 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://britishairways.com/ CODE:200
TITLE: British Airways - Information Page
COPYRIGHT: 

=== cartfulsolutions.com
TLS: subject=CN = cartfulsolutions.com|issuer=C = US, O = Google Trust Services, CN = WE1|notBefore=Aug 28 20:27:49 2026 GMT|notAfter=Nov 26 21:27:39 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://cartful.com/ CODE:200
TITLE: Cartful — AI-Powered Guided Selling for Enterprise Ecommerce
COPYRIGHT: &copy; 2026 Cartful Solutions, Inc|

=== cdnbasket.net
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://cdnbasket.net/ CODE:000
TITLE: 
COPYRIGHT: 

=== cedexis.com
TLS: subject=C = US, ST = Florida, L = Fort Lauderdale, O = "Cloud Software Group, Inc.", CN = citrix.com|issuer=C = US, O = DigiCert Inc, CN = DigiCert Global G2 TLS RSA SHA256 2020 CA1|notBefore=Oct 14 00:00:00 2025 GMT|notAfter=Oct 13 23:59:59 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://cedexis.com/ CODE:200
TITLE: Cedexis
COPYRIGHT: 

=== cedscdn.it
TLS: subject=C = IT, ST = Firenze, O = Register spa, CN = *.dadapro.com|issuer=C = GB, O = Sectigo Limited, CN = Sectigo Public Server Authentication CA OV R36|notBefore=Oct  9 00:00:00 2025 GMT|notAfter=Oct 26 23:59:59 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://cedscdn.it/ CODE:000
TITLE: 
COPYRIGHT: 

=== chango.com
TLS: subject=CN = chango.com|issuer=C = US, O = Let's Encrypt, CN = YR2|notBefore=Jul 18 13:02:56 2026 GMT|notAfter=Oct 16 13:02:55 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.chango.com/ CODE:200
TITLE: Chango Interior &amp; Architectural Design Studio
COPYRIGHT: ©    |

=== cjponyparts.com
TLS: subject=CN = cjponyparts.com|issuer=C = US, O = Let's Encrypt, CN = YE1|notBefore=Aug 17 15:59:01 2026 GMT|notAfter=Nov 15 15:59:00 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://cjponyparts.com/ CODE:403
TITLE: Just a moment...
COPYRIGHT: 

=== cloudfront.net
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://cloudfront.net/ CODE:000
TITLE: 
COPYRIGHT: 

=== cnevids.com
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://cnevids.com/ CODE:000
TITLE: 
COPYRIGHT: 

=== cnn.com
TLS: subject=C = US, ST = New York, L = New York, O = "Warner Bros. Discovery, Inc.", CN = cnn.com|issuer=C = BE, O = GlobalSign nv-sa, CN = GlobalSign Atlas ECCR5 OV TLS CA 2025 Q2|notBefore=Apr  2 18:49:02 2026 GMT|notAfter=Oct 18 18:49:01 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://edition.cnn.com/ CODE:200
TITLE: Breaking News, Latest News and Videos | CNN
COPYRIGHT: copyright-text,|copyright-text{color:var(--theme-footer-copy-accent);margin:24px auto 0}|copyright-text>a{color:var(--theme-footer-copy-accent);text-decoration:none}|

=== cnzz.com
TLS: subject=C = CN, ST = Zhejiang, L = Hangzhou, O = "Alibaba (China) Technology Co., Ltd.", CN = *.umeng.com|issuer=C = BE, O = GlobalSign nv-sa, CN = GlobalSign GCC R46 OV TLS CA 2025|notBefore=Aug  3 03:32:07 2026 GMT|notAfter=Feb 18 03:26:26 2027 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://cnzz.com/ CODE:000
TITLE: 
COPYRIGHT: 

=== collective-media.net
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://collective-media.net/ CODE:000
TITLE: 
COPYRIGHT: 

=== comcast.com
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://comcast.com/ CODE:000
TITLE: 
COPYRIGHT: 

=== company-target.com
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://company-target.com/ CODE:000
TITLE: 
COPYRIGHT: 

=== compass-fit.jp
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://compass-fit.jp/ CODE:000
TITLE: 
COPYRIGHT: 

=== contentabc.com
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://contentabc.com/ CODE:000
TITLE: 
COPYRIGHT: 

=== conviva.com
TLS: subject=CN = conviva.com|issuer=C = US, O = Google Trust Services, CN = WE1|notBefore=Jul 19 17:29:42 2026 GMT|notAfter=Oct 17 18:29:38 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.conviva.ai/ CODE:200
TITLE: Conviva | Real-Time Experience Intelligence for AI Agents
COPYRIGHT: Copyright &copy; 2026 Conviva|Copyright &copy; 2026 Conviva|

=== cookiefirst.com
TLS: subject=CN = *.cookiefirst.com|issuer=C = GB, O = Sectigo Limited, CN = Sectigo Public Server Authentication CA DV R36|notBefore=Dec 10 00:00:00 2025 GMT|notAfter=Dec 16 23:59:59 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://cookiefirst.com/ CODE:200
TITLE: Cookie Consent GDPR, ePR, CCPA, LGPD compliant | CookieFirst
COPYRIGHT: copyright li a i, #footer-outer #copyright p|© Digital Data Solutions BV 2024 |

=== coverartarchive.org
TLS: subject=CN = coverartarchive.org|issuer=C = US, O = Let's Encrypt, CN = YE1|notBefore=Aug 25 01:33:52 2026 GMT|notAfter=Nov 23 01:33:51 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://coverartarchive.org/ CODE:200
TITLE: Cover Art Archive
COPYRIGHT: copyrighted by their respective copyright owners|

=== cratecamera.com
TLS: subject=CN = cratecamera.com|issuer=C = US, O = Let's Encrypt, CN = YE1|notBefore=Jul 27 14:30:09 2026 GMT|notAfter=Oct 25 14:30:08 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://cratecamera.com/ CODE:404
TITLE: 404 Not Found
COPYRIGHT: copyright access control in accordance with the Digital Millennium Copyright Act and related intern|copyright laws, enabling privacy consent, including for GDPR, and supporting subscriptions and dona|copyrighted content, logging into their subscription, recording consent, or configuring website fea|

=== criteo.net
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://criteo.net/ CODE:000
TITLE: 
COPYRIGHT: 

=== crsspxl.com
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://crsspxl.com/ CODE:000
TITLE: 
COPYRIGHT: 

=== crwdcntrl.net
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
TITLE: 
COPYRIGHT: 

=== ctnsnet.com
TLS: subject=C = GB, L = London, O = Crimtan Holdings Ltd, CN = *.ctnsnet.com|issuer=C = US, O = DigiCert Inc, CN = DigiCert Global G2 TLS RSA SHA256 2020 CA1|notBefore=Jul 26 00:00:00 2026 GMT|notAfter=Feb  9 23:59:59 2027 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://ctnsnet.com/ CODE:404
TITLE: 404 Not Found
COPYRIGHT: 

=== cudasvc.com
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://cudasvc.com/ CODE:000
TITLE: 
COPYRIGHT: 

=== cxt.ms
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://cxt.ms/ CODE:000
TITLE: 
COPYRIGHT: 

=== disquscdn.com
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://disquscdn.com/ CODE:000
TITLE: 
COPYRIGHT: 

=== dnb.com
TLS: subject=CN = dnb.com|issuer=C = US, O = Let's Encrypt, CN = YE1|notBefore=Aug 22 21:59:37 2026 GMT|notAfter=Nov 20 21:59:36 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.dnb.com/de-ch/ CODE:200
TITLE: Intelligente Daten für erfolgreiche Geschäfte | Dun &amp; Bradstreet
COPYRIGHT: © Dun &amp; Bradstreet, Inc|copyright":"© Dun \u0026 Bradstreet, Inc|

=== domdex.com
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://domdex.com/ CODE:000
TITLE: 
COPYRIGHT: 

=== elfsight.com
TLS: subject=CN = elfsight.com|issuer=C = US, O = Let's Encrypt, CN = YE1|notBefore=Sep  1 20:11:42 2026 GMT|notAfter=Nov 30 20:11:41 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://elfsight.com/ CODE:200
TITLE: 90+ Website Widgets — To Grow Your Business — Elfsight
COPYRIGHT: &copy; Elfsight |

=== emxdgt.com
TLS: subject=CN = emxdgt.com|issuer=C = US, O = Amazon, CN = Amazon RSA 2048 M01|notBefore=Apr 19 00:00:00 2026 GMT|notAfter=Nov  2 23:59:59 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://emxdgt.com/ CODE:200
TITLE: Redirecting...
COPYRIGHT: 

=== everestjs.net
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
TITLE: 
COPYRIGHT: 

=== experian.com
TLS: subject=serialNumber = 1992801, jurisdictionC = US, jurisdictionST = California, businessCategory = Private Organization, C = US, ST = Texas, O = "Experian Information Solutions, Inc.", CN = www.experian.com|issuer=C = GB, O = Sectigo Limited, CN = Sectigo Public Server Authentication CA EV R36|notBefore=Jul 13 00:00:00 2026 GMT|notAfter=Jan 27 23:59:59 2027 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.experian.com/ CODE:200
TITLE: Experian: Credit Report, FICO® Score &amp; Financial Tools
COPYRIGHT: © 2026 Experian|copyright, or trademark is for identification and reference purposes only and does not imply any as|copyright or trademark holder of their product or brand|

=== eyeota.net
TLS: subject=CN = eyeota.com|issuer=C = LV, L = Riga, O = GoGetSSL, CN = GoGetSSL RSA DV CA|notBefore=Mar 10 00:00:00 2026 GMT|notAfter=Mar 16 23:59:59 2027 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://eyeota.net/ CODE:000
TITLE: 
COPYRIGHT: 

=== farfetch-contents.com
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://farfetch-contents.com/ CODE:000
TITLE: 
COPYRIGHT: 

=== flashtalking.com
TLS: subject=C = GB, L = LONDON, O = SIMPLICITY MARKETING LIMITED, CN = flashtalking.com|issuer=C = US, O = DigiCert Inc, CN = DigiCert Global G2 TLS RSA SHA256 2020 CA1|notBefore=Aug 31 00:00:00 2026 GMT|notAfter=Mar 17 23:59:59 2027 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://flashtalking.com/ CODE:000
TITLE: 
COPYRIGHT: 

=== fontawesome.com
TLS: subject=CN = fontawesome.com|issuer=C = US, O = Google Trust Services, CN = WE1|notBefore=Aug 12 22:43:58 2026 GMT|notAfter=Nov 10 23:43:53 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://fontawesome.com/ CODE:200
TITLE: Font Awesome
COPYRIGHT: 

=== force.com
TLS: subject=C = US, ST = California, L = San Francisco, O = "Salesforce, Inc.", CN = salesforce.com|issuer=C = US, O = DigiCert Inc, CN = DigiCert Global G3 TLS ECC SHA384 2020 CA1|notBefore=Mar 18 00:00:00 2026 GMT|notAfter=Oct  2 23:59:59 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.salesforce.com/404/ CODE:404
TITLE: 
COPYRIGHT: 

=== forter.com
TLS: subject=CN = forter.com|issuer=C = US, O = Google Trust Services, CN = WE1|notBefore=Aug 13 21:34:01 2026 GMT|notAfter=Nov 11 22:33:57 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.forter.com/ CODE:200
TITLE: Forter &#8211; Agentic Intelligence you can trust
COPYRIGHT: &copy;&nbsp;Forter |

=== globo.com
TLS: subject=CN = globo.com|issuer=C = US, O = Let's Encrypt, CN = YR1|notBefore=Sep  2 05:13:03 2026 GMT|notAfter=Dec  1 05:13:02 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.globo.com/ CODE:200
TITLE: globo.com - Absolutamente tudo sobre notícias, esportes e entretenimento
COPYRIGHT: Copyright (c) Facebook, Inc|Copyright (c) Facebook, Inc|copyright__container{display:flex;align-items:center}|

=== glomex.com
TLS: subject=CN = glomex.com|issuer=C = US, O = Amazon, CN = Amazon RSA 2048 M04|notBefore=Oct 11 00:00:00 2025 GMT|notAfter=Nov  8 23:59:59 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.glomex.com/de/ CODE:200
TITLE: glomex - Ihr Premium Video Marktplatz - Jetzt kostenlos starten
COPYRIGHT: copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&|

=== go-mpulse.net
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://go-mpulse.net/ CODE:000
TITLE: 
COPYRIGHT: 

=== google.nl
TLS: subject=CN = *.google.nl|issuer=C = US, O = Google Trust Services, CN = WR2|notBefore=Aug 10 08:40:43 2026 GMT|notAfter=Nov  2 08:40:42 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.google.com/ CODE:200
TITLE: Google
COPYRIGHT: 

=== govdelivery.com
TLS: subject=CN = about.govdelivery.com|issuer=C = US, O = Let's Encrypt, CN = YR1|notBefore=Aug 30 14:07:44 2026 GMT|notAfter=Nov 28 14:07:43 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://granicus.com/ CODE:200
TITLE: Granicus | The Citizen Experience Platform for Government
COPYRIGHT: &copy; 2026 Granicus
|

=== govx.com
TLS: subject=CN = govx.com|issuer=C = BE, O = GlobalSign nv-sa, CN = GlobalSign Atlas R3 DV TLS CA 2025 Q4|notBefore=Dec  8 19:00:23 2025 GMT|notAfter=Jan  9 19:00:22 2027 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.govx.com/ CODE:200
TITLE: Military &amp; Government Discounts on 1000&#x2B; Brands | GOVX
COPYRIGHT: 

=== gssprt.jp
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://gssprt.jp/ CODE:000
TITLE: 
COPYRIGHT: 

=== gstatic.com
TLS: subject=CN = *.gstatic.com|issuer=C = US, O = Google Trust Services, CN = WR2|notBefore=Aug 10 08:39:04 2026 GMT|notAfter=Nov  2 08:39:03 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.gstatic.com/ CODE:404
TITLE: Error 404 (Not Found)!!1
COPYRIGHT: 

=== gumgum.com
TLS: subject=CN = *.gumgum.com|issuer=C = US, O = Amazon, CN = Amazon RSA 2048 M04|notBefore=Nov 12 00:00:00 2025 GMT|notAfter=Dec 11 23:59:59 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://gumgum.com/ CODE:200
TITLE: GumGum | The Mindset Company™ – CTV, OLV &amp; High Impact Display Advertising
COPYRIGHT: ©  {{Year}}  GumGum, Inc|

=== hearst.com
TLS: subject=CN = hearst.com|issuer=C = US, O = Certainly, CN = Certainly Intermediate R1|notBefore=Sep  3 05:06:58 2026 GMT|notAfter=Oct  3 05:06:57 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.hearst.com/ CODE:200
TITLE: Home - HEARST | Hearst
COPYRIGHT: CopyrightText: (c) 2000 Liferay, Inc|CopyrightText: (c) 2000 Liferay, Inc|CopyrightText: (c) 2000 Liferay, Inc|

=== heraldcorp.com
TLS: subject=CN = *.heraldcorp.com|issuer=C = GB, ST = Greater Manchester, L = Salford, O = Sectigo Limited, CN = Sectigo RSA Domain Validation Secure Server CA|notBefore=Jan 12 00:00:00 2026 GMT|notAfter=Jan 22 23:59:59 2027 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://heraldcorp.com/ CODE:200
TITLE: 
COPYRIGHT: 

=== histats.com
TLS: subject=CN = histats.com|issuer=C = US, O = Let's Encrypt, CN = YR1|notBefore=Aug 29 14:40:24 2026 GMT|notAfter=Nov 27 14:40:23 2026 GMT|
RDAP: 
RDAP-registrar: OVH sas
FINAL:https://www.histats.com/ CODE:200
TITLE: Histats.com Counter ,the free web stats and stat counter, hit counter, free web tracker and tracking tools, professional and free!!
COPYRIGHT: 

=== hitc.com
TLS: subject=CN = hitc.com|issuer=C = US, O = Google Trust Services, CN = WE1|notBefore=Aug  5 00:54:48 2026 GMT|notAfter=Nov  3 01:54:33 2026 GMT|
RDAP: 
RDAP-registrar: 123-Reg Limited
FINAL:https://hitc.com/ CODE:403
TITLE: Just a moment...
COPYRIGHT: 

=== hitslink.com
TLS: subject=CN = hitslink.com|issuer=C = US, O = Let's Encrypt, CN = YR1|notBefore=Jun 21 00:57:30 2026 GMT|notAfter=Sep 19 00:57:29 2026 GMT|
RDAP: 
RDAP-registrar: Network Solutions, LLC
FINAL:https://hitslink.com/ CODE:200
TITLE: Web analytics | HitsLink
COPYRIGHT: ©2012 Net Applications, Inc|

=== hotjar.io
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://hotjar.io/ CODE:000
TITLE: 
COPYRIGHT: 

=== hqseek.com
TLS: subject=CN = *.hqseek.com|issuer=C = US, O = Let's Encrypt, CN = YE1|notBefore=Aug  5 10:31:34 2026 GMT|notAfter=Nov  3 10:31:33 2026 GMT|
RDAP: 
RDAP-registrar: DNC Holdings, Inc.
FINAL:https://hqporn.pics/ CODE:200
TITLE: Free HQ Porn Pics, Nude Babes, Sexy Nudes - HQporn.pics
COPYRIGHT: 

=== hs-analytics.net
TLS: <no handshake>|
RDAP: 
RDAP-registrar: MarkMonitor Inc.
FINAL:https://hs-analytics.net/ CODE:000
TITLE: 
COPYRIGHT: 

=== hs-scripts.com
TLS: <no handshake>|
RDAP: 
RDAP-registrar: MarkMonitor Inc.
FINAL:https://hs-scripts.com/ CODE:000
TITLE: 
COPYRIGHT: 

=== htplayground.com
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://htplayground.com/ CODE:000
TITLE: 
COPYRIGHT: 

=== i.ua
TLS: subject=CN = i.ua|issuer=C = US, O = Google Trust Services, CN = WE1|notBefore=Aug 10 06:18:46 2026 GMT|notAfter=Nov  8 07:18:36 2026 GMT|
RDAP: Digital Ventures LLC
RDAP-registrar: Internet Invest LLC
FINAL:https://www.i.ua/ CODE:200
TITLE: 
COPYRIGHT: &copy;&nbsp;I|copyright {|copyright {|

=== ibb.co
TLS: subject=CN = ibb.co|issuer=C = US, O = Let's Encrypt, CN = YE1|notBefore=Aug 12 21:52:48 2026 GMT|notAfter=Nov 10 21:52:47 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://imgbb.com/ CODE:200
TITLE: ImgBB — Upload Image — Free Image Hosting
COPYRIGHT: 

=== id5-sync.com
TLS: subject=CN = id5-sync.com|issuer=C = US, O = Let's Encrypt, CN = YE1|notBefore=Sep  1 11:01:48 2026 GMT|notAfter=Nov 30 11:01:47 2026 GMT|
RDAP: 
RDAP-registrar: Cloudflare, Inc.
FINAL:https://id5-sync.com/ CODE:200
TITLE: 
COPYRIGHT: 

=== iqzone.com
TLS: subject=CN = iqzone.com|issuer=C = US, O = Let's Encrypt, CN = YR1|notBefore=Jul  6 17:15:06 2026 GMT|notAfter=Oct  4 17:15:05 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://iqzone.com/ CODE:200
TITLE: IQzone — Programmatic Intelligence Platform
COPYRIGHT: &copy; 2026 IQzone|

=== ispot.tv
TLS: subject=CN = *.ispot.tv|issuer=C = US, O = Amazon, CN = Amazon RSA 2048 M01|notBefore=Jan 23 00:00:00 2026 GMT|notAfter=Feb 21 23:59:59 2027 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.ispot.tv:443/ CODE:200
TITLE: iSpot: The New Standard for TV Ad Measurement
COPYRIGHT: © 2026 iSpot|

=== jdpower.com
TLS: subject=C = US, ST = Michigan, O = J.D. Power, CN = www.jdpower.com|issuer=C = GB, O = Sectigo Limited, CN = Sectigo Public Server Authentication CA OV R36|notBefore=Oct 28 00:00:00 2025 GMT|notAfter=Oct 28 23:59:59 2026 GMT|
RDAP: 
RDAP-registrar: CSC Corporate Domains, Inc.
FINAL:https://www.jdpower.com/ CODE:403
TITLE: Attention Required! | Cloudflare
COPYRIGHT: 

=== jobs2careers.com
TLS: subject=CN = *.jobs2careers.com|issuer=C = US, O = Amazon, CN = Amazon RSA 2048 M01|notBefore=Oct 14 00:00:00 2025 GMT|notAfter=Nov 11 23:59:59 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.jobs2careers.com/ CODE:200
TITLE: Jobs and Employment Near Me Now Hiring September 2026 | Jobs2Careers
COPYRIGHT: ©  2026  Jobs2Careers   |©  2026  Jobs2Careers   Privacy Policy  Terms of Use  |

=== juicer.cc
TLS: subject=CN = juicer.cc|issuer=C = US, O = Amazon, CN = Amazon RSA 2048 M04|notBefore=Oct 24 00:00:00 2025 GMT|notAfter=Nov 21 23:59:59 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://juicer.cc/ CODE:200
TITLE: ユーザー分析DMP LOGLY Audience Analytics(旧Juicer)|ユーザー分析やA/Bテスト、NPSが無料で
COPYRIGHT: Copyright(C) LOGLY Audience Analytics |

=== kameleoon.io
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://kameleoon.io/ CODE:000
TITLE: 
COPYRIGHT: 

=== klarna.app
TLS: subject=CN = klarna.com|issuer=C = US, O = Amazon, CN = Amazon RSA 2048 M01|notBefore=Oct 10 00:00:00 2025 GMT|notAfter=Nov  8 23:59:59 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.klarna.com/ch/klarna-app/ CODE:200
TITLE: Klarna App | Flexibel bezahlen und dein Geld verwalten
COPYRIGHT: CopyrightAddition:en","content":{"contentType":"uiElement","id":"4G0DXZohJ7KSQ57X63z1hy","type":"En|CopyrightAddition","content":"Images on this website may be AI-generated|copyright":"Copyright © 2005-2025 Klarna Bank AB (publ)|

=== klaviyo.com
TLS: subject=CN = klaviyo.com|issuer=C = US, O = Amazon, CN = Amazon RSA 2048 M04|notBefore=Jan 17 00:00:00 2026 GMT|notAfter=Feb 15 23:59:59 2027 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.klaviyo.com/de/ CODE:200
TITLE: Klaviyo: KI-E-Mail-Marketing, SMS uns WhatsApp | B2C CRM
COPYRIGHT: Copyright © 2026 Klaviyo|

=== km0trk.com
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://km0trk.com/ CODE:000
TITLE: 
COPYRIGHT: 

=== ksearchnet.com
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://ksearchnet.com/ CODE:000
TITLE: 
COPYRIGHT: 

=== lduhtrp.net
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://lduhtrp.net/ CODE:000
TITLE: 
COPYRIGHT: 

=== liadm.com
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://liadm.com/ CODE:000
TITLE: 
COPYRIGHT: 

=== lijit.com
TLS: subject=CN = *.lijit.com|issuer=C = US, O = Amazon, CN = Amazon RSA 2048 M01|notBefore=Nov 27 00:00:00 2025 GMT|notAfter=Dec 25 23:59:59 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://lijit.com/ CODE:200
TITLE: Lijit is an ad serving domain owned by Sovrn Holdings, Inc.
COPYRIGHT: 

=== loopme.me
TLS: subject=CN = loopme.com|issuer=C = US, O = Let's Encrypt, CN = YR1|notBefore=Aug 17 08:31:08 2026 GMT|notAfter=Nov 15 08:31:07 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://loopme.me/ CODE:204
TITLE: 
COPYRIGHT: 

=== makaira.io
TLS: subject=CN = *.makaira.io|issuer=C = US, O = Let's Encrypt, CN = YR1|notBefore=Jul  7 22:16:10 2026 GMT|notAfter=Oct  5 22:16:09 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.makaira.io/ CODE:200
TITLE: Headless Commerce Software | Composable Commerce | Makaira.io
COPYRIGHT: 

=== mapixl.com
TLS: subject=CN = mapixl.com|issuer=C = US, O = Google Trust Services, CN = WE1|notBefore=Jul 27 15:00:49 2026 GMT|notAfter=Oct 25 16:00:46 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://mapixl.com/ CODE:403
TITLE: Attention Required! | Cloudflare
COPYRIGHT: 

=== marphezis.com
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://marphezis.com/ CODE:000
TITLE: 
COPYRIGHT: 

=== medallia.com.au
TLS: subject=CN = medallia.com|issuer=C = US, O = Amazon, CN = Amazon RSA 2048 M01|notBefore=Nov 16 00:00:00 2025 GMT|notAfter=Dec 15 23:59:59 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.medallia.com/ CODE:200
TITLE: Experience Management Software Platform &#8211; Medallia &#8211; Experience Management Software
COPYRIGHT: Copyright &copy; 2026 Medallia, Inc|&copy; Medallia®, the Medallia logo, and the names and marks associated with Medallia’s products|

=== medchatapp.com
TLS: subject=CN = *.medchatapp.com|issuer=C = US, ST = Arizona, L = Scottsdale, O = "GoDaddy.com, Inc.", OU = http://certs.godaddy.com/repository/, CN = Go Daddy Secure Certificate Authority - G2|notBefore=Oct 24 16:12:50 2025 GMT|notAfter=Nov 25 16:12:50 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://medchatapp.com/site/ CODE:200
TITLE: Better Healthcare. Built on AI.
COPYRIGHT: © Medchat, LLC 2025          Better patient experiences with Medchat·ai                    |© Medchat, LLC 2025          Better patient experiences with Medchat·ai                    |© Medchat, LLC 2025           Better patient experiences with Medchat·ai                   |

=== mediaset.es
TLS: subject=C = ES, ST = Madrid, L = Madrid, O = "GRUPO AUDIOVISUAL MEDIASET ESPA\C3\91A COMUNICACION, SAU", CN = seguro.mediaset.es|issuer=C = US, O = DigiCert Inc, OU = www.digicert.com, CN = GeoTrust TLS RSA CA G1|notBefore=Aug  4 00:00:00 2026 GMT|notAfter=Feb 18 23:59:59 2027 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.mediaset.es/ CODE:403
TITLE: Access Denied
COPYRIGHT: 

=== ml.com
TLS: subject=jurisdictionC = US, jurisdictionST = Delaware, businessCategory = Private Organization, serialNumber = 2927442, C = US, ST = North Carolina, L = Charlotte, O = Bank of America Corporation, CN = ml.com|issuer=C = US, O = DigiCert Inc, CN = DigiCert EV RSA CA G2|notBefore=Aug 28 00:00:00 2026 GMT|notAfter=Feb 10 23:59:59 2027 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.ml.com/ CODE:200
TITLE: Wealth Management and Financial Services from Merrill Lynch
COPYRIGHT: &copy;",year:"2026",boaCorp:"Bank of America Corporation|&copy;",year:"2026",boaCorp:"Bank of America Corporation|

=== mmstat.com
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://mmstat.com/ CODE:000
TITLE: 
COPYRIGHT: 

=== mountain.com
TLS: subject=CN = mountain.com|issuer=C = US, O = Let's Encrypt, CN = YE1|notBefore=Aug  4 05:12:48 2026 GMT|notAfter=Nov  2 05:12:47 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://mountain.com/ CODE:200
TITLE: Connected TV Performance Marketing Platform - MNTN
COPYRIGHT: Copyright &copy; 2026 MNTN, Inc|

=== mparticle.com
TLS: subject=CN = mparticle.com|issuer=C = US, O = Let's Encrypt, CN = YR1|notBefore=Jul 28 04:41:36 2026 GMT|notAfter=Oct 26 04:41:35 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.mparticle.com/ CODE:200
TITLE: Performance Made Easy | mParticle Customer Data Platform
COPYRIGHT: © 2026 mParticle, Inc|copyright\":null,\"url\":\"https://images|copyright\":null,\"url\":\"https://mparticle-next|

=== myaccountaccess.com
TLS: subject=C = US, ST = Minnesota, L = Minneapolis, O = U.S. Bank National Association, CN = supplierpreferpay.com|issuer=C = US, O = DigiCert Inc, CN = DigiCert Global G2 TLS RSA SHA256 2020 CA1|notBefore=Aug 18 00:00:00 2026 GMT|notAfter=Mar  4 23:59:59 2027 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.myaccountaccess.com/ CODE:200
TITLE: Log In
COPYRIGHT: 

=== newrelic.com
TLS: subject=C = US, ST = California, L = San Francisco, O = "New Relic, Inc.", CN = *.newrelic.com|issuer=C = US, O = DigiCert Inc, CN = DigiCert Global G2 TLS RSA SHA256 2020 CA1|notBefore=Feb  9 00:00:00 2026 GMT|notAfter=Feb  8 23:59:59 2027 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://newrelic.com/ CODE:200
TITLE: AI-powered Observability
COPYRIGHT: ©2008-26 New Relic, Inc|

=== newsmemory.com
TLS: subject=CN = *.newsmemory.com|issuer=C = GB, O = Sectigo Limited, CN = Sectigo Public Server Authentication CA DV R36|notBefore=Mar  9 00:00:00 2026 GMT|notAfter=Apr  9 23:59:59 2027 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.newsmemory.com/eedition/ CODE:200
TITLE: e-Edition - A suite of e-publishing solutions by Tecnavia
COPYRIGHT: © Copyright Tecnavia 2015 - All rights reserved |

=== nofraud.com
TLS: subject=CN = nofraud.com|issuer=C = US, O = Let's Encrypt, CN = YE2|notBefore=Aug  5 03:02:01 2026 GMT|notAfter=Nov  3 03:02:00 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://wyllo.ai/ CODE:200
TITLE: Ecommerce Fraud Protection &amp; Risk Intelligence Platform | Wyllo
COPYRIGHT: ©2026 Wyllo|

=== offshoregeology.com
TLS: subject=CN = offshoregeology.com|issuer=C = US, O = Let's Encrypt, CN = YE1|notBefore=Jun 22 20:14:28 2026 GMT|notAfter=Sep 20 20:14:27 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://offshoregeology.com/ CODE:404
TITLE: 404 Not Found
COPYRIGHT: copyright access control in accordance with the Digital Millennium Copyright Act and related intern|copyright laws, enabling privacy consent, including for GDPR, and supporting subscriptions and dona|copyrighted content, logging into their subscription, recording consent, or configuring website fea|

=== omtrdc.net
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://omtrdc.net/ CODE:000
TITLE: 
COPYRIGHT: 

=== onecount.net
TLS: subject=CN = www.one-count.com|issuer=C = US, ST = VA, L = Herndon, O = Network Solutions L.L.C., CN = Network Solutions DV Server CA 2|notBefore=Apr 23 00:00:00 2020 GMT|notAfter=Apr  6 23:59:59 2022 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://onecount.net/ CODE:000
TITLE: 
COPYRIGHT: 

=== opti-digital.com
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://opti-digital.com/ CODE:000
TITLE: 
COPYRIGHT: 

=== owneriq.net
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://owneriq.net/ CODE:000
TITLE: 
COPYRIGHT: 

=== pages02.net
TLS: subject=CN = pages00.net|issuer=C = US, O = Amazon, CN = Amazon RSA 2048 M04|notBefore=Nov 23 00:00:00 2025 GMT|notAfter=Dec 22 23:59:59 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:http://contentz.rm02.net/lp/static/notfound.html CODE:200
TITLE: Page not Found
COPYRIGHT: © Copyright IBM Corp|Copyright Office|

=== paypal.com
TLS: subject=C = US, ST = California, L = San Jose, O = "PayPal, Inc.", CN = paypal.com|issuer=C = US, O = DigiCert Inc, CN = DigiCert Global G2 TLS RSA SHA256 2020 CA1|notBefore=May 11 00:00:00 2026 GMT|notAfter=Nov 25 23:59:59 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.paypal.com/ch/home CODE:200
TITLE: Geld senden und anfordern, einkaufen, Zahlungen verwalten und vieles mehr | PayPal CH
COPYRIGHT: © 1999–{{currentYear}}","target":"_self"},{"id":"6ouITb6s7Pkhdn7VkfJmh2","text":"Barrierefr|© 1999–2026     Barrierefreiheit    Edition    Datenschutz    Cookies    AGB       PayPal P|

=== primis.tech
TLS: subject=CN = primis.tech|issuer=C = US, ST = Arizona, L = Scottsdale, O = "GoDaddy.com, Inc.", OU = http://certs.godaddy.com/repository/, CN = Go Daddy Secure Certificate Authority - G2|notBefore=May  3 13:52:57 2026 GMT|notAfter=Nov 17 13:52:57 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.primis.tech/ CODE:200
TITLE: The Video Discovery Platform | primis
COPYRIGHT: © 2024 Primis, All right Reserved							 |

=== pushnami.com
TLS: subject=CN = *.pushnami.com|issuer=C = US, O = Amazon, CN = Amazon RSA 2048 M01|notBefore=Dec  5 00:00:00 2025 GMT|notAfter=Jan  3 23:59:59 2027 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://pushnami.com/ CODE:200
TITLE: The Leading Push Advertising Network for Affiliates &amp; Marketers - Pushnami
COPYRIGHT: © 2017-2021 Pushnami|

=== qbox.me
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://qbox.me/ CODE:000
TITLE: 
COPYRIGHT: 

=== quantserve.com
TLS: subject=CN = quantserve.com|issuer=C = US, O = Let's Encrypt, CN = YR1|notBefore=Aug 13 03:34:00 2026 GMT|notAfter=Nov 11 03:33:59 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://quantserve.com/ CODE:503
TITLE: Quantcast: Measure + Advertise
COPYRIGHT: 

=== radio-canada.ca
TLS: subject=CN = radio-canada.ca|issuer=C = US, O = Let's Encrypt, CN = YR1|notBefore=Aug  9 11:19:39 2026 GMT|notAfter=Nov  7 11:19:38 2026 GMT|
RDAP: Canadian Broadcasting Corporation / Réjean Lafrance
RDAP-registrar: Authentic Web Inc.
FINAL:https://ici.radio-canada.ca/ CODE:200
TITLE: Radio-Canada.ca | Information, radio, télé, sports, art
COPYRIGHT: © Société Radio‑Canada  2026 |

=== report-uri.io
TLS: subject=CN = report-uri.io|issuer=C = US, O = Google Trust Services, CN = WE1|notBefore=Jul  9 17:44:14 2026 GMT|notAfter=Oct  7 18:44:01 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://report-uri.com/ CODE:403
TITLE: Just a moment...
COPYRIGHT: 

=== researchnow.com
TLS: subject=CN = *.opinionology.com|issuer=C = US, O = Amazon, CN = Amazon RSA 2048 M04|notBefore=Jun  7 00:00:00 2026 GMT|notAfter=Dec 21 23:59:59 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.dynata.com:443/ CODE:200
TITLE: World’s Largest First Party Data Platform | Dynata - World’s Largest First Party Data Platform
COPYRIGHT: copyright-text{width:100%;text-align:center;margin-top:5px}footer |copyright-text::before{margin:0;display:none}footer |© 2026 Dynata|

=== reson8.com
TLS: <no handshake>|
RDAP: 
RDAP-registrar: IONOS SE
TITLE: 
COPYRIGHT: 

=== responsiveads.com
TLS: subject=CN = responsiveads.com|issuer=C = US, O = Amazon, CN = Amazon RSA 2048 M04|notBefore=Jul  9 00:00:00 2026 GMT|notAfter=Jan 22 23:59:59 2027 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://responsiveads.com/ CODE:200
TITLE: ResponsiveAds | Simplify Resizing &amp; High-Impact HTML5 Display Ads
COPYRIGHT: &copy;2026 RESPONSIVEADS, INC|

=== richrelevance.com
TLS: subject=C = US, ST = California, L = San Francisco, O = "RichRelevance, Inc.", CN = *.richrelevance.com|issuer=C = US, ST = Arizona, L = Scottsdale, O = "GoDaddy.com, Inc.", OU = http://certs.godaddy.com/repository/, CN = Go Daddy Secure Certificate Authority - G2|notBefore=Nov  3 17:48:21 2025 GMT|notAfter=Dec  5 17:48:21 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://richrelevance.com/ CODE:500
TITLE: Personalization Technology &amp; Personalization Solutions | RichRelevance
COPYRIGHT: 

=== sa-as.com
TLS: <no handshake>|
RDAP: 
RDAP-registrar: MarkMonitor Inc.
TITLE: 
COPYRIGHT: 

=== sapo.io
TLS: subject=CN = sapo.io|issuer=C = US, O = Let's Encrypt, CN = YR2|notBefore=Jul  9 02:31:54 2026 GMT|notAfter=Oct  7 02:31:53 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.sapo.io/ CODE:200
TITLE: Stratus CDN 
COPYRIGHT: 

=== sendtonews.com
TLS: subject=CN = sendtonews.com|issuer=C = US, O = Amazon, CN = Amazon RSA 2048 M01|notBefore=Aug 22 00:00:00 2026 GMT|notAfter=Mar  7 23:59:59 2027 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.minutegroup.com/platform/video CODE:200
TITLE: Minute Video Platform for Publishers - Minute
COPYRIGHT: © 2026 Minute|

=== sharethis.com
TLS: subject=CN = sharethis.com|issuer=C = US, O = Amazon, CN = Amazon RSA 2048 M04|notBefore=Feb 17 00:00:00 2026 GMT|notAfter=Mar 17 23:59:59 2027 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://sharethis.com/ CODE:200
TITLE: ShareThis | Share Buttons | Website Tools | Behavioral Intelligence
COPYRIGHT: &copy; 2026 ShareThis|

=== simpli.fi
TLS: subject=CN = simpli.fi|issuer=C = US, O = Let's Encrypt, CN = YE1|notBefore=Aug 17 15:33:54 2026 GMT|notAfter=Nov 15 15:33:53 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://simpli.fi/ CODE:200
TITLE: Real-World Media Platform | Programmatic DSP | Simpli.fi
COPYRIGHT: © 2026 Simpli|© 2026 Simpli|

=== smartadserver.com
TLS: subject=CN = smartadserver.com|issuer=C = US, O = Google Trust Services, CN = WR3|notBefore=Jul 21 04:57:02 2026 GMT|notAfter=Oct 19 05:50:54 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.equativ.com/ CODE:200
TITLE: Equativ — The Global End-to-End Media Platform
COPYRIGHT: 

=== snapengage.com
TLS: subject=CN = snapengage.com|issuer=C = US, O = Google Trust Services, CN = WE1|notBefore=Aug 31 19:36:28 2026 GMT|notAfter=Nov 29 20:36:22 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://snapengage.com/ CODE:200
TITLE: Live Chat Software For Sales &amp; Support - Chatbots &amp; Live Chat
COPYRIGHT: &copy;2026 SnapEngage All rights reserved|

=== solarwinds.com
TLS: subject=C = US, ST = Texas, L = Austin, O = "Solarwinds Worldwide, LLC", CN = *.solarwinds.com|issuer=C = US, O = DigiCert Inc, CN = DigiCert Global G2 TLS RSA SHA256 2020 CA1|notBefore=Apr 27 00:00:00 2026 GMT|notAfter=Nov 11 23:59:59 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.solarwinds.com/ CODE:200
TITLE: Observability, Database, and IT Service Management | SolarWinds
COPYRIGHT: ©2026 SolarWinds Worldwide, LLC|copyright\"]},\"component\":{\"name\":\"SWDC Global Simple Footer\",\"options\":{\"theme\":\"gray\"|copyright\":\"©2026 SolarWinds Worldwide, LLC|

=== sparkasse.de
TLS: subject=CN = sparkasse.de|issuer=C = US, O = Let's Encrypt, CN = YE1|notBefore=Jul 29 06:44:45 2026 GMT|notAfter=Oct 27 06:44:44 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.sparkasse.de/ CODE:200
TITLE: Sparkasse: Produkte und Services | Sparkasse.de
COPYRIGHT: 

=== spot.im
TLS: subject=CN = spot.im|issuer=C = US, O = Amazon, CN = Amazon RSA 2048 M04|notBefore=Jul 17 00:00:00 2026 GMT|notAfter=Jan 30 23:59:59 2027 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.spot.im/index.html CODE:502
TITLE: 
COPYRIGHT: 

=== spotxchange.com
TLS: <no handshake>|
RDAP: <none>
TITLE: 
COPYRIGHT: 

=== squarecdn.com
TLS: subject=CN = squarebusinessdebit.com|issuer=C = US, O = Amazon, CN = Amazon RSA 2048 M04|notBefore=Apr 26 00:00:00 2026 GMT|notAfter=Nov  9 23:59:59 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://squareup.com/us/en CODE:200
TITLE: Power your entire business | Square
COPYRIGHT: copyright|copyright|copyright|

=== stat-track.com
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://stat-track.com/ CODE:000
TITLE: 
COPYRIGHT: 

=== stripe.com
TLS: subject=jurisdictionC = US, jurisdictionST = Delaware, businessCategory = Private Organization, serialNumber = 4675506, C = US, ST = California, L = South San Francisco, O = "Stripe, LLC", CN = stripe.com|issuer=C = US, O = DigiCert Inc, CN = DigiCert Global G3 TLS ECC SHA384 2020 CA1|notBefore=Jul 28 00:00:00 2026 GMT|notAfter=Nov 12 23:59:59 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://stripe.com/de-ch CODE:200
TITLE: Online-Bezahldienst und Zahlungsdienstleister | Stripe
COPYRIGHT: ©  2026  Stripe, LLC|

=== stripst.com
TLS: subject=CN = stripst.com|issuer=C = US, O = Google Trust Services, CN = WE1|notBefore=Jul 14 02:44:47 2026 GMT|notAfter=Oct 12 03:44:45 2026 GMT|
RDAP: 
RDAP-registrar: 
TITLE: 
COPYRIGHT: 

=== tmdb.org
TLS: subject=CN = *.tmdb.org|issuer=C = US, O = Amazon, CN = Amazon RSA 2048 M04|notBefore=Jul 22 00:00:00 2026 GMT|notAfter=Feb  4 23:59:59 2027 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.themoviedb.org/ CODE:200
TITLE: The Movie Database (TMDB)
COPYRIGHT: 

=== tns-counter.ru
TLS: subject=C = RU, ST = Moscow, L = Moscow, O = JSC ADFACT, CN = *.tns-counter.ru|issuer=C = BE, O = GlobalSign nv-sa, CN = GlobalSign ECC OV SSL CA 2018|notBefore=Dec 22 08:06:30 2025 GMT|notAfter=Jan 23 08:06:29 2027 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://tns-counter.ru/ CODE:200
TITLE: Интернет-счетчик tns-counter.ru
COPYRIGHT: 

=== tqlkg.com
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://tqlkg.com/ CODE:000
TITLE: 
COPYRIGHT: 

=== travelpayouts.com
TLS: subject=CN = travelpayouts.com|issuer=C = US, O = Amazon, CN = Amazon RSA 2048 M01|notBefore=Jul 10 00:00:00 2026 GMT|notAfter=Jan 23 23:59:59 2027 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.travelpayouts.com/ CODE:200
TITLE: Travel Affiliate Partnership Platform | Affiliate Programs - Travelpayouts
COPYRIGHT: © Travelpayouts, 2011– 2023         {"props":{"pageProps":{"locale":"en","meta":{"title":"T|

=== trustarc.com
TLS: subject=CN = trustarc.com|issuer=C = US, O = Google Trust Services, CN = WE1|notBefore=Jul 18 10:26:51 2026 GMT|notAfter=Oct 16 11:26:49 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://trustarc.com/ CODE:200
TITLE: Data Privacy Management Software &amp; Solutions | TrustArc
COPYRIGHT: © 2026  TrustArc Inc |

=== trustpilot.net
TLS: subject=CN = *.trustpilot.com|issuer=C = US, O = Amazon, CN = Amazon RSA 2048 M01|notBefore=Nov  1 00:00:00 2025 GMT|notAfter=Nov 29 23:59:59 2026 GMT|
RDAP: 
RDAP-registrar: Amazon Registrar, Inc.
FINAL:https://trustpilot.net/ CODE:000
TITLE: 
COPYRIGHT: 

=== tu-dresden.de
TLS: subject=C = DE, ST = Sachsen, O = Technische Universitaet Dresden, CN = tu-dresden.de|issuer=C = GR, O = Hellenic Academic and Research Institutions CA, CN = GEANT TLS ECC 1|notBefore=Oct 28 16:20:14 2025 GMT|notAfter=Oct 28 16:20:14 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://tu-dresden.de/ CODE:200
TITLE: Technische Universität Dresden — TU Dresden
COPYRIGHT: © TUD|© TUD|© David Sünderhauf|

=== tvtime.com
TLS: subject=CN = *.tvtime.com|issuer=C = US, O = Amazon, CN = Amazon RSA 2048 M04|notBefore=Oct 27 00:00:00 2025 GMT|notAfter=Nov 24 23:59:59 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://tvtime.com/ CODE:200
TITLE: Thank You — TV Time
COPYRIGHT: 

=== twiago.com
TLS: subject=CN = *.twiago.com|issuer=C = GB, O = Sectigo Limited, CN = Sectigo Public Server Authentication CA DV R36|notBefore=Jan  5 00:00:00 2026 GMT|notAfter=Feb  5 23:59:59 2027 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.twiago.com/ CODE:200
TITLE: Native Advertising in Bestform | Twiago - Twice as Good
COPYRIGHT: 

=== userzoom.com
TLS: subject=CN = userzoom.com|issuer=C = US, O = Let's Encrypt, CN = YR1|notBefore=Jul  7 18:57:53 2026 GMT|notAfter=Oct  5 18:57:52 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.usertesting.com/platform/userzoom CODE:200
TITLE: UserZoom Platform | UserTesting | UX Research Capabilities
COPYRIGHT: © UserTesting 2026 &nbsp; &vert; &nbsp; Cookie Settings                           |

=== vg.hu
TLS: subject=CN = vg.hu|issuer=C = US, O = Google Trust Services, CN = WE1|notBefore=Sep  2 17:16:22 2026 GMT|notAfter=Dec  1 18:13:55 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.vg.hu/ CODE:200
TITLE: Világgazdaság | Főoldal
COPYRIGHT: copyright[_ngcontent-ng-c2780841918]{line-height:24px;font-size:16px;font-weight:400;color:var(--ku|copyright[_ngcontent-ng-c2780841918]{text-align:center}}|©    VILÁGGAZDASÁG               Portfóliónk minőségi tartalmat jelent minden olvasó számár|

=== vidazoo.com
TLS: subject=CN = *.vidazoo.com|issuer=C = US, ST = Arizona, L = Scottsdale, O = "Starfield Technologies, Inc.", OU = http://certs.starfieldtech.com/repository/, CN = Starfield Secure Certificate Authority - G2|notBefore=Feb 21 11:00:28 2026 GMT|notAfter=Mar 23 10:06:41 2027 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://perion.com/ CODE:403
TITLE: Just a moment...
COPYRIGHT: 

=== viralize.com
TLS: subject=CN = viralize.com|issuer=C = US, O = Google Trust Services, CN = WR3|notBefore=Aug 23 04:41:59 2026 GMT|notAfter=Nov 21 05:35:12 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://viralize.com/ CODE:200
TITLE: home page - Viralize
COPYRIGHT: copyright:before{content:"\f1f9"}|copyright{font-family:"Font Awesome 5 Free";font-weight:400}|

=== visualstudio.com
TLS: subject=C = US, ST = WA, L = Redmond, O = Microsoft Corporation, CN = visualstudio.com|issuer=C = US, O = Microsoft Corporation, CN = Microsoft TLS G2 RSA CA OCSP 04|notBefore=Aug 28 04:24:00 2026 GMT|notAfter=Dec  6 03:24:00 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://visualstudio.microsoft.com/ CODE:200
TITLE: 	Visual Studio: IDE and Code Editor for Software Development
COPYRIGHT: 

=== webmd.com
TLS: subject=CN = le.prod.webmd.com|issuer=C = US, O = Let's Encrypt, CN = YR1|notBefore=Sep  2 00:10:04 2026 GMT|notAfter=Dec  1 00:10:03 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.webmd.com/ CODE:200
TITLE: WebMD - Better information. Better health.
COPYRIGHT: © 2005 - 2026 WebMD LLC, an  Internet Brands  company|

=== wishabi.com
TLS: subject=CN = flipp.com|issuer=C = US, O = Amazon, CN = Amazon RSA 2048 M04|notBefore=Apr 29 00:00:00 2026 GMT|notAfter=Nov 12 23:59:59 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://wishabi.com/ CODE:200
TITLE: 
COPYRIGHT: 

=== wp.com
TLS: subject=CN = wp.com|issuer=C = US, O = Let's Encrypt, CN = YE2|notBefore=Aug  1 19:44:46 2026 GMT|notAfter=Oct 30 19:44:45 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://wordpress.com/ CODE:200
TITLE: WordPress.com: Everything You Need to Build Your Website
COPYRIGHT: 

=== wrbm.com
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://wrbm.com/ CODE:000
TITLE: 
COPYRIGHT: 

=== yahooapis.com
TLS: subject=C = US, ST = New York, L = New York, O = Yahoo Holdings Inc., CN = src3.yahoo.com|issuer=C = US, O = DigiCert Inc, CN = DigiCert Global G2 TLS RSA SHA256 2020 CA1|notBefore=Jul  1 00:00:00 2026 GMT|notAfter=Dec 23 23:59:59 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://developer.yahoo.com/ CODE:200
TITLE: Yahoo Developer Network
COPYRIGHT: copyright')|&copy; " + new Date()|

=== yceml.net
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://yceml.net/ CODE:000
TITLE: 
COPYRIGHT: 

=== yieldlove-ad-serving.net
TLS: <no handshake>|
RDAP: 
RDAP-registrar: 
FINAL:https://yieldlove-ad-serving.net/ CODE:000
TITLE: 
COPYRIGHT: 

=== zoominfo.com
TLS: subject=CN = zoominfo.com|issuer=C = US, O = Let's Encrypt, CN = YE1|notBefore=Aug 23 16:21:49 2026 GMT|notAfter=Nov 21 16:21:48 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.zoominfo.com/ CODE:200
TITLE: ZoomInfo: The #1 GTM Platform  - Sales AI for Lead Generation
COPYRIGHT: &copy; 2026 ZoomInfo Technologies LLC    Privacy Policy    Terms of Use     Cookies Settings    |copyright":"\u0026copy; {year} ZoomInfo Technologies LLC","interestLabel":"Also of interest","navCo|

=== zopim.com
TLS: subject=CN = zopim.com|issuer=C = US, O = Google Trust Services, CN = WE1|notBefore=Sep  1 22:34:51 2026 GMT|notAfter=Nov 30 23:34:40 2026 GMT|
RDAP: 
RDAP-registrar: 
FINAL:https://www.zendesk.com/service/messaging/live-chat-software/?from=zp CODE:200
TITLE: Live chat software
COPYRIGHT: © 2026 Zendesk, Inc|
  • webxray — the provenance page these blocks belong to: queries, denominators, corrections, limits, reviewers.
  • webxray — the content page the figures are on.
  • corpus — corpus scope, the selection funnel, extraction stability.
provenance/programming/crawler/webxray/random_sample.txt · Last modified: by karel.kubicek.claude

Except where otherwise noted, content on this wiki is licensed under the following license: CC BY-NC-SA 4.0
CC BY-NC-SA 4.0 Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki