Reverse engineering · October 2026

BotGuard: what our tests reveal
about Google’s protections

Which browsers obtain results, what session state changes, what Google’s scripts inspect in the browser, and why a results page received is not necessarily a reliable measurement.

The Google logo inside a shield, surrounded by bots
Powered by RESONEO

Since summer 2026, Google has changed the check that runs in the background on its results pages. Between August 20 and 22, it added four families of tests: settings declared by the browser, text rendering, pointer precision and the graphics card via WebGPU. The WebGPU test disappeared on October 5. Since July, a share of requests has also received a module that retains an interaction history in the browser and reads it back on the next run. In late August, Google also extended /goto redirect links across its results.

Browser trials from a VPS, using its native IP and VPN exits, and analysis of the code Google serves describe up to four virtual machines (VMs) on a single results page and three distinct check flows. In the controlled comparison of the same Chrome, refusal follows the native navigator.webdriver value, independently of the launch setting that normally activates it. The automation signal and session state influence the observed flows; IP alone does not explain the differences. And a results page obtained does not guarantee a reliable measurement.

The interactive experience SearchGuard — Episode II
The Empire Scrapes Back
The same investigation, played out in seven acts. Clear Google’s check yourself, see what your browser gives away about you, and what decides whether you get the results — or not. Enter the experience →

Contents

Part I

Field findings

Which configurations obtain results? How does session state matter? Can the returned rankings be trusted?

1

What is at stake: who gets to observe Google results

Google results pages are more than a service: they reflect what the world is searching for, minute by minute. An entire industry measures its visibility through them. The protections documented on this page decide who gets to look.

The market depends on this window

Every ranking report, every visibility metric, every tool that tells a business where it stands relies on reading Google results pages. The DoJ antitrust case against Google ended in 2024 with a finding of monopoly in general search: there is no substitute source. What happens on these pages is the market.

AI newcomers raised the stakes

Since 2024, AI companies have been tapping Google results at scale to feed their own answers, without Google’s consent. During the US antitrust trial, an OpenAI executive testified that OpenAI had asked for access to Google’s index and been turned down. Since then, many independent researchers, ourselves included, have shown that ChatGPT answers are built in part on Google results. The protections documented on this page now also guard Google against its newest competitors.

Google is turning the lights off, one switch at a time

The timeline in Part II shows the sequence: the end of 100 results per page (September 2025), redirect links on every result (August 2026), four new browser checks (August 2026) and a module that keeps data between visits (July 2026). No announcement, no version number. Each step makes independent observation harder and more expensive.

Regulators are ordering the opposite

While the room goes dark, courts and regulators are reaching for the switch. In the US antitrust case, the court ordered Google to share search data with qualified competitors (September 2025). In Europe, the Digital Services Act gives vetted researchers a right of access to data from very large search engines. What Google’s code turns off, the law is starting to turn back on.

What people search for is produced by the public. Today, a single company decides who may observe it.

2

Accessing results: what gets through, what gets blocked

In the controlled trials, refusal follows the native value of navigator.webdriver. With Chrome, machine and network held constant, results appear when this property is false, even with --enable-automation. When it is true, the browser is refused, even without that setting. The launch setting and the signal exposed to the page can therefore be distinguished experimentally.

ConfigurationDeclares automationNetwork exitObserved flow
HTTP client without JavaScriptNot applicableCompared VPN exitRemains on the challenge
Chrome launched normally, search typed on the keyboardNoNative IPResults after challenge
Same Chrome + only the --enable-automation settingYesNative IPRefused
Headed Chrome driven by PlaywrightYesNative IP and VPNRefused
Headless Chrome driven by PlaywrightYesCompared VPN exitRefused
Camoufox · fresh profileNoNative IP and VPNResults after challenge
Camoufox · retained sessionNoFixed VPN exit, session trialsDirect results

The dividing line follows the automation declaration. IP alone cannot explain the differences: on both native IP and VPN, Camoufox obtains results where Chrome driven by Playwright is refused, and the same Chrome launched normally gets through on the native IP.

The launch setting or the signal exposed to the page?

The comparison crosses two factors: the presence of --enable-automation and the native value of navigator.webdriver. The four combinations are repeated in two randomly ordered blocks, with a fresh profile for each navigation. Two ordinary Chrome controls bracket the series and both display results.

Chrome 153 · same binary, same IPv4 and IPv6 · two trials per combination
--enable-automationnavigator.webdriverOutcome
Absentfalse2 / 2 results
Presentfalse2 / 2 results
Absenttrue2 / 2 refusals
Presenttrue2 / 2 refusals

The JavaScript getter remains native: the browser controls the value without replacing the property in the page. The Blink AutomationControlled feature is disabled in all four combinations; a CDP command sets the signal independently of the flag. Knitsail and the YouTube VM read this property (see observed reads). The result supports a causal role for the native signal in this environment, without revealing the server score or establishing a universal rule.

The decision comes right after the verification page

Flow in the flag-only test, without intervention on the native value:

Chrome · launched normally

Does not declare automation

Verification page, 0.2 sReloadResults
Chrome · same launch + --enable-automation

Declares automation

Verification page, 0.2 sReloadRefusal and CAPTCHA

On the observed fresh profiles, Google serves a verification page before reloading the search with the data produced by the check. Traces from the flag-only test place this reload about 0.2 seconds after the response. The main document then leads either to results or to /sorry and a 429 response. Classification uses the main navigation, the presence of results and screenshots; a background request to /sorry alone does not classify a navigation as refused.

In the controlled matrix, the presence of the flag does not distinguish outcomes; the native webdriver value does in all our trials. Accepted controls and unchanged IPv4 and IPv6 addresses limit an explanation based on a network change.

Two trials per combination, on one machine, network and query: these counts do not yield a generalisable success rate. A JavaScript replacement getter returning false was also refused, so that intervention is not a neutral control. Protocol and supporting controls: automation signal and Chrome settings.

3

Session state changes the path

With a fixed browser configuration and network exit, we compared copies of the same profile, retaining or deleting the NID cookie. The contrast repeats: retaining the session avoids the challenge; deleting NID brings it back.

Camoufox · same configuration

Retained session

NID presentDirect results
Camoufox · same configuration

NID deleted

New challengeResults

Starting with a fresh profile or deleting cookies can reintroduce a check that the retained session avoided.

A returning challenge is not a failure: results also arrive after it. NID is associated here with a session effect; SG_SS carries a challenge result. These observations do not make NID a universal pass or measure how long SG_SS remains valid.

4

Suspected result poisoning: two lists for the same query

Same query, same IP, two lists with no URL in common. This contrast raises suspicion of result poisoning by Google: plausible pages could be served to an automated client with deliberately altered content.

GoogleQuery: musée du Louvre site officiel

On October 18, 2026, the two searches start 2 minutes apart. The profiles are two copies of the same source profile; only NID differs among transmitted cookies. The branch retaining NID receives results directly; the other goes through a challenge.

Pair 06/07 · main results, excluding sitelinks and modules
NID retained
Direct results
6 results
  1. 1Louvre homepagelouvre.fr/
  2. 2Louvre MuseumMinistry of Culture
  3. 3Louvre Instagram account
  4. 4Louvre-Lens
  5. 5Louvre Facebook page
  6. 6Museum listingParis je t’aime

End of main results

NID deleted
ChallengeResults
9 results
  1. 1First steps at the LouvreEducational resource
  2. 2The Louvre at a glancePress site
  3. 3École du Louvre
  4. 4Louvre X account
  5. 5Guided tourParis je t’aime
  6. 6Louvre bookshop and gift shop
  7. 7English homepagelouvre.fr/en/
  8. 8Tickets and prices FAQ
  9. 9Visitor trails

Blue background: the official homepage, in French on the left and in English on the right. These are two distinct URLs.

0 target URLs shared between the 6 and 9 results. The second list highlights educational resources, press content, the school, the shop and ticketing.

Across the October 18 series, the Louvre homepage usually ranks seventh, less often first, and is sometimes missing from the main results. In the branches that keep NID, the pages where it ranks seventh record a Validate call, 8 to 10 seconds after the page was received. The displayed order is already set by then: on every page, the order received matches the final order.

Part II

Under the hood: code and traces

How the protection evolved, its components and the observed exchanges. Code describes capabilities; traces show which ones ran in our sessions.

5

How the protection evolved

Protection expands without a new BotGuard major version: an intermediate page, background checks, request retries, then in 2026 new browser tests and a module that keeps data from one visit to the next. Technical dates mark the first available observations in our corpus, not necessarily deployment dates.

BotGuard and SearchGuard mechanisms Changes affecting SERP collection
  1. First observed

    BotGuard version 41

    BotGuard already uses version 41. That version number remains in use in October 2026 despite rotation of scripts and their cipher parameters.

  2. First observed · confirmed by Google

    A flow requiring JavaScript

    Results code handles the sg_ss parameter and provides a redirect to /httpservice/retry/enablejs when JavaScript is disabled.

    Google confirmed the JavaScript requirement on January 17, 2025, presenting it as protection against bots and spam (TechCrunch).

  3. First observed

    The SearchGuard intermediate page

    An intermediate page embeds knitsail, produces the SG_SS cookie and restarts navigation. This mechanism is established by May 2025 at the latest.

  4. Press report
    Data access · Scraping costs

    The end of 100 results per request

    Google stops supporting num=100. Collecting the top 100 positions can now require about ten results pages instead of one.

    Stopped working late on September 11, 2025, reported on September 15 by Search Engine Land. On September 18, Google said it does not formally support this parameter.

  5. First observed

    A separate delivery channel

    The /sgasync channel, associated with code BMW, delivers the script, its hash and its program together. It complements an existing protection flow.

  6. First observed

    Background checks

    The sg_ck=QyE channel serves background checks, with a program distinct from the BMW program.

  7. First observed

    A check during a request

    The sg_ck=ON4 mode can compute a token and retry a request with X-Sg-Ss. This flow is distinct from the intermediate page.

  8. First observed

    Code for iframes

    Engines gain functions handling sandbox, srcdoc and script loading. Knitsail also receives these functions.

  9. First observed

    A module that keeps data in the browser

    A share of requests receives the background-check program extended with a module of about 6 KB. The module retains an interaction history in the browser (localStorage) and reads it back on the next run (structure and content). Both versions are served at the same time, for the same request URL.

    Observed from July 8 to October 17, 2026. In July, 10.5% of captures contain this module, all between July 8 and 16; afterwards, around 1%. The data is only read back by the program copy that wrote it. A/B test, sampling or server-side targeting: our corpus cannot tell which.

  10. First observed

    Four new tests in the background check

    The QyE check program reads settings declared by the browser (platform, “Do Not Track”), measures the height of a text block with and without hyphenation, tests pointer precision (mouse or touchscreen) and queries the graphics card via WebGPU. The decoded program grows by about 13% (+2.6 KB); the engine that runs it does not grow.

    Appearance dated between August 20 at 12:06 and August 22 at 20:58 UTC: our corpus holds no capture between those two moments, and the four tests arrive together. Program size says nothing about execution cost or effectiveness against bots.

  11. Confirmed by Google
    Data access · URL resolution

    Result URLs go through /goto

    Google rolls out /goto redirect links in its results pages. The final URL sometimes has to be resolved separately. An ordinary HTTP request is still enough in documented cases.

    Rollout confirmed by Google to Search Engine Land on August 26, 2026, after several months of testing according to the publication.

  12. First observed

    A channel associated with Google Flights

    The /sgasync channel associates sg_ck=QyE with sg_fe=flights.

  13. First observed

    The graphics card test disappears

    The background check stops querying the graphics card via WebGPU. The other three tests added in August remain in place. The change coincides with a new version of the JavaScript engine.

    Removal dated between 06:53 and 14:07 UTC on October 5, 2026. Our live session on October 17 confirms it: navigator.gpu is no longer read. The program loses about 320 bytes.

Orange milestones concern result collection and are separate from BotGuard mechanisms. “Confirmed by Google” refers to confirmation reported in the linked source; “First observed” refers to our code and page captures.

6

Who does what in the browser?

SearchGuard is Google’s name for its Search protection. BotGuard is a browser-side attestation engine: its virtual machine (VM) runs a Google-supplied program. The engine and the program are separate objects that can evolve independently.

A Google results page

Results

/async/bgasy provides the script address and program. The VM notably tracks interactions with results. No output token was identified during these sessions.

Knitsail

/sgasync delivers the engine and program together. This check inspects the browser and sends a token to Validate, on both classic results and AI Mode.

Advertising

A VM in an adtrafficquality.google frame produces a token for the pagead/sodar advertising flow.

Embedded YouTube

The embedded player brings its own VM and exchanges with Waa/GenerateIT. Its presence depends on page content.

Up to four VMs coexisted on an observed page. They do not all serve the same role: advertising and YouTube have their own flows. The homepage engine copy was analysed separately, without a trace of its reads in these sessions.

Engine, namespaces and obfuscation

Engine, program and obfuscation

The results, knitsail and advertising VMs observed on October 17, as well as the homepage VM copy from October 18, declare version 41. The YouTube VM version was not recorded. Entry function names rotate: in the 26 programs captured on October 17, the first three letters match the first three characters of the encoded program.

ElementObservation
VersionThe /js/bg/ scripts and VMs embedded in /sgasync examined declare version 41.
Namespaceswindow.botguard for results and advertising; window.knitsail, constructor ks, for knitsail.
RegistersIndices reach 511 in the advertising VM and 484 in knitsail: consistent with a 512-slot space. Individual index roles are not stable across scripts.
ObfuscationShort identifiers, state dispatch, bitwise calculations and strings reconstructed at runtime. Random blank lines are added to evaluated code; a dummy source map carries the name closureDynamicButton.
Script hashesVerified /js/bg/ and advertising filenames match the base64url SHA-256 of their contents. In the /sgasync responses examined, the hash field exactly matches the embedded script.
Iframes and sandboxThe code configures sandbox, removes srcdoc and assigns an iframe URL. Some permissions are added to it, including allow-same-origin and allow-scripts.
7

The three check flows

Checks can occur before results, on an already displayed page or during an additional request. These three flows are distinct, not a mandatory sequence.

Before results

  1. Search → intermediate page
  2. The program runs in the browser
  3. Result transported, notably through the SG_SS cookie
  4. The search restarts

In the background

  1. A results page is already displayed
  2. /sgasync delivers engine and program
  3. The browser computes a token
  4. The token is sent to Validate

During a request

  1. A response requests a check: X-Sg-Cs:s
  2. The client computes a token
  3. Retry with the X-Sg-Ss header
  4. The capture then shows X-Sg-Cs:a

If the flow ends in refusal: a redirect to /sorry can lead to reCAPTCHA. In the studied captures, this redirect clears SG_SS. The server remains the decision-maker; an HTTP 200 page can also be a challenge.

The retry with X-Sg-Ss was actually captured. However, neither an empty Validate response nor token production reveals the server’s internal verdict.

Headers, modes and client branches

Headers and request retries

The client wraps fetch and XMLHttpRequest for same-origin requests. An early layer queues responses in __sg_lite_queue; a later layer processes them when ready. The values below describe the observed protocol; none of them is a confidence score.

NameMeaning established by the code
x-sg-eObserved values: 2,isrpe=1,hcs=1 in the initial corpus and 1,isrpe=1,hcs=1 in the October 18 VPS retry. The client preserves mode 1 when requested by the caller; otherwise it uses 2. Capability flags are appended.
isrpeDerived from isrpeEnabled or window.sglc.isrpe. It participates in the decision to reload for a synchronous check; the exact internal expansion is not published.
hcsDerived from hasCaptchaSupport or window.sglc.hcs: client capability to handle a CAPTCHA.
X-Sg-CsResponse header. The client distinguishes values starting with s (synchronous branch) and a (asynchronous event). A retry path tests exact s and a values. The sfl prefix receives special handling.
X-Sg-SsCarries the computed token when retrying a request. It is a header, distinct from the intermediate page’s SG_SS cookie.
X-Sorry-RedirectIts presence, or a response URL containing /sorry/index, triggers CAPTCHA-flow handling.

In the retry path examined, internal codes 0, 1, 2 and 3 select, respectively: token computation and retry; an sglacte event; waiting for sglhcte_retry after sglhcte; and returning the response without this handling. These are local branch codes, unrelated to any risk level.

Client modes and switches

The code distinguishes a request-triggered check (ON4) from a non-synchronous load (BMW). Captures also show the QyE background channel. These short names are opaque identifiers: their roles follow from call sites and observations; we do not read meaning into the letters.

In the October client examined, configuration derives from bits in the x array. The names below belong to this copy and may rotate with obfuscation. Their presence shows what the code can do, without telling whether these branches are enabled.

Local switchBranch effect
ObEnables the startup path in setup().
QbSelects synchronous startup; the other branch waits one second and then an idle callback.
DdOn visibility change, can produce a result when the page becomes hidden.
BdSkips VM result retrieval in this branch.
Cd / vcThe first gates submission; the second selects the /sgvalid path instead of Validate.
bd / cdCan defer submission until a DOMContentLoaded callback, or add a 1,000 ms delay. These branches exist; activation during the sessions is not established.
Lc / zdControl two separate telemetry paths: step logging and timing measurements.
8

What each program observes

This matrix summarises reads and listeners observed during instrumentation. “Not observed” does not mean the engine cannot do it: the received program and session determine what runs.

SignalResultsKnitsailAdvertisingYouTube
Click and touch eventsYesYesNot observedYes
Mouse, keyboard, wheelNot observedYes, including positions for some mouse eventsNot observedListeners; mouse positions not read
Browser and screenVery limited: window.scrollbarsBrowser properties and dimensionsSome properties depending on the programExtensive inspection
Automation indicatorsNot observedwebdriver, window.chromeSometimes window.chromewebdriver, window.chrome
Global-name enumerationYesYesNot observedNot observed
WebGL / GPUNot observedNot observedNot observedGPU name
Tab visibilityYesNot observedYesYes, plus focus
TimingYesYesYesYes
Code and property inspectionIts own codeFunctions and browser accessorsNot observedBrowser properties

Knitsail and the YouTube VM inspect the environment more broadly than the other two VMs. But these reads reveal neither Google’s weights, thresholds nor decision model.

What the background check reads since late August

Since August 22, 2026, the background-check program also reads settings declared by the browser (navigator.platform, navigator.doNotTrack, window.doNotTrack). It creates hidden text blocks in a monospace font and compares their height with and without automatic hyphenation (hyphens). It asks the browser whether the pointer is fine or coarse (any-pointer: fine and coarse): mouse or touchscreen. Until October 5, it also queried the graphics card via WebGPU (requestAdapter, then vendor and architecture).

These reads were recorded by running the collected programs offline, from November 2025 to October 17, 2026. Our live session on October 17 confirms the settings reads and the pointer test, as well as the absence of WebGPU. Details: background check, November 2025 to October 2026.

The controlled matrix separates the launch setting from the native navigator.webdriver signal: across all our trials, the outcome follows the signal value. It cannot attribute the server verdict to a particular read by a VM (see access trials).

An interaction history in the browser

The background-check variant equipped with the localStorage module retains interaction records and reads them back on a subsequent execution. On the August 18 program, a chain of 21 runs with distinct clicks leaves exactly the last 20 records in order: the oldest is removed. These are twenty program executions, not twenty clicks within a page.

Last click

The coordinate fields retain the last observed click. A click at (123, 234), followed by movement to (500, 400), leaves (123, 234). Movement alone does not populate these fields.

Event counters

One block contains 32 one-byte counters in the tested cases. One keystroke activates three counters; three keystrokes raise them to 3. The “a” and “b” keys produce identical content: this block describes observed events without distinguishing those characters.

Binary format and storage evolution

The programs from July to October all share the same structure: an 8-byte envelope; decoded content with the 01 be ef marker, a 12-byte block, records and a final count. Each record contains a 4-byte timestamp, a one-byte field observed as 1, a 2-byte length and a variable payload. The roles of the 12-byte block and the field equal to 1 remain undetermined.

Without interaction, the payload is 114 bytes: the binary total is 24 + 121 × n bytes for n records, or 145 for one and 2,444 for twenty. Interactions lengthen the payload, so this formula does not apply to every scenario. Timestamps in all our samples match program capture time within one second, rather than the simulated visit date.

An inventory of 134 states shows ten numeric key suffixes in July and padded base64 in July–August. September–October samples use an unsuffixed key and unpadded URL-safe base64. The change is bounded by our August 18 and September 28 captures; its exact deployment date remains unknown.

The structure is observed in all the decoded programs; click, counter and twenty-run queue interventions concern the August sample. These results demonstrate neither a stable personal identifier, cross-site tracking, nor use of this history in the server score. Background-check and storage details.

Instrumentation can itself modify inspected properties. Control comparisons and replays document some perturbations; they do not prove that observation is invisible to Google.

9

From received program to submitted token

The engine can execute instructions; the received program specifies the work. A token is the result transported to Google. By itself, it is not an access authorisation.

  1. Receive

    In the studied knitsail flow, /sgasync transports the script, its hash and the encoded program.

  2. Decode

    The client transforms the bytes, decodes UTF-8 and reads the JSON envelope. This step is separate from token encryption.

  3. Execute

    The VM runs the program, reads signals and produces an output. Roles vary by program.

  4. Transmit

    The output uses the flow’s transport: a cookie, a request header or a service call.

SG_SS ≠ X-Sg-Ss

The former is an intermediate-page cookie; the latter is a header added to a retried request. Similar names do not make them interchangeable.

Hash ≠ verdict

SHA-256 hashes match the checked scripts. They identify the received code; they do not measure trust in the browser.

/sgasync envelope and fields sent to Validate

The /sgasync transport

The client reads the response as a byte array, adds 97 to each byte modulo 256, decodes the result as UTF-8 and parses it. This transport transformation is separate from token encryption. The responses examined have an eight-position envelope. The program remains separate from the VM script.

Position (zero-based)Observed content
0bfkj: envelope marker.
1Six-position array; JavaScript occupies position 5, with five leading null entries.
2 and 6null in the responses examined.
3Base64url SHA-256 of the script.
4Encoded program, with an entry-function prefix.
5knitsail: namespace.
7Auxiliary string. Its meaning is not established by this analysis.

Fields sent to Validate

The Validate requests in the initial October 17 corpus are all GETs: the reqpld parameter contains a JSON array. Their response is [""]. The code links array positions to message field numbers. We only assign meanings to the values where they are demonstrated.

Message fieldPosition and content
1Position 0: text token. Initial corpus: 1,471 to 1,544 characters (53% of calls); VPS pilot: 1,417 to 1,441 (12%); controlled series: 1,400 to 1,448 (35%). These distributions establish neither acceptance nor invisible instrumentation.
2Position 1: context; nested field 9 contains a submessage whose field 1 receives ei.
3Position 2: null in every request. The code supports a binary alternative to the text token, in the same exclusive group as field 1.
4Position 3: value 3 in every request. The code also supports 1 and 2 for another result source; this does not establish three confidence levels.
10

What the engine internals reveal

An obfuscated, rotating engine

Short identifiers, reconstructed strings and state dispatch obscure the code’s structure. Hashes, entry names and parameters change even when the version number remains 41.

Encryption operations

Engines combine addition, rotation and XOR (ARX). Settings differ between VMs. Resemblance to a cipher family is not enough to identify the exact algorithm.

Tools for summarising measurements

The code contains a Welford-style mean and dispersion update and a bounded reservoir. These capabilities do not establish which metrics the server uses to decide.

Sensitivity to source text

In offline controls, extracting code while preserving its original wrapper restores outputs. Reformatting the inner code then changes them again.

Wrapper preserved + inner code extractedOutputs restored
Same wrapper + reformatted inner codeDifferent outputs

This contrast repeats across all our tested samples. It supports source-text sensitivity without locating a specific integrity mechanism or establishing server-side detection of modifications.

Encryption, statistics and offline controls

Encryption and script rotation

The code combines additions, rotations and XOR (ARX), with 8-bit and 3-bit rotations. The engines examined use 14, 15 or 16 rounds. A constant can be literal or passed as an argument: analysis follows call sites to avoid mistaking a neighbouring loop bound for the round count. A structural resemblance to a cipher family does not establish algorithm identity.

Copy examinedRoundsConstant
Results, October 17152905
Advertising, October 17152905
knitsail, October 17161088
Homepage, October 18151795

Settings also differ between VMs served at the same time. Hash and constant changes document script rotation; they do not establish immediate invalidation of older tokens or the server’s acceptance window. Initial ! and * characters and binary token structure make it possible to compare token families; they say nothing about the verdict.

Statistics and events actually observed

The engine contains a Welford-style incremental update of mean and dispersion, then computes sqrt(M2 / n): a population standard deviation. It also contains a bounded reservoir. These routines describe engine capabilities; their presence does not establish the metrics or thresholds used by the server to decide.

n = n + 1
delta = x - mean
mean = mean + delta / n
M2 = M2 + delta * (x - mean)
standard_deviation = sqrt(M2 / n)

The results VM installs four listener types: mousedown, mouseup, touchstart and touchend. Knitsail also listens to mouse movement, keyboard and wheel events. No scroll listener was observed in these sessions. A list of 101 tag names in the code does not prove systematic monitoring of 101 elements.

Knitsail and the YouTube VM read navigator.webdriver, test the HTML element’s webdriver attribute and inspect window.chrome properties. The results VM and knitsail also enumerate global page names. The names sought in that inventory are not established. These observations demonstrate no numerical threshold separating a human from a bot.

The 96 VM replays and 48 synthetic controller cases are documented in the experimental report. Replays send no generated token to Google. Controller tests reproduce local branches without measuring server-side token validity.

11

Methods, evidence and further reading

The findings above bring observations together by topic. The source documents keep the corpora separate for traceability.

Methods and tested configurations

Configurations. Chrome 153.0.8010.52 (same binary and SHA-256), Playwright 1.51.0, Camoufox Firefox 135.0.1-beta.24 (package 0.4.11), HTTP client without JavaScript. The factorial matrix uses headed Chrome, a 1280 × 720 viewport, a CDP connection in every cell and a native webdriver getter checked before and after navigation. Four combinations run in two randomised blocks with two external ordinary controls. Playwright setting controls separately compare the flag, the list of 17 disabled features and the other 29 options.

Setup. Dedicated profiles without a personal Google account; headed browser under Xvfb. Pilot on the native VPS IP and VPN exits; session series on a fixed US exit, with fr-FR language, hl=fr and gl=fr. The exit country therefore differs from the requested country, but is identical across compared branches.

Corpora. VM observation: four sessions, three profiles and nine results pages. VPS pilot: 37 trial records, three stopped before Google, plus one open-session navigation. NID control: 21 navigations, including three source profiles and nine pairs. Browser and launch-setting comparison: 37 navigations. Webdriver factorial matrix: eight trials and two controls. Background check: 444 collected captures from November 13, 2025 to October 17, 2026; 441 run offline and 69 traced for check families, with three differently formatted Google Flights responses excluded. Storage: six decoded programs, 134 inventoried states, a chain of 21 runs with distinct clicks on the August program. Other offline controls: 96 replays of four VMs and 48 controller cases. These corpora cannot be pooled into a success rate.

Controls. The webdriver matrix holds the query, binary and IPv4 and IPv6 addresses constant; each navigation uses a fresh profile. Session controls retain the configuration and observed JavaScript identity, check the IP before and after navigation and alternate the order. Eight of nine pairs differ only in NID among transmitted cookies; the remaining pair also differs in __Secure-STRP. Waits are measured from context opening. Storage is studied offline using the collected engine and program, without submitting generated tokens to Google.

Limits. Short trials, uncontrolled server states, two repetitions per factorial cell. Browser commands set the signal in an environment where AutomationControlled is disabled. Fresh profiles are not bit-for-bit identical. Replays do not test online token acceptance; the twenty-run FIFO limit is established on the August program. The visibility test cannot compare visible/hidden conditions. Background-check dates are capture dates bounded by our neighbouring captures; the context of collected requests is unknown. Cookies, tokens, HARs, profiles and raw screenshots remain private.

Study documents and Google scripts

Study document

Other sources and studies

Oct 2026 Google BotGuard: what our tests reveal about access to results, session state, the checks run in the browser (up to four VMs on one results page) and SERP reliability Oct 2026 How Gemini searches and chooses its citations: 222,753 Google searches analysed across 76,450 public conversations Oct 2026 Search & fan-out capture V6: our Chrome extension now captures Gemini (fan-out, cited passages, prompt classifier) and ChatGPT ads Oct 2026 Chrome Decisions API tested: turning what visitors type into filters, 38% to 85% right depending on the engine, and EmbeddingGemma 2 compared Oct 2026 Google Lens Shopping: how 752 object categories are ranked (ALLOWLIST, NEUTRAL, DENYLIST) and the list applied in 2026 Sept 2026 Google Ads deep dive: how Google Ads reads the site, links pages to queries, generates creatives and prepares the auction Sept 2026 RESONEO Shop, a WebMCP demo: 135 tools exposed to an AI agent, 33 guided scenarios, live and simulated data August 2026 What ChatGPT pulls, what it shows, what it cites (updated: it searches far less broadly, and cites just as much) August 2026 Google Map dissected: 72 ranking signals and the architecture linking the Web, places and AI July 2026 ChatGPT experiments tracker: what OpenAI tests before rollout More stuffs...
RESONEO