QyE background check: November 2025 to October 17, 2026
Analysis of the program Google runs in the background on its results pages (sg_ck=QyE channel), based on collected responses. Status as of October 19, 2026.
In brief
- Four new test families appear between August 20 at 12:06 UTC and August 22 at 20:58 UTC. Our corpus contains no capture between these two points in time. All four arrive together: settings declared by the browser, text rendering and hyphenation, pointer precision, WebGPU.
- The decoded program grows by about 13% (+2,648 bytes) between August 12 and 28, while the JavaScript engine that runs it shrinks slightly.
- The WebGPU test is removed on October 5, between 06:53 and 14:07 UTC. The other three families remain. Our live session of October 17 confirms this.
- A variant with a local storage module has coexisted with the normal program since July. 134 captures from July 8 to October 17; it is served at the same time as the normal version, for the same request URL.
- Stored data is only accepted by the program copy that wrote it.
Corpus and method
| Item | Value |
|---|---|
| QyE entries identified (responses over 20,000 bytes) | 4,780, from November 13, 2025 to October 17, 2026 |
| Selected captures | 444: all large responses, their nearest normal neighbour, all of September, three per week since November 2025, date bisections |
| Bodies retrieved and verified (hash and capture date) | 444 of 444 |
| Bodies run offline | 441; 3 responses related to Google Flights, in a different format, are excluded |
| Runs with empty storage | 441, without errors |
| Detailed traces | 69 |
The original engine is run with its program in an isolated browser. The https://www.google.com/search page is served locally; no request is sent to Google and no token is submitted.
The August increase
| Measure | August 12 | August 28 | Difference |
|---|---|---|---|
| Encoded program, characters | 26,275 | 29,807 | +3,532, i.e. +13.44% |
| Decoded program, bytes | 19,703 | 22,351 | +2,648, i.e. +13.44% |
| JavaScript engine, bytes | 63,734 | 63,231 | −503 |
| Full response, bytes | 120,495 | 123,421 | +2,926, i.e. +2.43% |
The auxiliary configuration is identical. The increase comes neither from the encoding nor from the packaging.
Size of the normal program, month by month
Decoded program, in bytes, excluding the variant with storage.
| Period | Captures | Median | Minimum | Maximum |
|---|---|---|---|---|
| November 2025 | 3 | 18,872 | 18,838 | 19,523 |
| December 2025 | 8 | 18,915 | 18,575 | 20,158 |
| January 2026 | 13 | 19,136 | 18,788 | 20,150 |
| February | 11 | 19,099 | 18,830 | 20,138 |
| March | 13 | 19,287 | 19,148 | 20,110 |
| April | 15 | 19,403 | 19,114 | 20,102 |
| May | 11 | 19,863 | 19,759 | 23,213 |
| June | 9 | 20,147 | 19,997 | 20,341 |
| July | 88 | 20,097 | 19,861 | 21,196 |
| August 1 to 20 | 53 | 19,734 | 18,638 | 19,950 |
| August 22 to October 5, 06:53 | 98 | 22,148 | 21,253 | 22,811 |
| October 5, 14:07 to October 17 | 27 | 21,829 | 21,439 | 22,663 |
About +1 KB over nine months, then a jump of about +2.4 KB on August 22, then −319 bytes after WebGPU was removed. The spread between captures from the same period reaches 1.5 KB: size alone is not enough to attribute the October decrease.
The new tests
| Test | What the program does |
|---|---|
| Declared settings | Reads navigator.platform, navigator.doNotTrack and window.doNotTrack |
| Text rendering | Creates hidden blocks in a monospaced font (16 px, 20 px line height), compares hyphens: auto and none, reads offsetHeight |
| Pointer | Calls matchMedia with any-pointer: fine and any-pointer: coarse |
| Graphics card (until October 5) | Calls navigator.gpu.requestAdapter with powerPreference: low-power, then reads info.vendor and info.architecture |
| Period (UTC) | Traces | Settings, rendering, pointer | WebGPU |
|---|---|---|---|
| November 2025 to August 20, 12:06 | 10 | absent | absent |
| August 22, 20:58 to October 5, 06:53 | 43 | present | present |
| October 5, 14:07 to October 17 | 16 | present | absent |
No exceptions in the 69 traces. The removal of WebGPU coincides with the switch to a new version of the JavaScript engine, between 06:53 and 14:07 UTC on October 5. Engine versions change several times a week: the coincidence dates the change, without proving that the engine is its cause.
Constants related to the new tests were located in the program (about 618 bytes of literal reconstruction). The exact split of the additional 2,648 bytes between code, data and padding is not established.
The variant with local storage
It can be identified in two consistent ways: its size, and the fact that it leaves state in localStorage after running. Out of 441 runs, the 134 large programs all leave state, the other 307 none.
| Month | Index entries | Variants | Share |
|---|---|---|---|
| November 2025 to June 2026 | 1,641 | 0 | 0% |
| July | 1,106 | 116 (July 8 to 16) | 10.5% |
| August | 72 | 1 (August 18) | 1.4% |
| September | 86 | 1 (September 28) | 1.2% |
| October 1 to 17 | 1,875 | 16 | 0.9% |
It is the normal program of the time, extended with a module of 4.7 to 7.4 KB (median 6 KB). It follows the normal program's changes: without the new tests in July, with WebGPU on September 28, without WebGPU in October. In October, the nearest normal capture with the same engine is a median of 1.2 minutes away; on October 15, a variant and a normal program are captured 16 seconds apart. Nothing in the request URL distinguishes them: the assignment is made server-side. An A/B test, sampling or targeting all remain compatible with this data.
The module also schedules a 2,000 ms interval.
Stored data is tied to its program
| Reinjected state | Program reading it | Result |
|---|---|---|
| Its own state | the same program | accepted (6 July programs out of 6, and the August 18 variant) |
| State from another July 8 program, same engine | July program | rejected (4 cases out of 4) |
| State from another July 8 program, different engine | July program | rejected (2 cases out of 2) |
| State from a July program | August 18 variant | rejected |
| State from the August 18 variant | July program | rejected |
"Accepted": same result as with the program's own state. "Rejected": same result as with empty storage. These cross-program tests do not establish how state is validated or used server-side.
Storage structure and content
Decoding six programs (July 8 and 11, August 18, September 28, October 6 and 15) shows a common structure. The original engine and associated program are replayed offline, without sending tokens to Google. The decoded array is captured during storage readback; lengths and the final count are verified.
| Element | Size and observation |
|---|---|
| Outer envelope | 8 bytes |
| Decoded-content marker | 3 bytes: 01 be ef |
| Program-associated block | 12 bytes, unknown role, different across the six samples |
| Record | 4-byte big-endian timestamp, 1-byte field observed as 1, 2-byte big-endian length, variable payload |
| Final count | 1 byte |
Without interaction, the payload is 114 bytes: 121 bytes per record and a binary total of 24 + 121 × n. One record therefore represents 145 bytes; twenty, 2,444 bytes, before base64 encoding. Interactions change the length: 146 payload bytes for a movement or keystroke, 151 for an isolated click in the tested scenarios.
The timestamp matches program capture time exactly to the second in five samples and differs by one second in the sixth. It does not measure the simulated visit date in these replays. The role of the field equal to 1 remains unknown.
History of the last twenty runs
On the August 18 program, 21 fresh contexts successively receive the state written by the previous context. Each run contains a distinct click, from (101,201) to (121,221). The final state contains exactly the twenty records from (102,202) to (121,221), in order: the first is removed. This FIFO policy concerns program runs, not twenty clicks within one page. Format similarity alone does not establish it for the other five programs.
The studied coordinates represent the last click: a click at (123,234), followed by movement to (500,400), leaves (123,234). Movement alone leaves the (65535,65535) sentinel.
A block marked c5 26 01 20 contains a flag, followed by 32 one-byte counters when active in the tested scenarios. One keystroke sets counters at indices 27, 28 and 29 to 1; three keystrokes raise them to 3. The a and b keys produce identical payloads. These are event counters, without distinguishing typed characters in this block and these scenarios; this does not establish whether collection occurs elsewhere.
A synthetic JavaScript click increments a counter without populating coordinates like the CDP click. Since sequences and targets may differ, this contrast does not establish an effect of isTrusted alone. Exact mappings between all counters and DOM events, and their saturation rules, remain undetermined.
Keys and encoding: 134 states
| Period | States | Observed keys | Encoding |
|---|---|---|---|
| July | 116 | Common base with suffix 0 to 9 | Padded base64 |
| August | 1 | Base with suffix 4 | Padded base64 |
| September | 1 | Unsuffixed base | Unpadded URL-safe base64 |
| October | 16 | Unsuffixed base | Unpadded URL-safe base64 |
The change is bounded by our August 18 and September 28 captures, without an exact deployment date. The purpose and selection rule of suffixes are not established; cumulative volume across multiple keys is unmeasured. A persistent history establishes neither a stable personal identifier, cross-site tracking, nor use in the server score.
Limits
- Dates are capture dates, bracketed by our neighbouring captures. The context in which each request was issued is unknown.
- An absent test means that its strings were not reconstructed in this offline scenario. For WebGPU, the October absence is cross-checked live.
- The variant counts for the index rely on size: a single false positive among the 441 verified bodies.
- No reliable conclusion on execution cost or detection effectiveness.