Bot detection

How Rybbit identifies and filters bot traffic from your analytics

Rybbit checks every incoming tracking request against several detection layers, on every site. The per-site Block Bot Traffic setting decides what happens to a request that a layer flags as a bot.

Block Bot Traffic

Block Bot Traffic is on by default for new sites. To change it:

  1. Open your site in the Rybbit dashboard
  2. Go to Site Settings
  3. Toggle Block Bot Traffic
SettingWhat happens to a detected bot
On (default)The request is kept out of your normal analytics and stored as a bot event instead.
OffThe request is tracked like any other visit and counts toward usage. It does not appear in bot events.

What Happens to Detected Bots

With blocking on, detected bot requests are not added to your normal analytics data. This keeps dashboard totals, reports, journeys, funnels, session lists, and usage metrics focused on human traffic.

Blocked bot requests also do not count toward billable usage, because usage is counted from your normal analytics events only. With blocking off, detected bots are tracked and billed like any other traffic.

For blocked requests, Rybbit stores a compact bot event record so you can inspect what was filtered. Bot event records include route, device, location, ASN, and which detection layers matched.

Detection Layers

Rybbit runs all detection layers before making a final decision. A request can match multiple layers, and the bot event records every layer that matched.

For sites set up as mobile apps, the user-agent and header layers are skipped, because native app traffic legitimately looks like a non-browser HTTP client. The other layers still run.

User-Agent Patterns

The ua_pattern layer checks the request user-agent against known bot, crawler, AI agent, SEO tool, monitoring, social preview, framework, and headless browser patterns.

Examples include:

  • Search engine crawlers
  • Headless browser user-agents
  • AI crawler and agent user-agents
  • SEO and monitoring tools
  • Script or framework HTTP clients

Header Heuristics

The header_heuristics layer scores request headers for browser consistency.

It looks for signals such as:

  • Missing browser headers
  • Suspicious fetch metadata
  • Inconsistent browser claims
  • Headless or automation-looking headers
  • Stale or unusual Chrome versions
  • Script/framework-style requests that do not look like normal browser traffic

This layer is useful because many bots use a browser-like user-agent but do not send the full set of headers a real browser normally sends.

Client Signals

The client_signals layer uses lightweight browser-side signals collected by the tracking script.

Signals include:

  • Automation APIs
  • Zero or impossible window dimensions
  • Default automation viewport sizes on desktop browsers: 800x600, 1024x768, and 1280x1200
  • Square screens (a heuristic: a few real monitors are square, but most square screens in traffic are renderer defaults)
  • Suspicious outer window dimensions
  • Missing browser APIs
  • Missing Chrome globals
  • SwiftShader renderer signals
  • Empty plugin lists

The server also notes when a web hit arrives with no screen dimensions at all.

Rybbit combines these into a weighted score. Strong signals (automation APIs, impossible dimensions, the default viewports, and square screens) can identify bot traffic on their own. Weaker signals only add supporting evidence when another layer has already flagged the request.

ASN and Network Signals

The bot_asn layer uses ASN metadata from the resolved IP address.

There are two kinds of ASN matches:

  • Curated bot provider ASNs: Known AI, scanner, and internet measurement providers can trigger bot detection directly.
  • Generic hosting/datacenter ASNs: Hosting ASNs are treated as supporting evidence. They are recorded when another bot layer also matches, but generic hosting ASN alone is not enough to block a request.

This avoids filtering every legitimate visitor who happens to browse through a cloud, CDN, VPN, corporate gateway, or first-party proxy, while still preserving ASN context when other bot evidence exists.

Rate and Anomaly Detection

The rate_anomaly layer watches for bursty or crawl-shaped behavior.

It watches rolling windows, from seconds to a day. Rules that describe a single visitor (one IP and user agent) can flag a request on their own:

  • Too many events, or too many distinct paths, from the same IP and user agent in a short window
  • Interaction events (clicks, copies, form events) faster than a person can produce them
  • A busy browser fingerprint spread evenly across many browser versions, which real visitor populations don't produce
  • During a traffic flood measured against the site's own normal volume, a burst of one-shot visitors arriving directly, or a single hosting-network address sending a large share of events
  • Very high daily volume from a single address on a hosting or datacenter network

Rules about things many real visitors share, such as one IP address or one popular user agent, only add supporting evidence and never flag a request alone:

  • Too many events from the same IP
  • Too many different user agents from one IP
  • Too many hostnames from one IP
  • High site-wide volume from one user agent
  • High daily volume from one IP address
  • A burst of requests missing the client-side bot score

This layer is designed to catch fast crawlers, floods, slow distributed crawlers, and replayed tracking requests that may not have obvious user-agent or browser fingerprint signals.

Bot Identity

Every detected bot carries the layers that caught it. Bots matched by one of Rybbit's curated user-agent patterns carry three more fields, which is what the Bots dashboard groups by:

FieldExampleMeaning
bot_nameGPTBotThe name the bot publishes in its user agent
bot_operatorOpenAIWho runs it
bot_purposeai_trainingWhat the fetch is for

A bot matched only by a broad pattern (crawl, spider) is still filtered, but has no published identity — those rows read as Unnamed, which is more useful than a guess.

Purposes

bot_purpose answers a different question from bot_category. Category groups bots into families; purpose says what the operator does with the page, which is the distinction that matters for AI traffic:

PurposeWhat it means
ai_trainingCollecting pages to train a model. Sends no readers back. Examples: GPTBot, ClaudeBot, CCBot, Google-Extended, Bytespider
ai_searchIndexing pages so an assistant can cite them. Can send readers back. Examples: OAI-SearchBot, Claude-SearchBot, PerplexityBot
ai_agentA person asked an assistant to open the page, and it fetched it there and then. Examples: ChatGPT-User, Claude-User, Perplexity-User, Google-Agent, Claude Code
searchClassic search engine indexing
social_previewLink unfurling
seoBacklink, rank, and site-audit crawlers
monitoringUptime, synthetic, and performance checks
securityScanners
scriptedHTTP libraries and CLI clients
headlessBrowser automation

Splitting the AI family in three is the point: a training crawler reading 4,000 pages and a person's assistant opening one page are both category: ai, but they mean opposite things for your site.

These fields were added in a later release. Bot events recorded before then have empty identity fields and appear as Unnamed / Unclassified; nothing is backfilled.

How Decisions Are Made

Rybbit does not stop at the first matching layer. It runs every layer, records all matches, and then makes one final decision.

A request is marked as bot traffic when at least one blocking layer matches. The resulting bot event includes boolean fields for each layer:

  • User-agent pattern
  • Header heuristics
  • Client signals
  • Bot ASN
  • Rate anomaly

Because multiple layers can match the same request, per-layer bot counts can add up to more than the total number of bot requests.

Server-Side Tracking

Requests sent to /api/track with Authorization: Bearer <api key> and a valid key for the site with the ingest:write scope (or an unrestricted key) are treated as trusted server-side ingestion. Four of the five layers are skipped: the headers, the client signals, the network address, and the request rate all belong to your server, not to the visitor it is reporting, so scoring them would convict your own backend.

The user-agent layer still runs, on the user_agent you send. Nothing changes for ordinary backend events — a request reporting a real browser's user agent is tracked normally.

Reporting crawlers that never run JavaScript

Rybbit's tracker is JavaScript, so a crawler that fetches your HTML and executes nothing never reaches Rybbit at all. Most AI training crawlers work exactly that way, which is why the Bots dashboard carries a note about its own coverage.

If you want to see them, report them from the edge — middleware, a worker, or a reverse proxy — forwarding the real request's user_agent:

{
  "site_id": "1",
  "hostname": "example.com",
  "pathname": "/pricing",
  "user_agent": "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; GPTBot/1.2; +https://openai.com/gptbot"
}

With Block Bot Traffic on, a forwarded crawler user agent is classified and lands in your bot events with full identity, rather than in your analytics as a phantom visitor. With blocking off, it is tracked as a normal visit.

Do not expose API keys in browser JavaScript. API keys are only for server-side requests.

Proxies and CDN Setups

If you proxy Rybbit through Cloudflare Workers, AWS CloudFront, Nginx, Caddy, or another reverse proxy, forward the original visitor IP:

X-Forwarded-For: <visitor-ip>
X-Real-IP: <visitor-ip>

Also preserve the original User-Agent, Referer, and Accept-Language headers where possible.

If the proxy IP is sent instead of the visitor IP, traffic may be geolocated to the proxy location, may inherit the proxy provider's ASN, and many visitors can look like one busy address to the rate layer.

Then turn on First-Party Proxy in Site Settings. It tells Rybbit to read the visitor IP from the forwarded headers (X-Real-IP, then X-Forwarded-For) instead of inferring whether a proxy is in front.

See the proxy troubleshooting guide for examples.

What Bot Detection Does Not Guarantee

Bot detection improves analytics quality, but no bot filter is perfect.

Some sophisticated bots can look like normal browsers. Some legitimate users may browse through unusual network paths or constrained browser environments. Rybbit uses multiple layers to reduce both misses and false positives, but you should still interpret bot counts as an operational signal rather than an exact measurement of all automation on your site.

On this page