Skip to content
Sign inStart free trial

Bot detection

MetriXs uses multiple layers to filter out bot traffic from your analytics.

  • User-agent filtering — the isbot library covers 1500+ known bots
  • Automation patterns — blocks Puppeteer, Playwright, Selenium, python-requests, curl, Scrapy, and more
  • Rate limiting — max 120 events per IP per minute, plus a per-/24-subnet cap (200 events / 5 min) to catch distributed botnets (Redis-backed)
  • Domain verification — the Origin header must match the registered domain
  • Accept-Language check — requests without a valid Accept-Language header are dropped
  • Browser fingerprint token — the tracker encodes real browser signals (screen size, timezone, hardware concurrency, etc.) into a token that raw HTTP bots cannot produce

The tracker script also detects bots before sending events:

  • navigator.webdriver === true — Selenium/CDP
  • window._phantom, window.__nightmare — PhantomJS, Nightmare.js
  • window.Cypress — Cypress test runners
  • screen.width === 0 — headless Chrome
  • navigator.languages.length === 0 — many headless environments

MetriXs uses the MaxMind ASN database to identify traffic from known cloud and datacenter providers. Events from these networks are dropped automatically, as they are almost always automated:

  • AWS, Google Cloud, Azure, DigitalOcean, Hetzner, OVH, Linode
  • Alibaba Cloud, Tencent Cloud, Huawei Cloud, ByteDance, Cloudflare Workers
  • And many more

Add localStorage.setItem('metrixs_ignore', 'true') in your browser console to exclude your own visits.

The dashboard’s Security tab shows a Blocked bots card: how many bot requests were dropped in the selected period, with breakdowns by reason, country, and page. Blocked requests never count toward your stats, the card only shows that filtering is active.

The tracker records a pageview on every page that loads it, including error pages. When a site goes offline or is restructured, crawlers keep re-checking the old URLs for months. Those re-checks show up as pageviews on paths that no longer exist, with a recognizable pattern: exactly one pageview per visitor, no referrer, no scroll and no time on page, and a geographic spread that follows the crawler’s proxy network instead of real readers. This traffic runs real JavaScript, so it is not blocked.

If you recognize this pattern, three options, in order of impact:

  1. Remove the snippet from the error-page template. The most targeted fix when 404 traffic is pure noise: crawlers and stray visitors stop being counted, while real pages keep full tracking.
  2. Track 404s explicitly. Add the 404 meta tag to the error-page template: every 404 then also records a 404 event with the requested path in the Auto-tracked Events card, so dead URLs with real visitors (for example broken internal links) become visible. The pageviews themselves still count.
  3. Serve 410 Gone for permanently removed paths. Crawlers and search engines de-index 410 responses faster than 404s, so the re-check traffic fades out over time.