ReleaseInsight · On RadarHabr AI→ original

Traffic Is Up, Orders Are Not: How Headless Bots and AI Agents Hide in Metrika and GA4

Traffic keeps growing while orders stand still: some of the "visitors" turn out to be browsers with no human behind them. The author put a counter resembling Metrika and GA4 on a test page and opened it from curl, Python and Playwright. Crawlers without JavaScript never reach the reports, while any Chromium produces a full visit with depth and a cookie.

AI-processed from Habr AI; edited by Hamidun News
Traffic Is Up, Orders Are Not: How Headless Bots and AI Agents Hide in Metrika and GA4
Source: Habr AI. Collage: Hamidun News.
Listen to article
Article Fact Sheet & Key Figures
ParameterDetails
Primary sourceHabr AI ↗
Editor-in-Chief
Key metric #1curl and requests show up only in the server log, the counter stays silent
Key metric #2Playwright is indistinguishable from a human after a couple of lines of masking
Giveawaysa data-center IP, SwiftShader in WebGL and a frameless window

The traffic chart has been climbing for the third week, marketing is happy, and there are no orders. The product manager walks through the funnel step by step and finds nothing broken. Maybe there is nothing to fix: part of the "visitors" simply are not people. According to Cloudflare data from September 30, 2026, more than half of internet traffic is already generated by non-humans, and AI agent requests have grown by more than 1700% in a year.

Who the Counter Hears

An analytics counter lives as a script on the page. No executed JavaScript means no hit. The author of the piece tested this in practice: he put a mini-counter on a test page that does the same as the Metrika and GA4 tags (collects browser data, sends a ping after 3 seconds, sets a first-party cookie), and opened the page with different clients. Next to it, nginx wrote its own log.

The result is simple. curl, Python requests and even curl with the GPTBot User-Agent remain only in the log. Any Chromium, including Playwright in different modes and chrome --headless --dump-dom, leaves both a log entry and a counter hit. The large AI crawlers from OpenAI and Anthropic download JS files but do not run them. Gemini (through Googlebot infrastructure) and AppleBot do execute JavaScript. The author found no fresh independent measurements.

Hence a practical rule: if traffic on the server has grown but not in Metrika, it is most likely crawlers, and they are harmless to analytics. The dangerous ones are those visible in analytics.

How Headless Browsers Disguise Themselves

Unmasked Playwright with headless=True gives itself away immediately: HeadlessChrome in the User-Agent and Client Hints, no Accept-Language, empty plugins, webdriver=true. Checking a single UA string is enough. With channel='chromium' (the new headless) the picture is different: Client Hints show ordinary Chromium, and a detector that has switched to Client Hints will let such a browser through.

After a couple of lines of masking (custom UA, 1536×864 screen, Russian locale, Moscow time zone, an anti-webdriver flag, a Yandex referrer, mouse movements), half of the signals disappear. Mouse events arrive with isTrusted=true, so the flag cannot tell them apart.

What remains are inconsistencies that cannot be fixed inside the browser context: the UA says "Windows" while navigator.platform says "Linux"; there is no Google Chrome brand, because Playwright uses Chrome for Testing; the outer window size equals the inner one; and WebGL runs on software SwiftShader. The last signal is weak on its own (a human in a virtual machine looks the same), and Chrome 153 already warns that falling back to software WebGL is deprecated. A data-center IP cannot be fixed at all.

What to Do

GA4 excludes bots using a closed list from Google and the IAB; this cannot be turned off, and the volume filtered out cannot be viewed. The "AI Assistant" channel in GA4 counts referrals from assistants and has nothing to do with bots. In Metrika, robots that identify themselves in the UA are excluded immediately, while those detected by behavior are counted by default. Start by switching "Data: without robots" and "Compare with data with robots". The second comparison happens outside Metrika: growth in the report versus growth in the server log.

On simulated data (the shares were set by the author, so the percentages prove nothing) the combination of signals matters. Individually, direct visits, bounces or English language can be explained by newsletters, landing pages and advertising. Together with a hosting network and a falling share of returning visitors, they are hard to explain.

The combination "hosting network, direct visit and a visit under 2 seconds or zero scroll" catches 86% of bots and affects 0.43% of humans, but of agents with human-like behavior it finds only 215 out of 844. The combination "hosting, new visitor, server-class screen" caught 745 of 844 with 1.

2% of humans affected. For this you will have to add IP-to-ASN tagging to the Logs API export yourself.

Signatures and Agents in the Browser

ChatGPT agent signs requests under RFC 9421 (Signature, Signature-Input and Signature-Agent headers), and only the server sees this. Add $http_signature_agent to the nginx log format and count such visits there. The Web Bot Auth protocol is still an IETF draft from September 1, 2026, but OpenAI, Google and AWS already sign requests with it.

The situation is worse with agents inside the user's own browser: Comet, Atlas, Claude in Chrome. To Metrika and GA4 this is an ordinary person on an ordinary machine, and no environment signal fires. Night-time traffic will not help either: agents are launched by people, so their activity follows the human weekly cycle.

Takeaway for the product manager: do not fix the funnel until you have reconciled the report with the server log. And agent visits will have to be counted as a separate visitor type with a different conversion rate.

Story

Key Questions Answered

Who the Counter Hears?

An analytics counter lives as a script on the page. No executed JavaScript means no hit. The author of the piece tested this in practice: he put a mini-counter on a test page that does the same as the Metrika and GA4 tags (collects browser data, sends a ping after 3 seconds, sets a first-party cookie), and opened the page with different clients. Next to it, nginx wrote its own log. The result is simple. curl, Python requests and even curl with the GPTBot User-Agent remain only in the log.

How Headless Browsers Disguise Themselves?

Unmasked Playwright with headless=True gives itself away immediately: HeadlessChrome in the User-Agent and Client Hints, no Accept-Language, empty plugins, webdriver=true. Checking a single UA string is enough. With channel='chromium' (the new headless) the picture is different: Client Hints show ordinary Chromium, and a detector that has switched to Client Hints will let such a browser through.

What to Do?

GA4 excludes bots using a closed list from Google and the IAB; this cannot be turned off, and the volume filtered out cannot be viewed. The "AI Assistant" channel in GA4 counts referrals from assistants and has nothing to do with bots. In Metrika, robots that identify themselves in the UA are excluded immediately, while those detected by behavior are counted by default. Start by switching "Data: without robots" and "Compare with data with robots".

ZK
Zhemal Khamidun — CPO at Alpina Digital, product manager of AlpinaGPT. Building AI products since 2019. Hamidun News is a pet project that grew into a production aggregator with 6,000+ readers.
✦ Private AI Builders Community · Vibe Club

Ship AI Faster with Founders, Engineers & Weekly Architecture Reviews

Inside Vibe Club (hamidun.com/club) — weekly live masterminds with Zhemal Khamidun, Tech Radar, full LMS access, and 370+ production Claude Code skills.

Join Vibe Club →Explore Hamidun Academy
What do you think?
Loading comments…