Repository navigation
feat(devices): name the crawlers production reads generically - #1
Merged
Merged
Conversation
A dump of redirection.io's traffic of 2026-09-21 holds 150 user agents production answers with `Generic Bot`, or with the string itself. Thirty-nine of them name something whose operator documents it: Kubernetes and Azure Front Door health probes, Prometheus, Gatus, Telegraf, Zabbix, updown.io, Yaut and LogicMonitor monitors, the platform agents of CloudFront, SNS, Cloud Tasks, cert-manager, Sentry's symbolicator and redirection.io's own agent, and the crawlers of Shenma, Keenable, Linkup, Azure AI, Reflection, QuillBot, Semji, Echobox, DoubleVerify, billiger.de, idealo, Amazon, SE Ranking, Squiz, the INA, ClimaTax, Intrinsec and Hadrian. Each entry is anchored on the token its operator publishes, and carries the page that publishes it. The rest of the dump is left generic: a scraper someone wrote for themselves, or a research bot with no page behind it, is a guess, and a bot regex written on a guess reads people as crawlers on every site served. Two entries sit under rules matomo already holds. `ias-va` takes priority -1 so matomo's `/3.1` reading of the same fetcher still answers for the version it names, and `k6-performance-test` reuses matomo's own name rather than contradicting the `k6/<version>` rule beside it. YisouSpider is the one entry in the Search bot category, which moves the row out of the log injector's tool column, so `tests/pinned/traffic/false-negatives.yml` says why production's answer stands.
… nothing Eleven more strings from the traffic of 2026-09-21, none of which the corpus holds: Maxeda's Praxis application, the four online pharmacies of the apo.com Group that share one iOS application and name it after the domain they sell under, Go City on both its platforms, Smart Launcher under its Android package name, and four libraries -- Symfony's BrowserKit, python-zeep, MWFeedParser and npm's rss-parser -- each of which sends its own name and nothing else. The client and only the client. Nothing in `GoCityAndroid/10.2.0` or in `ginlemon.flowerfree/6.6` names a system, so those two keep the type production gave them: the client axis is where a hand-written client entry goes, and it has no business inventing one.
joelwurtz
force-pushed
the
feat/traffic-2026-09-21
branch
from
September 21, 2026 10:27
4c9a615 to
212c3d3
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
User agents the detector read only as
Generic Bot, or not at all, each looked up on the web one at a time. An entry was written where an operator or a project says what the thing is. The last section says why the rest stays generic.Bots (
src/devices/bots.yml)Health probes and monitors
kube-probe/1.34,/1.35,/1.35+,/1.36kube-probe/<its own version>)Edge Health Probezabbix,ZabbixBlackbox-Exporter/0.28.0Blackbox-Exporter/<version>since the RFC 9110 changeTelegraf/1.39.3 Go/1.26.5http_responseinputLogicMonitor SiteMonitor/1.0,LogicMonitor InternalServiceGatus/1.0GatusUserAgent = "Gatus/1.0"inconfig/endpoint/endpoint.goyaut monitoring,YAUT monitoring,Mozilla/5.0 (compatible; Yaut/1.0; …)updown.io daemon 2.11Agents a platform sends on its own behalf
redirection-io-agent-proxy/agent-proxy-v3,redirection-io-agent/2.2.6…3.3.0amazon cloudfront,Amazon CloudFrontAmazon CloudFrontunless the real UA is forwarded)symbolicator/26.8.0,/26.9.0Google-Cloud-TasksUser-Agentheader is set toGoogle-Cloud-Tasks")Mozilla/5.0 (compatible; Cloudinary/1.0)WinHttp-Autoproxy-Service/5.1GET /wpad.datof the WPAD serviceias-va/3.3 (former https://www.admantx.com + …)/3.1string, so this entry sits at priority -1 under itAmazon Simple Notification Service Agentcert-manager-challenges/v1.21.2 (linux/amd64) cert-manager/…linux/amd64had it counted as a person at a keyboardSearch, and the crawlers that feed an answer rather than an index
Mozilla/5.0 … Reflectionbot/1.0; +https://reflection.ai/bot …YisouSpiderMozilla/5.0 … KeenableBot/1.0; +https://keenable.ai/LinkupBot/1.0 (LinkupBot for web indexing; https://linkup.so/bot; …)Mozilla/5.0 … AzureAI-SearchBot/1.0;url(Rankly, botcrawl)quillbot.comquillbot-comin ai.robots.txt, and the entry reads both spellingsYisouSpideris the only entry in theSearch botcategory.The rest of the crawlers
mozilla/5.0 - research.hadrian.ioMozilla/5.0 (compatible; EchoboxBot/1.0; hash/…; +http://www.echobox.com)Mozilla/5.0 (compatible; INA dlweb; +https://www.ina.fr/collecte-du-depot-legal-web)Mozilla/5.0 (compatible; CorporateResearch/1.0; …; +https://climatax.org/…)CorporateResearchalone would read half the research crawlers there are, so the entry asks for the address toobilligerbot/1.0 (https://www.solutions.billiger.de/de/bot)Mozilla/5.0 … AmazonProductDiscovery/1.0; https://vendorcentral.amazon.com/…Mozilla/5.0 (Windows NT 6.3;compatible; Leikibot/1.0; +http://www.leiki.com)SEBot-WAMozilla/5.0 (compatible; Funnelback)Mozilla/5.0 … SemjiBot/1.0; +http://semji.com …Mozilla/5.0 (compatible; idealo-bot inventory-image-downloader; …)tphotobot/0.1 (+https://crawler.estidraft.com/bot)intrinsec easm vulnerability scannerLoad generators
k6-performance-testk6/<version>; this string has no slash, so the entry only adds the shape and reuses matomo's name rather than contradicting the rule beside itoha/1.8.0Clients (
src/devices/clients.yml)GoCityAndroid/10.2.0,/10.4.1,GoCity/39and/48withCFNetworkMAXEDA/PraxisApp;apodiscounter …,apotheke.at …,apo.com … IOS Version …ginlemon.flowerfree/6.6 build 020/trueand/falseginlemon.flowerfreeis Smart Launcher's Android packageSymfony BrowserKitAbstractBrowserZeep/4.3.3 (www.python-zeep.org)MWFeedParser[req setValue:@"MWFeedParser" forHTTPHeaderField:@"User-Agent"]rss-parserDEFAULT_HEADERS = { 'User-Agent': 'rss-parser', … }The client and only the client. Nothing in
GoCityAndroid/10.2.0or in an Android package namesays which system it runs on, and the client axis, where a hand-written client entry goes, has
no business inventing one.
What was left alone, and why
A few were already named here; the detector they were compared against is older.
The rest name nothing a search can place, and
Generic Botor no answer at all is the honestreading. A bot regex written on a guess turns readers into crawlers on every site it serves:
AionBot/1.0(Udger lists it with an unknown author andno URL),
[SEOBot](seobotai's own crawlerdocuments a
different string),
SSI-Nutch/1.23,PatteBlancheBot/0.1,ExitChecker/1.0.0,netcheck-probe,WPImageProxy,KELKOO resizer, and the plainVarnish, which is not theVarnish Health Probethe documentation writes.Mozilla/5.0strings,node,app-iphone,webview-androidand the like. The Apple networking processes already read as Safari, which iswhat matomo answers.
tests/pinned/production.rspins both halves: one case per entry written, and a guard that themost common of the unnamed still read as
Generic Bot, so an over-wide entry addedlater cannot quietly swallow them.
Tests
The corpus does not move;
tests/pinned/traffic.rsstays green. Every new case intests/pinned/production.rswas checked to fail against the database as it was.Two entries had to be placed under rules matomo already holds, which the corpus caught:
ias-vaat priority -1, below matomo's reading of the/3.1string, andk6-performance-testas its own shape rather than a wider
k6rule that would have renamed matomo's.