matomo-org/device-detector: parsing User Agents and Client Hints in PHP
The Universal Device Detection library will parse any User Agent and detect the browser, operating system, device used (desktop, tablet, mobile, tv, cars, console, etc.), brand and model.
At a glance
- What is it?
- The Universal Device Detection library reads a User Agent string and, optionally, Browser Client Hints, then reports device type, brand, model, client and operating system. It is a PHP package for server-side analytics and bot filtering, not a phone app.
- Who is it for?
- Adopt matomo-org/device-detector if you run PHP on the server and need device, client, OS and bot classification for analytics or request filtering; install it with composer require matomo/device-detector and confirm your YAML parser and cache setup first. Do not adopt it if you need a mobile app that scans a room for hidden cameras or microphones, which is what the search results for this name mostly describe, and the README documents no such capability.
- Can I use it commercially?
- Yes, with conditions. LGPL-3.0 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
- Is it still maintained?
- Yes. The repository last received commits 7 days ago.
- What is it written in?
- Mainly PHP, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 26, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What matomo-org/device-detector actually solves
A raw User Agent string is a dense, unstandardised line of text. The README describes the library as "The Universal Device Detection library that parses User Agents and Browser Client Hints to detect devices (desktop, tablet, mobile, tv, cars, console, etc.), clients (browsers, feed readers, media players, PIMs, ...), operating systems, brands and models." That list is the scope. The output is structured: a device type, a brand name, a model string, a client entry and an OS entry, rather than a substring you have to match yourself.
The audience is server-side PHP developers. Analytics platforms need to segment traffic by device class and browser version. Ad and content servers need to branch on device type. Bot filtering needs a fast yes or no before the rest of the request pipeline runs. The library ships as a Composer package, matomo/device-detector, and the repository layout shows the parsers separated into a Parser directory alongside regexes and YAML data files, so the classification rules live in data rather than in compiled code.
One thing worth stating plainly, because the name invites the confusion: this is not a mobile app and it does not scan for hidden cameras, microphones or listening devices. A large share of the phrases people search alongside this name concern exactly that, and the README documents none of it. If that is what you came for, this repository is the wrong result.
How the parsing pipeline works
You construct a DeviceDetector object with a User Agent string and, optionally, a ClientHints object. Calling parse() runs the parsers. After that, isBot() tells you whether the request came from a bot, spider or crawler, and the accessor methods return the client, OS, device name, brand and model.
The Client Hints path matters because modern browsers reduce the information in the User Agent string deliberately. The README is explicit that hints are optional and that your server must announce support for them with the Accept-CH header to specify the hints it is interested in receiving. Without that header, the browser sends nothing extra, and detection falls back to the User Agent string alone. So the accuracy of the result is partly a property of your HTTP response headers, not just of the library.
Two optional calls change cost and behaviour. discardBotInformation() makes getBot() return only true when a bot is detected, which the README says speeds up detection a bit. skipBotDetection() goes further and skips bot detection entirely, so bots are then detected as regular devices. That second one is a real fork in the road: pick it only if you have no interest in bot traffic at all.
The library also exposes narrower entry points. If you only want to know whether a request is a bot, the README shows using the bot parser directly instead of the full DeviceDetector. That avoids paying for client and OS resolution you will not read.
Installing matomo/device-detector and a first parse
The documented install route is Composer. Adding the package pulls in the library and its autoloader.
composer require matomo/device-detectorAfter that, the README gives a usage example. The minimal version is to require the autoloader, build the detector from a User Agent, call parse(), then read the fields you need. Note the version truncation call: by default only minor versions are returned, in the form X.Y, and the example sets truncation to none so full versions come back.
require_once 'vendor/autoload.php';
use DeviceDetector\DeviceDetector;
use DeviceDetector\Parser\Device\AbstractDeviceParser;
AbstractDeviceParser::setVersionTruncation(AbstractDeviceParser::VERSION_TRUNCATION_NONE);
$userAgent = $_SERVER['HTTP_USER_AGENT'];
$dd = new DeviceDetector($userAgent);
$dd->parse();
$clientInfo = $dd->getClient();
$osInfo = $dd->getOs();
$device = $dd->getDeviceName();
$brand = $dd->getBrandName();
$model = $dd->getModel();To include Client Hints, the README constructs them from the server variables and passes them as the second argument.
use DeviceDetector\ClientHints;
$clientHints = ClientHints::factory($_SERVER);
$dd = new DeviceDetector($userAgent, $clientHints);If you are not using Composer, the repository includes an autoload.php that registers an autoloader for the DeviceDetector namespace. The README warns that a YAML parser is required and that the default Spyc parser is not bundled, so you include it yourself or wire in another parser.
Caching, YAML parsing and the cost you inherit
The default cache is static, which the README describes as working best within one PHP process as a memory array. In a typical request-per-process model that means the classification work repeats on every request. For cross-request caching the library supports several bridges: DoctrineBridge, LaravelCache, PSR6Bridge and PSR16Bridge. The README's own example wraps an APCu adapter in a PSR6Bridge.
This is the main operational decision in the whole package. A framework integration that already has a PSR-6 or PSR-16 cache available should use it, since the default gives you nothing between requests. The bridges are the documented seam for that.
YAML parsing is the second dependency choice. Spyc is the default, and the README notes you can supply a different parser, mentioning a Symfony facade and a Pecl one, with the caveat that you may need to implement the YAML parser facade if you use something other than Spyc or Symfony. That is a small but real integration cost for anyone who has already standardised on a different YAML implementation.
Neither of these is a defect. They are the price of a data-driven detector: the rules live in YAML and regex files, so parsing and caching them efficiently is your responsibility.
Where matomo-org/device-detector is the wrong tool
The clearest limitation is that User Agent parsing is inference from a string the client controls. The library matches patterns; it does not verify anything. A client that sends a fabricated User Agent gets classified according to that fabrication. For analytics segmentation this is usually acceptable noise. For access control or fraud decisions it is not a security boundary, and treating it as one would be a mistake.
Client Hints improve the picture only when the server opts in. If you never send Accept-CH, as the README explains, the hints are simply absent and you are back to the User Agent string. So the accuracy ceiling depends on a header you must configure on the response side.
Version truncation is a quiet trap. The default returns only minor versions in the form X.Y. If your reporting needs full version strings, you must set VERSION_TRUNCATION_NONE as the README example does, and anyone who skips that call will wonder later why patch versions are missing.
Finally, this is a PHP library. If your stack is Node, Python or .NET, the README documents no binding for those runtimes, and the repository is a PHP package with a composer.json at the root. Ports and reimplementations exist in other ecosystems, but they are separate projects with separate rule sets, and nothing in this material describes them.
Alternatives and the difference in approach
The obvious alternative is to write your own regular expressions or substring checks against the User Agent header. The difference is maintenance, not capability. A handful of patterns for the browsers you care about is genuinely cheap, and for a narrow internal tool it may be the right call. What you give up is the continuously updated rule data, the YAML and regex files that the repository carries and that the project's release history shows being revised. You also give up the structured output: device type, brand and model as separate fields rather than a match you interpret yourself.
The other alternative is a hosted detection service. That moves the rule updates off your infrastructure and gives you an API instead of a library, at the cost of sending User Agent data to a third party and depending on a network call in your request path. A local PHP library keeps the parsing in-process, which is why the caching bridges matter so much here.
Within the library itself there is a smaller alternative worth knowing: the bot parser alone, as the README demonstrates, when bot filtering is the only requirement.
Maintenance, licence and upgrade cost
The repository is not archived, and the last push was on 2026-09-23. Releases are tagged and reasonably frequent: 6.5.1 on 2026-05-27, 6.5.0 on 2026-01-21, and 6.4.8 on 2025-11-27. The version numbering suggests a stable major line with minor feature releases and patch fixes, and the README's badges point at CI workflows for PHPUnit, PHPStan, PHPCS, YAML linting and regular expression validation. That last one is telling for a project whose core asset is a large body of regex rules.
Upgrade cost is dominated by the data files, not the API. The public surface shown in the README is small: construct, parse, then read fields, with a handful of optional setters. Code written against that surface should survive minor releases. The risk sits in behaviour changes to classification rules, which can shift your device and bot numbers between versions without any code change on your side. If you report on those numbers, pin the version and review the diff when you bump it.
The licence is LGPL-3.0. That is a copyleft licence with a linking exception designed for libraries, but the terms still impose obligations when you distribute software that includes or links the library, and they interact with how you ship your own code. This is not legal advice; read the LICENSE file in the repository and get your own review if you redistribute.
Editorial conclusion
Adopt matomo-org/device-detector if you run PHP on the server and need device, client, OS and bot classification for analytics or request filtering; install it with composer require matomo/device-detector and confirm your YAML parser and cache setup first. Do not adopt it if you need a mobile app that scans a room for hidden cameras or microphones, which is what the search results for this name mostly describe, and the README documents no such capability. Before rolling it out, verify the version truncation behaviour, because by default only minor versions are returned, and check whether you need a cross-request cache bridge rather than the default in-process static cache.
Frequently asked questions
What is matomo-org/device-detector?
It is a PHP library, published as matomo/device-detector, that parses User Agents and Browser Client Hints to detect device type, brand, model, client and operating system, and to identify bots. It is used server-side, not as a mobile app.
How do I use matomo-org/device-detector in PHP?
Install it with composer require matomo/device-detector, then require the autoloader, create a DeviceDetector with the User Agent string, call parse(), and read the results with getClient(), getOs(), getDeviceName(), getBrandName() and getModel(). Client Hints can be passed as a second constructor argument.
Is matomo-org/device-detector an app for finding hidden cameras or listening devices?
No. The README describes a PHP library that parses User Agent strings and Client Hints to classify devices, clients and operating systems. It documents no hardware scanning, camera detection or listening device detection of any kind.
Does matomo-org/device-detector need Composer?
No, the README gives an alternative: include the autoload.php file shipped in the repository, which registers an autoloader for the DeviceDetector namespace. You still need to supply a YAML parser, since the default Spyc parser is not bundled.
Why does matomo-org/device-detector return only X.Y versions by default?
The README states that by default only minor versions are returned, in the form X.Y. To get full versions you call AbstractDeviceParser::setVersionTruncation(AbstractDeviceParser::VERSION_TRUNCATION_NONE) before parsing.
How can matomo-org/device-detector cache results across requests?
The default static cache works within one PHP process as a memory array. For cross-request caching the README lists several bridges, including DoctrineBridge, LaravelCache, PSR6Bridge and PSR16Bridge, set through setCache().
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/matomo-org-device-detector)