feat(user-agent): expand OS, browser, device, and bot detection#77
Merged
lohanidamodar merged 4 commits intoJul 20, 2026
Merged
Conversation
Broaden detection coverage using Matomo DeviceDetector 6.4 as the reference so that popular user agents resolve to a real result instead of null or unknown, while keeping the fast token-and-bounded-regex hot path (no data files, no runtime dependencies). - Operating systems: iPadOS, tvOS, watchOS, HarmonyOS, OpenHarmony, Fire OS, webOS, Sailfish, BlackBerry, PlayStation, Nintendo, and popular Linux distributions (Debian, Fedora, Arch Linux, Mint, and more). - Browsers: Opera Mobile, Brave, Vivaldi, Yandex, UC Browser, DuckDuckGo, QQ Browser, Coc Coc, Whale, Huawei Browser, Amazon Silk, and Firefox Focus, all resolved ahead of the generic Chrome and WebView rules. - Libraries: Python urllib, aiohttp, Go-http-client, Node Fetch, Axios, HTTPie, Apache HTTP Client, Java, and more. - Device brands: Realme, Asus, Tecno, Infinix, HTC, Lenovo, ZTE, TCL, Meizu, Nothing, Fairphone, Alcatel, plus LG/Sony smart-TV mapping. - Bots: PerplexityBot, Google Extended, GoogleOther, Meta External Agent, CCBot, YouBot, Yahoo Slurp, SeznamBot, Pinterest, and more, with narrowed needles so the Sogou browser and Pinterest app are not misclassified as bots. Short-name codes stay aligned with Matomo so the added categories match its reference output. Differential tests against Matomo 6.4 gain iPad, Debian, and Yandex profiles; unit tests cover the new browsers, libraries, platforms, device brands, and crawlers. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BnwCG9DYF9KQwBtRbQHZNv
lohanidamodar
requested review from
Meldiron,
abnegate,
eldadfux and
loks0n
as code owners
July 19, 2026 00:45
Benchmark resultsuser-agent
Shared CI runners — treat absolute numbers as rough, compare modes within a run. Commit e6b95f4. |
Contributor
Greptile SummaryThis PR expands the user-agent package detection rules. The main changes are:
Confidence Score: 5/5This looks safe to merge.
Important Files Changed
Reviews (4): Last reviewed commit: "fix(user-agent): tighten Honor brand rul..." | Re-trigger Greptile |
- OperatingSystemDetector: satisfy PHPStan (drop always-true empty-string check in webOS version parsing) and Rector (use instanceof over !== null for the Apple and Linux-distro results). - ClientDetector: report the correct engine for Chromium derivatives that ship no Chrome token — legacy Amazon Silk now resolves to WebKit at its AppleWebKit version instead of Blink at the Silk version, matching Matomo. - BotDetector: stop treating WhatsApp as a bot. Matomo classifies the WhatsApp token as a mobile app, so real in-app browser sessions must not report isBot(). - DeviceDetector: drop the Nothing brand rule; the bare "Nothing" needle matched unrelated build and app tokens and mislabeled the brand. - Vale: add Wget, aiohttp, Axios, HTTPie, and GPTBot to the shared vocabulary so the README spell-check passes. - Tests: lock in legacy Silk WebKit engine reporting and WhatsApp staying non-bot. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BnwCG9DYF9KQwBtRbQHZNv
The README spell-check runs over the whole file, so every product and brand name in the expanded detection-coverage section needs a vocabulary entry. Add the OS, browser, and library names introduced by this PR (macOS, iOS, iPadOS, HarmonyOS, webOS, Vivaldi, Yandex, DuckDuckGo, Huawei, OkHttp, and more). Verified with Vale 3.15.1 that the package README reports zero spelling errors. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BnwCG9DYF9KQwBtRbQHZNv
The bare `Honor` alternative matched the common word "honor" anywhere in the user-agent string, so an app or build token such as `Build/InHonorOfRelease` could mislabel a non-Honor device. Match only the uppercase `HONOR` brand token or `Honor <model>` (numbers, X/V series, and named product lines), alongside the existing HLK-/BKL- model codes. Real Honor devices — including uppercase `HONOR WKG-LX9` — still resolve to Honor, while "honor" in surrounding text no longer sets the brand. Adds regression tests for named and uppercase Honor models and a negative case where "InHonorOfRelease" must not override the real Samsung brand. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BnwCG9DYF9KQwBtRbQHZNv
loks0n
approved these changes
Jul 20, 2026
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.
Summary
The
user-agentpackage shipped a deliberately small rule set, so many popular user agents resolved tonull/unknown. This PR broadens coverage across all four categories using Matomo DeviceDetector 6.4 as the reference, while keeping the existing fast parsing approach — direct token checks plus a small set of bounded regular expressions, with no data files and no runtime dependencies.Short-name codes stay aligned with Matomo (
IPA,OHS,BR,YA,UC,FIR, …) so the added categories match its reference output. Model marketing names still come back as the raw model token by design — mapping those requires Matomo's LGPL data, which this library intentionally does not ship.What's added
Operating systems — iPadOS, tvOS, watchOS, HarmonyOS, OpenHarmony, Fire OS, webOS, Sailfish, BlackBerry, PlayStation, Nintendo, and popular Linux distributions (Debian, Fedora, Arch Linux, Mint, Kali, Raspbian, and more). iPad now resolves to iPadOS instead of iOS, matching Matomo.
Browsers — Opera Mobile, Brave, Vivaldi, Yandex Browser, UC Browser, DuckDuckGo, QQ Browser, Coc Coc, Whale, Huawei Browser, Amazon Silk, and Firefox Focus. These resolve ahead of the generic Chrome and Android WebView rules, since their user-agent strings also carry a
Chrome/token (and sometimes theVersion/4.0WebView marker). The engine is derived from the actual tokens: Blink at the embedded Chrome version, or WebKit at theAppleWebKitversion for legacy Amazon Silk builds that carry no Chrome token.HTTP libraries — Python urllib, aiohttp, Go-http-client, Node Fetch, Axios, HTTPie, Apache HTTP Client, Java, and more.
Device brands — Realme, Asus, Tecno, Infinix, HTC, Lenovo, ZTE, TCL, Meizu, Fairphone, Alcatel, plus LG/Sony smart-TV brand mapping.
Crawlers — PerplexityBot, Google Extended, GoogleOther, Meta External Agent, CCBot, YouBot, Yahoo Slurp, SeznamBot, Pinterest, and more. Needles are narrowed so human traffic — the Sogou browser, the Pinterest app, and the WhatsApp in-app browser — is not misclassified as a bot (Matomo treats the WhatsApp token as a mobile app, not a crawler).
Safety / no regressions
Linux/X11, so tokens likeArchinsideSearchdo not false-positive.Review feedback (Greptile)
isBot() === false.Silk/3.13, no Chrome token) now reports WebKit533.16instead of Blink3.13, matching Matomo.Nothingneedle matched unrelated build/app tokens, and real devices report opaque model codes with no brand string.Testing
bin/monorepo test user-agent— 94 tests, 393 assertions, all passing. CI green across validate (Vale), test (PHPStan level 5, Rector, PHPUnit), and benchmark.MatomoCompatibilityTestgains iPad, Debian, and Yandex profiles (verified field-for-field against Matomo 6.4).🤖 Generated with Claude Code
https://claude.ai/code/session_01BnwCG9DYF9KQwBtRbQHZNv