# Sample dataset: "How to find out who owns a website" blog post

**REAL DATA.** All 26 domains are real and were analyzed through the live
WhoisGenius API on 2026-08-26 (65 credits total). Raw API responses are
archived in `scratchpad/find-website-owner-live/` for provenance. To produce
equivalent results on your own list, run `bulk_analyze.py`.

## Files

| File | Shape | Mirrors |
|---|---|---|
| `domains_sample.txt` | one domain per line, `# segment (n)` comments | input for both scripts |
| `sample_analysis_results.json` | per-domain results: `attribution` (verdict block), `entities[]` (parent/legal/impersonation detail), `signals[]` (per-signal evidence) | `GET /jobs/{job_id}` -> `scoring_result` + `GET /jobs/{job_id}/signals` |
| `sample_analysis_export.csv` | the same 26 results flattened into one row per domain | the CSV `bulk_analyze.py` writes |
| `sample_correlation.json` | the real 15-domain showcase correlation, plus the submit response with credit accounting | `GET /correlate/{correlation_id}` (payload under `result`) + `POST /correlate` 202 |
| `bulk_analyze.py` | batch submit + poll + CSV export | `POST /analyze/batch`, `GET /jobs/{job_id}` |
| `correlate_networks.py` | correlation submit + poll + cluster report | `POST /correlate`, `GET /correlate/{id}` |

## Shape notes that bite people (verified live)

- `scoring_result.attribution.ownership_signals` and
  `corroborating_correlations` are **counts**, not arrays. The per-signal
  breakdown is a separate endpoint: `GET /jobs/{job_id}/signals`.
- `parent_company`, `parent_company_domain`, `legal_entity`, and
  `impersonation_suspected` live on `scoring_result.entities[]`, **not** on
  the attribution object. Read the top entity for the rollup.
  (`parent_company` populated on Meta/Amazon subsidiaries here;
  `parent_company_domain` was null on every entity we pulled.)
- In `/signals` output, `signal_type` is the **collector** name (`whois`,
  `http_probe`, `http_vision`, `asn`, `rdns`, `dns`, `domain_name`,
  `wayback`). Shared analytics identifiers appear under
  `entities[].correlations[]` (for example `shared_analytics_id`), not in
  `signals[]`.
- `status: "partial"` does not always mean dropped collectors. It means
  fresh collection fell short and the run leaned on cached or surviving
  evidence. stripe.com was `partial` with a full collector count and still
  `confirmed` at 1.0; taz.de was `partial` at 7/11.
- In correlation output, only `analytics_id` and `ads_txt_seller` carry
  `relation: "owner"`. Everything else (registrar, nameserver, cert issuer,
  CAA, IP/ASN, registration timing) is `relation: "host"`. That is why
  instagram.com and whatsapp.com (same parent, same ASN, same registrar)
  did NOT cluster, and medium.com/discord.com/producthunt.com behind one
  CDN stayed unclustered.

## Edge-case coverage matrix (all real)

| Segment | Domains | What the live API did |
|---|---|---|
| `clean` | stripe.com, dropbox.com, airtable.com | `confirmed`/`likely` at 1.0, legal entity attached |
| `redacted_gdpr` | spiegel.de, heise.de, sueddeutsche.de | DENIC publishes nothing; operators recovered from JSON-LD org and copyright lines |
| `privacy_shield` | downloadpage.xyz | Dynadot privacy proxy, no surviving signals: honest `inconclusive` 0.4 |
| `parent_subsidiary` | instagram.com, whatsapp.com (Meta), twitch.tv (Amazon) | deep runs; `entities[0].parent_company` populated |
| `network` | theverge/vox/sbnation/eater/thrillist/thedodo/popsugar | 7-site cluster at 0.72; 340 owner-relation shared signals (ads.txt seller graph + shared GA4/UA properties) |
| `shared_hosting` | medium.com, discord.com, producthunt.com | same CDN edge, zero owner evidence: unclustered, max pairwise 0.5 |
| `impersonation` | twtter.com | brand_similarity 0.96 vs twitter.com (typosquat); open WHOIS names an individual; `possible` 0.21 |
| `parked` | atlas.com | for-sale lander at a premium brokerage; `inconclusive` 0.1 |
| `expired_domain` | tuaw.com | dropped AOL blog re-registered; Apple imagery yields contested `possible` 0.9, verdict refuses to upgrade |
| `idn` | münchen.de | auto-converted to `xn--mnchen-3ya.de` |
| `partial_collectors` | taz.de | `status: "partial"` 7/11, still `likely` taz at 1.0 |
| `inconclusive` | golem.de | conflicting thin signals, no winner: `inconclusive` 0.4 |

## Not covered

- Webhook delivery (`callback_url`, `X-Signature-256` verification): see the
  [API reference](https://whoisgeni.us/api-reference/).
- `POST /analyze/bulk` (500-domain fire-and-forget, results by email):
  submit verified live (`202` + `bulk_job_id`).
- `GET /entities/{name}/portfolio` (reverse WHOIS): returned `503`
  (upstream circuit breaker) at dataset build time. Best-effort endpoint.
