{"@context":"https://schema.org","@type":"BlogPosting","headline":"Raw-Stream Hidden Signals: What ChatGPT Actually Sends (2026)","description":"A read-only re-test of three claimed undocumented fields inside the raw ChatGPT server-sent-event stream, run against ai-scrapers’ own public.fanout_captures table (the AI Hotel Landscape corpus) — not a third-party dataset. Extraction walks the SSE/JSON-patch tree depth-first, collecting fields by key presence rather than a hardcoded path, to survive release-to-release schema drift. Sample: 300 recent ChatGPT captures pulled in 40-row chunks (large queries reliably hit Supabase statement timeouts / Cloudflare 521-525), deduped to 150 rows, 146 parsed cleanly. Results: PARTIALLY CONFIRMED — ChatGPT’s supporting_websites winner-vs-runner-up citation field appears in 112/146 records (77%, 141 groups total), but every winner/runner-up snippet field is an empty string in all inspected pairs, so the “same claim” judgment reduces to title-only comparison (roughly 7 of 10 manually-read pairs genuinely compete, 3 of 10 are only topically adjacent). REFUTED — ChatGPT never narrates brand priors in “thoughts” blocks: 0/146 records show any brand, chain, or destination-specific entity name; all 16 distinct thought strings observed are boilerplate (“Searching N websites”). REFUTED — ChatGPT’s model_escalation metric is structurally unmeasurable under the current capture trigger: default_model_slug reads “auto” in 146/146 records (100%), so the metric’s qualifying denominator is zero by construction (the resolved model does split 89% gpt-5-6 / 11% gpt-5-5-mini, which is normal Auto routing, not escalation). All refuted findings are scoped to this capture pipeline and query library, not claimed as universal; read-only throughout, no writes, no migrations applied during the retest. SCOPE NOTE: a companion Perplexity re-test (trust tiers, intent-classifier scorecard, mode/model escalation) is intentionally omitted from this article — ai-scrapers’ storage layer has unconditionally stripped Perplexity’s raw SSE field from every stored capture since 2026-05-02 (a deliberate, unrelated storage-cost decision), which confounded that side of the original retest by making it indistinguishable from an upstream Bright Data schema change. A corrected Perplexity re-test needs to read the pre-storage payload directly; see aeo-kb/entries/perplexity-untapped-raw-response-signals.md for current status.","datePublished":"2026-08-13","dateModified":"2026-08-24","url":"https://nicolassitter.com/research/raw-stream-hidden-signals-2026","category":"research","keywords":["ChatGPT raw response","AI hidden signals","ChatGPT thoughts field","ChatGPT model escalation","SSE stream AI","AEO methodology","ChatGPT supporting_websites"],"articleSection":"Research","wordCount":2000,"readTime":"9 min","articleBody":"week of 2026-09-14AI Search · Methodology\n\n# Raw-stream hidden signals:what ChatGPT actually sends\n\n**TL;DR:** Behind the ChatGPT answer you see is a raw server-sent-event stream carrying dozens of undocumented fields our [AI Hotel Landscape pipeline](/projects/ai-hotel-landscape/all-models) already stores but had never parsed. We walked that stream, by key presence rather than a hardcoded path, against our own captures — not a third party's — and re-tested three claimed hidden signals. One held up, real but weaker than advertised (a citation-competitor field). Two came back as clean, structural zeros: no brand priors in ChatGPT's “thoughts,” no measurable model escalation.\n\nNS\n\nNicolas Sitter\n\nPublished August 2026 · read-only retest, August 2026\n\n141\n\nCitation-competitor groups (77% of captures)\n\n0/146\n\nCaptures with brand priors in \"thoughts\"\n\n0/146\n\nCaptures qualifying for model escalation\n\n[Read the Report](#executive-summary)\n\n[Summary](#executive-summary)[1\\. What held up](#confirmed)[2\\. What didn’t](#refuted)[3\\. Signal tracker](#live-tracker)[Methodology](#methodology)[FAQ](#faq)\n\n## Executive Summary\n\nWe had our own data. We had never actually parsed it.\n\nBright Data's capture pipeline stores the full raw server-sent-event (SSE) stream from ChatGPT on every hotel prompt in the AI Hotel Landscape corpus — but until this retest, nobody had walked that field for anything beyond the parsed answer text. It is dozens of undocumented keys deep: retrieval-tier tags, citation-competition graphs, model routing metadata. The AEO knowledge base had flagged three specific ChatGPT claims about what lives inside that stream, sourced from a different capture surface (a live-browser Chrome extension) than the one that actually feeds our production data. This retest re-ran all three against **our own** Bright Data captures — a read-only walk of `public.fanout_captures`, no third-party dataset involved.\n\nThe result is a genuine mixed verdict, not a clean win: one signal (the citation-competitor field) is real but weaker than the KB entry implied, and two — ChatGPT narrating brand priors and ChatGPT's model escalation — came back as clean, reproducible zeros in this pipeline and this query set today. We report the zeros as prominently as the hits; that is the point of re-testing.\n\n**Read the negative results as scoped, not universal.** A zero in our data means the signal did not appear in our specific capture pipeline and query library — a narrow set of single-turn, simple hotel prompts fired through Bright Data's SSE tee. It does not prove the phenomenon can never occur on a different client, a richer multi-turn conversation, or a paid-tier account. Every refuted finding below says exactly what would change that verdict.\n\n**A note on scope.** This retest also examined three Perplexity signals from the same knowledge-base entries. Those results are omitted here: our own storage layer strips Perplexity's raw SSE field from every stored capture, which confounded the re-test in a way that needs a cleaner methodology before it's worth publishing. ChatGPT's findings above don't share that confound.\n\nSection 1\n\n## What held up\n\nOne of three signals survived contact with real data — real, but weaker than the source implied.\n\n### ChatGPT's winner-vs-runner-up citations (partially confirmed)\n\nA `supporting_websites` structure appears in 112 of 146 (77%) recent ChatGPT hotel captures, with 141 winner/runner-up groups total — each pairing the citation ChatGPT actually used against one or more competitors it considered. Manually reading 10 of those pairs, roughly 7 in 10 are genuine same-claim competitors — e.g. Bangkok's winner (“The 10 best luxury hotels in Bangkok in 2026 | Latitude”) against a runner-up making the identical claim (“The Best Luxury Hotels in Bangkok for 2026 · La Revue des Hôtels”) — while roughly 3 in 10 are only topically adjacent, like a curated Beijing top-10 list paired against a Reddit thread asking for help choosing between four hotels.\n\n**Why “partially,” not “confirmed”:** in every single inspected pair — and on spot checks across the wider 141-group set — the `snippet` field on both winner and runner-up nodes is an empty string. Bright Data's parse never populates it for these citation nodes. That means the “surrounding claim” comparison this signal implies reduces entirely to title-string similarity; there is no snippet text to confirm sentence-level competition. This is itself worth fixing before `supporting_websites` becomes a metric — title similarity alone is a much weaker signal than a same-sentence claim match.\n\nSection 2\n\n## What didn't\n\nTwo claimed signals came back as clean, reproducible zeros — not “rare,” genuinely absent given how each is currently defined and how our pipeline captures data. We report them as negative results rather than quietly dropping them.\n\n**ChatGPT never narrates brand priors in “thoughts” (refuted, 0/146).** `thoughts` blocks are present in all 146 parseable records, but every one of the 16 distinct thought strings observed is boilerplate — “Searching 10 websites” (28×), “Searching 11 websites” (23×), down to a single “Searching www.cntraveler.com” (a bare domain, not a brand mention). `thoughts.content` is always an empty string; no capitalized multi-word proper-noun candidate — no hotel brand, chain, or destination-specific reasoning — appears anywhere in the stream, before or after the first search event.  \n  \n**Scope of the refutation:** this used our own Bright Data SSE-tee capture on simple, single-turn “best/cheap/luxury hotels in \\[city\\]” prompts — not the live-browser capture the original claim was sourced from. It's plausible the tee only surfaces the UI-facing summary type of thoughts block, or that more complex, comparative, multi-turn prompts would surface narrated reasoning these queries never trigger. This refutes the signal as it manifests in our capture pipeline and query set today — it is not a claim that ChatGPT never narrates priors under any circumstances.\n\n**ChatGPT's model escalation is structurally unmeasurable right now (refuted, 0/146 qualify).** `default_model_slug` reads `“auto”` in 100% of records — never a concrete model name to compare against. The resolved model underneath does vary (`gpt-5-6` on 130 records / 89%, `gpt-5-5-mini` on 16 / 11%), but that's normal Auto routing, not escalation — the metric's own definition requires a concrete requested model, so the qualifying denominator is 0/146 by construction. This exactly reconfirms a caveat already written into our own pipeline code: it isn't a new finding, it's a clean re-confirmation that this framing is unmeasurable unless the capture trigger is changed to request a concrete model.\n\nSection 3\n\n## Signal tracker\n\nAll three ChatGPT signals, one table. Citation runner-ups is backed by `public_dashboard.pd_weekly_raw_stream_signals` and updates weekly from live capture data. The other two came back as clean, reproducible zeros and were deliberately excluded from the migration — they stay frozen at this retest's counts (read-only retest, August 2026) unless a future re-test overturns that.\n\nSignal\n\nVerdict\n\nOccurrences\n\nSample checked\n\nsupporting\\_websites (winner vs. runner-up citations)\n\nReal and common, but weaker than advertised: every inspected snippet field is empty, so the \"same claim\" judgment reduces to title-only comparison — about 7 in 10 manually-read pairs genuinely compete, 3 in 10 are only topically adjacent.\n\nPartially confirmed\n\n2 captures, 2 groups\n\n616 captures\n\npriors (brand names in thoughts before search)\n\n100% of observed thoughts text (16 distinct strings) is boilerplate progress messages (\"Searching N websites\") — zero brand, chain, or destination-specific reasoning in any record.\n\nRefuted\n\n0 occurrences\n\n146/146 records\n\nmodel\\_escalation (default\\_model\\_slug vs. resolved)\n\ndefault\\_model\\_slug is \"auto\" on every single record — the escalation metric requires a concrete requested model to compare against, so it cannot fire by construction under the current trigger config.\n\nRefuted\n\n0/146 qualify\n\n146/146 records\n\nLive from public\\_dashboard.pd\\_weekly\\_raw\\_stream\\_signals, week of 2026-09-14. The two rows without a live-updating count were excluded from the migration as structural zeros — see Methodology.\n\n## Methodology\n\n**Source.** This is a read-only re-test of open questions from our AEO knowledge base, run against `ai-scrapers`' own `public.fanout_captures` table — the same corpus behind the [AI Hotel Landscape](/projects/ai-hotel-landscape/all-models). Every signal in this article was mined from our own hotel-search captures, not a third party's dataset.\n\n**Shape.** `fanout_captures.raw_response` is a JSON-deserialized dict whose `response_raw` field is (when present) a JSON string containing a list of `{event, data}` server-sent-event frames. `data` is itself a JSON-patch-shaped tree (`p`/`o`/`v`/`c` keys at points) whose values are where fields like `supporting_websites` and `thoughts` actually live.\n\n**Extraction, not path-matching.** Because the JSON shape drifts release to release, we walk every dict/list depth-first and collect fields by key presence rather than a hardcoded path — a plain `dict.values()` traversal still reaches values nested inside the patch tree's `v` field, confirmed with exploratory probes before writing the main extraction script.\n\n**Sampling.** 300 recent ChatGPT captures with non-null `raw_response`, pulled in 40-row chunks (a single large query reliably hit Supabase statement timeouts and Cloudflare 521/522/525 errors on this project — confirmed empirically), deduped to 150 rows across 150 distinct `query_id`s, 146 of which parsed cleanly.\n\n**Live tracker.** A permanent extraction module, `fanouts-automation/tasks/raw_signals.py`, feeds a weekly aggregate, `public_dashboard.pd_weekly_raw_stream_signals` (built via `public.rebuild_raw_stream_signals`, wired into the existing Monday-morning refresh flow). The migration shipped and the backfill ran on ~22.9k eligible ChatGPT captures. The other two ChatGPT signals (`priors`, `model_escalation`) came back as clean structural zeros and were deliberately left out of the migration rather than carried as dead columns; those rows in Section 3 stay frozen at this retest's counts.\n\n**Scope: Perplexity omitted.** This retest also covered three claimed Perplexity signals (trust tiers, an intent-classifier scorecard, mode/model escalation). We're not publishing those results here: ai-scrapers' storage layer has unconditionally stripped Perplexity's raw SSE field from every stored capture since 2026-05-02 (a deliberate, unrelated storage-cost decision), and the original pass mistook that internal stripping for an upstream Bright Data schema change — confounding the result. A corrected re-test needs to read the pre-storage payload directly rather than the stored copy; until that lands, see `aeo-kb/entries/perplexity-untapped-raw-response-signals.md` for the open status rather than this page.\n\n**Access.** The re-test itself was read-only throughout: only `SELECT` queries against Supabase, no writes. The migration, extraction module and backfill script were reviewed and applied separately, after the re-test concluded.\n\n## FAQ\n\nUndocumented fields inside the raw server-sent-event stream an AI engine sends while assembling an answer — retrieval-tier tags, citation-competition graphs, model-routing metadata — that never appear in the rendered chat UI but are captured by a scraping pipeline that logs the full SSE payload. This article mines three specific claimed signals out of our own ChatGPT captures to see which ones actually exist.\n\n## Explore the data behind this page\n\nEvery number here comes from a read-only walk of our own AI Hotel Landscape captures — CC-BY-4.0.\n\n[Live dashboard](/projects/ai-hotel-landscape/all-models)[Data feed docs](/api/landscape/raw-signals)","author":{"@type":"Person","name":"Nicolas Sitter","url":"https://nicolassitter.com/about","sameAs":["https://www.linkedin.com/in/nicolassitternolleau/","https://github.com/Nicositter88","https://hotelrank.ai"]},"publisher":{"@type":"Person","name":"Nicolas Sitter","url":"https://nicolassitter.com"},"image":"https://nicolassitter.com/api/og/raw-stream-hidden-signals-2026","mainEntityOfPage":{"@type":"WebPage","@id":"https://nicolassitter.com/research/raw-stream-hidden-signals-2026"},"tags":["AI Search","Methodology","ChatGPT","AEO"],"sameAs":["https://hotelrank.ai/research/raw-stream-hidden-signals-2026"],"alternateFormat":{"html":"https://nicolassitter.com/research/raw-stream-hidden-signals-2026","json":"https://nicolassitter.com/api/post/raw-stream-hidden-signals-2026","rss":"https://nicolassitter.com/rss.xml"},"datasets":[{"name":"summary","contentUrl":"https://nicolassitter.com/data/raw-stream-hidden-signals-2026/summary.csv","encodingFormat":"text/csv"}]}