Update, 2026-10-06: Applebot after the window closed, and one more renderer.

  • Applebot. The 32 beacons below are its count when this post’s window closed, on 2026-08-06 at 15:02. Over the next day it made 17 more verified test-cell fetches, and a beacon followed 16 of them, one on hash-routing, so it has now fired on all eight content patterns. In total it sent 48 beacons, all through the React component, and a beacon followed 45 of its 49 verified fetches within an hour. Verified Applebot has not fetched a test cell since 2026-08-07; the Applebot user agents on test cells since then failed reverse DNS.
  • Baidu. Its crawler was filed under other-bot when this post was written. Between 2026-07-16 and 2026-09-27, Baiduspider made 39 test-cell fetches, of 19 different server-rendered pages, from China Telecom and China Unicom networks (AS23724 and AS4837). A beacon from Baiduspider-render followed 37 of those fetches, with a median delay of 8 seconds. Every rendered fetch ran the React component and 5 also ran the inline script, 38 and 5 beacons in all. That puts Baidu in the full tier, though it skips the inline script most of the time. Its renderer never used the address that fetched the page: 39 of its 40 beacon addresses sent the beacon from China Unicom’s network, and Cloudflare’s log has no row for the last one. The tracker cannot verify Baidu yet: Baidu documents reverse DNS, which the tracker doesn’t check. It does now, since a change later the same day: every Baidu request from the China Telecom and China Unicom networks passed, 120 in all, 42 of them Baiduspider-render’s beacon calls, and all 58 Baiduspider requests from VPS hosts failed. Requests calling themselves Baiduspider from the same three networks as the fake Google-CloudVertexBot made 13 test-cell fetches and fired no beacon. The Baidu result is exploratory: no pre-registered hypothesis covers it, and most of its data comes after 2026-08-07.

Update, 2026-10-06: two more beacon sources after this post’s window. Meta-ExternalAgent fired the beacon 83 times between 2026-08-10 and 2026-08-20: 59 through the inline script and 24 through the React component, on 21 cells, from 66 addresses. Meta publishes no crawler IP list, but 65 of the 66 addresses made every other request we logged from Meta’s network (AS32934); the last one made no other request to check. For that period Meta-ExternalAgent belongs in the full tier, not the zero tier; details in Meta-ExternalAgent ran our JavaScript on 23 of 32 page fetches. GPTBot added four inline fires on 2026-08-15, seven in total from two addresses on OpenAI’s published list, and still none through the React component. The inline-only reading holds, on a slightly larger sample.

Update, 2026-10-05: one more renderer, found after this post’s window. ShapBot, the crawler behind Parallel’s search APIs for AI agents, was filed under other-bot until 2026-10-05. Re-classified, it accounts for 50 beacons, 25 through each channel, on 2026-08-29 and 2026-09-16. All 203 of its requests came from addresses on Parallel’s published IP list, and every beacon came from one of those addresses. That puts it in the full tier. It does not render every page, though:

  • client-side-rendered cells: a beacon after all 41 fetches;
  • server-rendered cells whose main content is missing from the HTML (click-reveal, js-fetched, mixed): a beacon after 10 of 32 fetches;
  • cells whose content is already in the HTML: a beacon after none of 67 fetches.

That looks like a crawler that renders only when the HTML arrives without the content. It would be a third way of handling JavaScript, next to the two depths below. Two days of crawling are too few to call it a rule. This update and the one above are exploratory: their data comes after the planned Phase 1 window, which ended on 2026-08-07 (methodology).

Correction, 2026-10-03: a re-check against the raw tracker database found four errors, all fixed below. The full tier’s inline count is 133, not 122 (one of the two 11s was left out of the sum). Applebot fired on seven of the eight content patterns, not all eight: none on hash-routing, as Figure 2 already showed. The component channel went live on 2026-05-22, so the two channels did not run in parallel for the whole window. And GPTBot was not the only batch AI crawler with a beacon: a crawler identifying as AIWebIndex/2.0 fired both channels on 2026-06-10. Applebot’s render rate is now also given per request.

We already knew NotebookLM runs JavaScript and Bingbot splits into a JS and a non-JS subsystem. Both findings came from one beacon firing, or not firing. This one comes from the beacon firing through the wrong channel - and it turns “does the bot run JS?” into “how deep does it go?”

Two channels

The Layer 3 beacon has two independent delivery paths:

  • Inline - an inline <script> at the end of <body>, sent as an image request. Fires if the bot executes raw inline script.
  • Client-component - a React client component running in a useEffect, sent as a fetch(). Fires if the bot evaluates the React bundle and runs the component lifecycle.

Both ran in parallel from 2026-05-22, when the component channel went live, until the last inline fire on 2026-08-01. So “fired one channel but not the other” is a property of the renderer, not an artifact of timing - in any week where one bot fired the inline channel, another fired the component channel.

Four tiers

applebotgoogle-readaloudgooglebotnotebooklmgptbotgsc-inspectionbingbotheadless-chrome 32 12 7 1 3 11 inline scriptReact client component
Figure 1 - Beacon fires per bot, inline channel (coral) vs React-component channel (blue). The Google and Apple renderers fire only the component channel; GPTBot fires only the inline channel; Bing, GSC inspection and headless Chrome fire both. (Human traffic, 106 inline / 46 component, is omitted for scale.)
tier classes inline component reading
Bundle-evaluators applebot, googlebot (WRS), google-readaloud, google-other, notebooklm 0 54 Evaluate the React tree, skip the inline <body> script
Inline-only gptbot 3 0 Runs a raw inline script, does not evaluate the bundle
Full human, headless-chrome, gsc-inspection, bingbot 133 65 Both channels - full browser-class execution
Zero claudebot, amazonbot, ccbot, meta-external, oai-searchbot, perplexitybot, chatgpt-user, claude-user, perplexity-user, google-extended, bytespider 0 0 No beacon, ever

Two headline numbers

Applebot renders almost everything it crawls. 32 component-channel beacons against 32 verified Applebot cell fetches, spread across seven of the eight content patterns (none on hash-routing). Per request, 29 of the 32 fetches were followed by a beacon from the same cell within an hour. Applebot belongs with Googlebot-WRS in the full-renderer club, not with the batch AI crawlers.

cleanlate-loadedmixedjs-fetchedjs-linksclick-revealjs-images 15 6 4 3 2 1 1
Figure 2 - Applebot component-channel beacons by content pattern. It rendered on seven of the eight patterns, not just the easy cells.

GPTBot is the only named batch AI crawler that runs any JS at all - and only the inline channel (three fires, one cell, one day). Every other batch AI crawler the tracker names produced exactly zero beacons across 80 days. One crawler outside those classes did fire: AIWebIndex/2.0, which the tracker files under other-bot, sent 10 inline and 10 component beacons from 7 addresses on 2026-06-10.

Why the beacon population is trustworthy

A spoofer sending a fake user-agent to a static scraper cannot fire the beacon - firing it requires actually executing the page’s JS. So this layer self-selects for genuine renderers; the nine-IP impersonation pool that pollutes the HTTP logs never appears here. The beacon, not any HTTP side-effect, is the authoritative execution signal.

What this means for site owners

The tiers imply a specific rule for JS-gated content:

  • Injected by an inline <script>: seen by GPTBot, skipped by the renderers that matter most (Google WRS, Applebot, Read Aloud, NotebookLM), which treat the inline <body> script as boilerplate.
  • Behind React (useEffect, client fetch, hydration): seen by Applebot, Googlebot-WRS, Read Aloud and NotebookLM; invisible to GPTBot and every zero-JS batch crawler.
  • In the server-rendered HTML: seen by everyone.

If you must hide content behind JavaScript, put it in the React component lifecycle, not an inline script. But the only channel that reaches the zero-JS majority - ClaudeBot, Perplexity, Amazon, CCBot - is server-side rendering.

What this does not prove

  • The mechanism is confounded. The inline channel is both an inline script and an image-beacon, so we cannot fully separate “skips the inline script” from “blocks analytics-shaped image requests.” The effect on content visibility is the same; the cause is not isolated.
  • GPTBot’s inline result is thin (n=3, one cell, one day). Directional, not robust.
  • The beacon is a floor, never a ceiling. A bot can render fully and still drop the beacon (sandbox, keepalive). Every tier is a lower bound on execution.

What would falsify this

If, in a fresh window, Applebot starts firing the inline channel or GPTBot fires the component channel, the tiers are less clean than they look here. And if a claudebot or amazonbot beacon ever appears, the zero tier breaks - that single row would be a bigger finding than this whole post.

Method notes

Beacon rows are stored with a source of inline or client-component; the counts above are direct group-bys over the js_executions table for the full window. Applebot’s render rate compares its 32 component beacons against its 32 verified (reverse-DNS confirmed) content fetches in the canonical HTTP log - aggregate counts, so read it as “near 1:1,” not exact. A per-request join (a beacon from the same cell within an hour of a verified fetch) gives 29 of 32, about 90%.


Data availability: methodology, tracker code, classifier and beacon source are in the repository at github.com/Qbeczek1/jsseo-dev, private for now; access on request at [email protected].

Bias disclosure: I run JS SEO Lab as an independent technical SEO research project, and do paid technical SEO and AI-visibility audits through FratreSEO. No framework vendor, crawler vendor, search engine, or AI company funds this work.