p4ni.

Research

Fingerprinting AI Browsing Agents: They Never Move the Mouse

· 7 min read

On this page

Every bot detector on the web is about to meet a new kind of visitor: a real browser, on a real machine, sometimes inside a logged-in session — driven by a language model instead of a person. Wang, Vekaria, and Shafiq built a test bench to ask the obvious question: can you actually tell? They ran 7 AI browsing agents and 56 human participants through the same three web tasks and measured everything — 418 browser fingerprinting features and 50 behavioral ones.

That’s “FP-Agent: Fingerprinting AI Browsing Agents” (May 2026, preprint — not yet peer-reviewed). The agents are the ones you’d expect: OpenAI’s Atlas Browser and ChatGPT Agent, Anthropic’s Claude for Chrome, Perplexity’s Comet, Manus, plus the open-source Browser Use and Skyvern. The tasks are the ones agents are actually being sold for: booking a flight (multi-step forms, date pickers), online shopping (search, filter, select), and forum interaction (read a thread, write a long reply). A thousand runs per agent, 546 human sessions as the baseline.

The headline splits cleanly in two. Browser fingerprints — the classic stack of screen resolution, fonts, CPU cores, timezone — managed an F1 score of 0.80 at telling agents from humans and from each other. Behavioral fingerprints alone hit 0.999. Combined: 1.000. Every agent, every human, every run. And the single most damning behavioral signal is almost funny: the agents never move the mouse. No mousemove events at all — the cursor teleports to the click target.

Why browser fingerprints can’t do the job

The fingerprinting result is worth understanding before the behavioral one, because it kills the approach most existing bot infrastructure is built on.

The problem isn’t that agents lack fingerprints — it’s that their fingerprints are someone else’s. Atlas Agent, Browser Use, and Claude for Chrome shared identical browser fingerprints in the study’s setup, because a browser fingerprint describes the browser and the machine, not the thing driving them. Claude for Chrome runs inside the user’s own Chrome, so its fingerprint is just… the user’s, varying with whatever machine it runs on (the study observed 2 distinct fingerprints across its test environments, tracking the environments themselves). Locally-run open-source agents inherit whatever box they’re launched from.

Cloud-hosted agents are more distinctive, but not more honest. Manus consistently reported the same tidy datacenter profile — Linux x86_64, 4 GB RAM, 6 CPU cores — which makes it recognizable as infrastructure, not as an agent per se. ChatGPT Agent flipped between reporting Linux x86_64 and MacIntel across runs, which is its own kind of tell but a brittle one: it identifies a configuration choice OpenAI could change tomorrow, not anything intrinsic to agent-ness.

That’s the structural issue. Browser fingerprinting was designed to answer “is this the same browser I saw yesterday?” The question that matters now is “is a human operating this browser right now?” — and no amount of canvas hashing answers it, because the browser is genuinely real. An agent in a user’s Chrome profile is indistinguishable from the user by construction, right up until it starts doing things.

The behavior is unmistakable

Then it starts doing things, and everything changes. Three channels, each individually damning:

Typing. The keystroke-simulating agents type with inter-key intervals of 1.39 ms (Manus), 5.31 ms (Browser Use), and 9.52 ms (Skyvern) — machine-gun cadence with almost no variance. Humans are slower and, more importantly, inconsistent: high inter-key and hold latencies with substantially greater spread. The other agents don’t type at all — ChatGPT Agent issues Ctrl+V, Atlas and Comet fire paste events. A form field that fills via paste on a site with no clipboard workflow is its own signal.

Scrolling. Humans scroll in long, variable, overlapping gestures. Agents jump — discrete offsets or short bursts to a computed position, then stillness. (One exception: ChatGPT Agent scrolls more than humans, longer distances and durations — which just makes it anomalous in the other direction.)

The mouse. This is the one I keep coming back to. Human cursors wander: hundreds of mousemove events, curves, overshoots, corrections. The agents produce none. Click events simply materialize at the target coordinates with no path leading to them. Of all the signals in the paper this is the hardest to wave away — there’s no legitimate human interaction mode where the cursor teleports.

Feed the 50 behavioral features to an XGBoost classifier (80/20 train-test split) and you get that 0.999 F1 — not just human-versus-agent but which agent, since each one’s automation stack has its own motor signature. Add browser features and it’s 1.000.

Cloudflare caught one agent out of seven

The paper’s case study is the part with immediate operational relevance: run all seven agents against a site behind Cloudflare’s free-tier bot management. Result: one detection out of seven. Manus — the one with the loud datacenter fingerprint — got caught. The other six sailed through.

That number deserves to be read carefully rather than triumphantly. Free-tier bot management is tuned for the bots that existed before 2025: headless browsers, script kiddies, scrapers with fake user agents. I’ve measured that regime from the inside — my robots.txt and rendering tests looked at how AI crawlers fetch pages, and crawlers mostly do identify themselves. Browsing agents are a different animal: real Chrome, residential-looking context, no self-identification header in sight. The study’s conclusion is blunt — self-identification alone is not a reliable basis for detecting or controlling browsing-agent traffic. The infrastructure assumed cooperation, and the new traffic class doesn’t cooperate. It doesn’t even decide not to cooperate; it just runs in a place the cooperation protocols never covered.

I keep landing in this territory from different directions. Astro 7’s agent detection is the cooperative version of this exact problem — environment variables that agents choose to set, checked with string comparisons. It works because coding agents have no incentive to hide from their own dev server. (Moltbook, the agent-only network I covered earlier, runs the same check in reverse — proving the visitor is an agent, with agents deploying verification schemes on each other.) The prompt-injection field study I covered in the previous post found 3,096 injection attempts whose whole purpose was AI bot identification — site operators planting canary challenges in page content because they had no better detection tool. This paper is what “a better tool” looks like: don’t ask the visitor what it is, don’t trick it into confessing — watch its hands.

What I’m taking from it

If you run a website, the actionable half is knowing what your bot analytics can’t currently see. Some slice of your “human” traffic is already agents wearing user browsers, and header-based or fingerprint-based tooling will not surface it. Before reaching for behavioral blocking, though, ask what you’d actually be blocking: a browsing agent usually acts on behalf of a specific human who wanted something from your site — a purchase, a booking, an answer. That’s not scraper traffic; that’s a customer with a weird input device. My own position hasn’t moved since the llms.txt post: serve clean static HTML, be legible to machines on purpose, and save the adversarial machinery for traffic that actually causes harm.

If you build agents, this paper is a roadmap of everything your automation stack leaks. Fixed-interval keystrokes, paste-only input, teleporting cursors — all trivially patchable with humanized motor noise, and you can bet the frameworks will patch them now that there’s a published classifier to test against. Which is exactly how detection arms races start: today’s perfect F1 is a snapshot of automation stacks that weren’t trying to hide.

The caveats are real. Seven agents, 56 undergrads, three lab tasks, one site behind one CDN’s free tier — and a 1.000 F1 on a dataset of that size should be read as “cleanly separable today,” not “solved forever.” The authors flag the coverage limits themselves. But the structural finding doesn’t depend on the exact numbers: identity signals describe the browser, behavior describes the operator, and only the second question matters now.

The part I find genuinely clarifying is that the mouse — the least secure, most ignored input on the web — turns out to be the closest thing to a Turing test we currently have in production. Nobody designed it that way. Twenty years of fraud detection tried to answer “is this browser lying?”, and the answer to the question that replaced it was sitting in the mousemove stream the whole time.