One line in an access log rarely tells you much. A request for /pricing at 3:14 a.m. from an address with no referer and a string that looks like a browser could be a search engine, a scraper, a monitoring probe, or somebody's forgotten cron job. The pattern around that line is what identifies the caller. Years of tooling taught us to read logs for search engine crawlers; the traffic arriving now follows different rules, and the old filters will mislabel a good chunk of it.
Legacy bots arrived with a contract, more or less: announce who you are, fetch robots.txt first, respect Disallow and Crawl-delay, spread requests so you don't knock a small server over, and let the site owner verify your identity through reverse DNS. Search engine crawlers still largely behave this way, because their value depends on not getting blocked.
The crawlers now collecting pages for answer engines and model training inherited some of those manners and dropped others. Some check robots.txt; some read it and ignore the parts they dislike; a few never request it at all. Many identify themselves honestly in the User-Agent string and publish their IP ranges. Others arrive wearing a Chrome user agent. That inconsistency is the defining trait: identity and behaviour no longer line up the way they used to.
Names worth knowing in the User-Agent field: GPTBot, OAI-SearchBot, ChatGPT-User, ClaudeBot, Claude-User, PerplexityBot, Google-Extended, Applebot-Extended, meta-externalagent, Bytespider, CCBot, Amazonbot. On the traditional side you already have Googlebot, bingbot, DuckDuckBot, YandexBot, plus the SEO tools — AhrefsBot, SemrushBot, MJ12bot, DotBot.
Treat the string as a claim, not a fact. For Googlebot and bingbot, the standard test is reverse DNS followed by forward DNS confirmation: the PTR record should resolve to a hostname in the operator's domain, and that hostname should resolve back to the same IP. For newer crawlers, the reliable method is the operator's published IP list, which several vendors now serve as a plain-text or JSON file you can pull into a firewall rule or log filter. If an address claims to be a named crawler but sits outside the published ranges, you have found something worth blocking.
Headers often expose a crawler that is pretending to be a browser. A real Chrome request over HTTPS typically carries Accept, Accept-Language, Accept-Encoding with br and zstd, a set of Sec-Fetch-* fields, and cookies on repeat visits. A bare HTTP client sends a thin set instead: often just Accept and Accept-Encoding, sometimes no Accept-Language, no Sec-Fetch headers, no cookies, and a Referer that is missing or points to a URL that does not exist on your site.
Other clues: HTTP/1.1 where your real users negotiate HTTP/2 or HTTP/3; a header order that does not match the browser named in the string; a TLS fingerprint inconsistent with the claimed client. None of these is a conviction on its own. Three together usually are.
Headers can be copied. Request patterns are harder to fake, particularly at scale. Compare the profiles you will actually see:
The tell that matters most is what the crawler asks for compared with what a visitor needs. A client that fetches every article but never an image, stylesheet, or script is not a person.
Uptime checkers, link previewers, accessibility scanners, search-console verification fetches, and your CDN's own health probes all look faintly robotic. Block on user agent alone and you will eventually break something you rely on, which is why the order above matters: verify the IP, check the behaviour, then act.
One more complication. Some collectors deliberately fetch only a handful of pages per domain and spread those requests across many addresses over months. Those are nearly invisible in a single day's log and show up only in monthly aggregates. If you are deciding what to allow, review a full month rather than a busy afternoon.
Once you know which names and ranges you care about, keep a small, boring routine going:
Do that and the next 3 a.m. request for /pricing will take you two minutes to explain.
Photo: Laura Musikanski / Pexels