Weighted, additive, nought to a hundred, capped at a hundred. Every point added carries a reason code, and a verdict with no reasons is a bug rather than a terse answer.
The weights follow one principle: eighty or more is a claim that this signal alone is enough to call something a bot, because eighty is the bot threshold. So the question for every rule is not “how suspicious is this” but “am I willing to publish a verdict on this evidence and nothing else”. Seven of the seventeen clear that bar. Everything below eighty is designed to stack — three thirty-point behavioural rules reaching ninety is the intended path for a scraper that leaves no single decisive mark.
The panel shows human labels rather than these identifiers. Identifiers and labels is the mapping, and it is the page to read if you are writing your own query or reading a filter URL.
| Weight | Label | What it actually tests |
|---|---|---|
| 100 | Automation marker | A definitive driver artefact was exposed to the page: the webdriver flag, a chromedriver global, or a Puppeteer, Playwright or Selenium hook. Browsers do not have these; drivers do. There is no false positive here — a page cannot acquire them by accident. |
| 100 | Declared crawler | It said it was a bot and it was telling the truth. Verdict bot, threat none. See section 04. |
| 95 | rDNS claim failed | It declared itself a major search crawler and forward-confirmed reverse DNS did not back that up. This is impersonation, not automation, and forward-confirmed reverse DNS is the mechanism the search engines themselves document for verifying their crawlers. |
| 90 | Headless renderer | WebGL reported a software rasteriser — SwiftShader, llvmpipe, Mesa OffScreen or Microsoft Basic Render — which is what you get when there is no screen. Not 100, because a virtual machine, a remote desktop session or broken graphics drivers can legitimately land here. |
| 90 | Forged beacon timing | The claimed dwell time is impossible against the issue time of its own token, by more than a five-second tolerance. Within that tolerance the number is clamped silently and nothing fires, because one-second token resolution plus a heartbeat queued behind a busy main thread produces honest overshoot. The lie is recorded rather than discarded, because the lie is the evidence. |
| 85 | UA claim failed | The engine lacks a feature that shipped in the browser version the User-Agent claims, or has one that shipped after it — with a grace of two major versions in each direction, and iOS browsers skipped outright because they are all one engine wearing another’s User-Agent. A spoofed User-Agent cannot retrofit a JavaScript engine. |
| 80 | Proxy fleet fingerprint | Five or more distinct addresses shared this exact header fingerprint within twenty-four hours on non-mobile networks, and it is not a crawler whose reverse DNS check passed. One client, many exits. |
| Weight | Label | What it actually tests |
|---|---|---|
| 75 | Sec-CH-UA mismatch | A Chrome User-Agent arrived without the matching client hint, or with one that contradicts it. Chrome always sends its own client hints on a secure origin. Requires the header to be logged. |
| 70 | Platform mismatch | The platform client hint disagrees with the operating system the User-Agent claims. Windows in the User-Agent and Linux in the hint is a headless container in a costume. |
| 70 | No JS on HTML | An HTML page was served with a 200, the User-Agent claimed a real browser, and no beacon ever arrived — and the beacon is known to be deployed on this site. That gate is not optional: on a site that never installed the snippet, every session looks like this and the rule would condemn the whole audience. Weighted 70 for the same reason in miniature, so it cannot condemn anybody on its own. |
| 45 | Datacentre + browser UA | A consumer browser User-Agent arriving from hosting address space. People do browse from servers, so this is not decisive — but it is unusual enough to be worth stacking. |
| 45 | Periodic timing | Four or more gaps between requests, a median gap of at least a second, and a spread below ten per cent of that median. Relative rather than absolute, because a 200 ms rhythm and a 30 s rhythm are equally mechanical; the median floor keeps a burst of asset fetches from looking like a metronome. People are not metronomes. |
| 40 | No interaction | The beacon ran, the session ended, and not one scroll, click, key press or touch ever happened. Possible for a human reading a page on a static screen, which is why it is 40 and not 80. |
| 35 | Timezone mismatch | The browser timezone disagrees with the timezone derived from the address. Travellers, VPN users and anyone with a deliberately set timezone trip this legitimately, so it is low. It is a stacking signal: meaningless alone, meaningful next to a fingerprint cluster. |
| 30 | No conditional requests | At least two assets were re-requested with no conditional header ever sent, and this site is known to answer with a not-modified status at all. Both extra conditions exist to avoid blaming the client for the server’s behaviour. |
| 25 | No sub-resources | HTML was fetched and not a single stylesheet, script, font or image followed it. The classic scripted-client signature — only 25, because a warm cache, a text-only browser or a prefetch can all look like this. |
| 15 | Single page, under 10s | One page, gone in ten seconds or less. Weak alone and it is supposed to be weak — plenty of humans bounce. It exists to push a session that has already accumulated other signals over a threshold. |
Figure 1 — the verdict bands. Unknown is a real answer and it is used. A session with 45 points is not “probably a bot”; it is a session Loghound does not have enough evidence about, and saying so is more useful than guessing.
A session also carries a class saying what kind of automation it was — headless browser, scripted client, declared crawler, AI crawler, monitor, spoofed User-Agent, proxy fleet, or not automation at all. The vocabulary page lists them with what each one means.
Major search crawlers and AI crawlers identify themselves. They get the verdict bot — they are bots, and counting them as human traffic is how analytics dashboards end up lying to you — with a class that says which kind.
Conflating “a search engine indexed four hundred pages” with “someone is scraping you from two hundred residential addresses” is precisely what makes existing tools useless for this. They are opposite facts: one is a service you want, the other is a cost you are paying. The separation is enforced in the ruleset rather than by a checkbox in the interface, because every consumer of a session document must see the same split.
An AI-crawler flag is set for around thirty named agents, so “how much of my content is being taken for model training” is one facet away. Note that several of those are user-triggered fetchers rather than training crawlers — they fetch a page because a person asked an assistant about it. They are grouped together because operators consistently want them in one bucket, but the two are not the same event.
A session document is written for an open session too, on every scorer run, so the panel shows traffic within a minute of ingestion starting rather than after the thirty-minute idle timeout. Such a document is marked provisional, and it is scored differently.
Five of the seventeen rules fire on the absence of something a session may still go on to do, and every one of them would accuse a live human visitor:
| Deferred rule | What its absence means while the session is open |
|---|---|
| No JS on HTML | The beacon reports on page hide — a visitor still reading has not sent one |
| No sub-resources | The sub-resource log lines have not been written yet |
| No conditional requests | Nothing has been re-fetched yet, and no conditional response has arrived yet |
| No interaction | The visitor has not scrolled or clicked yet |
| Single page, under 10s | Every session is one page and under ten seconds at second one |
So a provisional verdict rests only on evidence already present, and it is floored at unknown: it may reach likely bot or bot on positive evidence — all seven decisive-alone rules are presence-based, so an automation marker is still called immediately — but it may never claim human or likely human, because “nothing incriminating yet” on one request is not an acquittal. When the floor applies, the reasons carry a code saying so, exactly as a clean session carries one saying nothing fired.
The same discipline applies to a beacon-only session, where five transport-reading rules are silenced instead.
Next: how to change a weight, and who this ruleset gets wrong.