VisitTrack
Start free
☰ Browse the docs

Tracking

Bot filtering: humans vs bots

How VisitTrack decides whether a visit was a person, what it counts, and how to see the bots it filtered out.

Scrapers, uptime checkers, headless browsers and crawlers that run JavaScript all load your tracking script, and left alone they inflate visitors, drag bounce rate up and put countries on your map that no customer ever came from. VisitTrack classifies every visit as a human or a bot the moment it arrives, and again once the visit is over. Bots are still recorded, flagged, so you can look at them — but every number in the dashboard, the API, your reports and your bill counts humans only.

How a visit is judged

Each rule that fires adds to a score from 0 to 100. A visit is a bot when its score reaches 60, or right away when a hard rule fires. No single soft rule reaches 60 on its own (except a pageview burst), so one odd signal — a VPN, a privacy browser, a quick read without touching the page — never turns a person into a bot. The strongest rule that fired is stored as the reason.

Hard rules (a bot on their own)

ReasonWhat it means
ua:headlessThe user-agent says HeadlessChrome or another headless browser.
ua:automationThe user-agent names an automation tool (PhantomJS, Selenium, Playwright, Puppeteer…).
ua:http-clientNot a browser at all: curl, wget, python-requests, Go-http-client, node-fetch, axios, Java, Scrapy…
ua:botA self-declared crawler, monitor or link-preview fetcher (a maintained list of several hundred patterns, from the open-source isbot project), including anything claiming to be Googlebot that we couldn't verify.
ua:empty, ua:shortNo user-agent, or one far shorter than any real browser sends.
client:webdriverThe browser reports navigator.webdriver — it's being driven by automation.
client:automationAutomation-framework globals are present on the page (Playwright, PhantomJS, Selenium, Nightmare).
crawler:<name>A verified search crawler that runs JavaScript, like crawler:Googlebot or crawler:Bingbot (see below).

Scored rules

ReasonPointsWhat it means
behavior:burst60More than 5 pageviews within 3 seconds, with no interaction. Nobody reads six pages in three seconds.
asn:AS<number> <provider>40The IP belongs to a hosting or cloud provider (AWS, Google Cloud, Azure, Hetzner, DigitalOcean, OVH, Alibaba, Tencent, Vultr, Linode, Contabo, M247, Leaseweb and ~800 more). VPN exits and cloud desktops live there too, so this only counts together with another signal.
client:screen40A 0×0 or physically impossible screen size.
client:no-languages35The browser reports no preferred language — every real browser reports at least one.
behavior:no-interaction30 (15 on phones and tablets)The visit ended without a single mouse movement, click, scroll, key press or touch.
net:burst30At least 8 visitors arrived from the same network within 10 minutes and 90% of them never interacted. Computers only — phones share networks through their carrier, so they're never judged by this.
client:ua-mismatch30The user-agent claims Firefox or Safari, but the browser exposes Chrome-only features.
client:no-chrome25A desktop Chrome, Edge or Opera user-agent without the window.chrome object every real one has.
client:no-plugins20Desktop Chrome reporting no plugins (real Chrome lists its built-in PDF viewer).
client:hardware10CPU core or memory values no real device reports.
client:timezone10The browser's time zone doesn't fit the country of its IP address. Deliberately weak: travellers and VPN users do this all the time, and it's never counted on a hosting-provider IP.

For example: a visit from an Alibaba Cloud IP scores 40 and stays human. If it then leaves without ever moving the mouse, it gains 30 more, reaches 70, and is flagged with the reason asn:AS45102 Alibaba Cloud. A person on a VPN who scrolls the page stays at 40 — human.

When each rule runs

  • When a visit starts — user-agent, hosting provider, crawler verification and the browser signals above.
  • On every pageview — the pageview burst.
  • About 30 minutes after a visit ends — no interaction, and many visitors from one network. Until then, a visit caught only by these rules briefly counts as a person.

Crawlers vs bots

Google and Bing render pages with a real browser, so their crawlers do run the script. When the user-agent claims to be Googlebot or Bingbot, VisitTrack checks the IP with a forward-confirmed reverse DNS lookup (the IP must resolve to googlebot.com / search.msn.com and back). Verified crawlers are labelled crawler:Googlebot and shown as crawlers rather than bad bots — but they're still not people, so they're excluded from your numbers too. An unverified claim is just ua:bot. Crawlers that never run JavaScript (most AI crawlers) are tracked separately — see AI crawler tracking.

Signups and payments are always human

A visitor who signs up or pays is a customer, whatever the rules said. When a visitor fires a signup (or sign_up), payment, payment_completed or purchase event, or a payment is attributed to them through revenue attribution, they're marked human for good (reason override:converted) and no rule can flag them again. One exception: a signup event from a visit that announced itself as automation (a headless or webdriver-driven browser — typically an end-to-end test running against production) doesn't count. A real payment always does.

Seeing the bots

  • Dashboard — the Humans / Bots / All toggle switches every chart and table between people only (the default), bots only, and everything. The Bots filtered card shows how many visits were filtered and why, grouped by reason.
  • API — every read endpoint accepts ?traffic=human (the default), ?traffic=bot or ?traffic=all.

Only the verdict is stored

The browser signals the script sends when a visit starts (whether webdriver is on, how many languages and plugins it reports, core count, memory, screen size and time zone) are used for the decision and thrown away — they're never saved, so they can't become a fingerprint. What's stored is the verdict: human or bot, a score, and one reason. IP addresses are never stored either: the hosting-provider check happens in memory, and the network rule uses a hash of the IP's network that changes every day and can't be linked across sites. Bot filtering works the same in cookieless mode.

What the script sends

On the first pageview of a visit the script adds a small sig object (the signals above), and every request carries ia: 0 until the visitor first moves the pointer, scrolls, presses a key or touches the page, 1 after. That's the whole footprint — about 200 bytes of script. Nothing about where or how the visitor interacted is sent.

Testing your own site with Playwright or Selenium?

Those visits are recorded as bots (client:webdriver) and won't show up in your numbers — switch the dashboard to Bots or All to see them.

Something missing? Tell us.

AI agent or LLM? Read this page as markdown.