phantomas: a modular headless Chromium metrics collector driven by an event bus
Headless Chromium-based web performance metrics collector and monitoring tool
At a glance
- What is it?
- phantomas runs a page inside headless Chromium and emits performance metrics from independent modules that subscribe to browser events. It is a diagnostics instrument for engineers who need per-page detail, not a synthetic field-data platform.
- Who is it for?
- Adopt phantomas if you need scriptable, per-page diagnostics that go beyond Core Web Vitals, especially DOM query counts, jQuery event bindings, and CSS complexity via analyze-css. Skip it if you need field data from real users or a single opinionated score with an audit trail.
- Can I use it commercially?
- Yes. BSD-2-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The gap phantomas fills between a Lighthouse score and a profiling session
Most performance tooling collapses a page load into a number. phantomas takes the opposite route. The README describes it as a modular web performance metrics collector built on headless Chromium, and the feature list makes the intent explicit: each metric is produced by a separate module, and the core is an events emitter that modules hook into. That design answers a narrow question well. If you want to know how many DOM queries a page issues, how many events are bound via jQuery, or how complex and duplicated its CSS selectors are, phantomas is built to report exactly that. The audience is engineers who already understand what they are measuring and want the raw counts, plus the ability to add their own module when an existing one does not cover a case. It is not aimed at someone who wants a letter grade. The output format is JSON, which tells you where the project expects the data to go: into a dashboard, a diff, or a build gate that you write yourself.
How the module and event architecture actually moves data
The core is an event emitter, and modules are subscribers. The README's usage example shows the shape of that contract from the outside: you call phantomas with a URL and receive a promise, then read results through methods such as getMetrics() and getAllOffenders(). The same promise object is an emitter, so you can attach listeners for events like recv, which carries a response object with method, url and contentType, and for module-specific events such as domQuery, which fires with a type and a query string. That is the whole data flow in one picture: the browser produces observations, the core rebroadcasts them, modules accumulate counts, and the caller reads the aggregate. Two details in the README are easy to miss and matter in practice. Metrics can be emitted from the JavaScript of the page under test through helper functions exposed on window.__phantomas, which means a site can instrument itself for a phantomas run. And device profiles change the user agent and viewport together, so mobile and tablet emulation is a configuration choice rather than a separate binary. The events documentation lives in docs/events.md and the full metric list in docs/metrics.md, both of which the README points to rather than duplicating.
Installing it and running a first collection
The requirement is NodeJS 16 or newer. Installation is a single npm command, and the README notes that this pulls in a recent version of Chromium supported by the puppeteer module, so the browser is not something you install separately. Docker is offered as an alternative through macbre/phantomas:latest on Docker Hub or ghcr.io/macbre/phantomas:latest from GitHub's container registry. From a Node project the entry point is a CommonJS require of phantomas followed by a call with a URL, which returns the promise described above; the README also points at ./examples/index.js as a runnable sample. As a command line tool the same package is invoked as phantomas, and the README directs you to run phantomas -h for the flags rather than listing them. For development against the devel branch you clone the repository and run npm install. Testing has a prerequisite that is easy to trip over: a local nginx container must be started with ./test/server-start.sh before npm t, because the integration suite serves static assets from it. Pull requests are tested through GitHub Actions. None of these commands were run for this article; they are taken from the README as written.
Where phantomas stops being the right instrument
The most consequential limitation is structural. phantomas drives a page in headless Chromium and reports what that run observed. Nothing in the supplied material describes a field-data pipeline, a real-user monitoring integration, or a way to aggregate measurements across actual visitors. If your question is what your users experience on mid-range Android devices over congested networks, a lab run answers a different question, and you should not treat its numbers as a substitute. There is a second, quieter cost: modularity means the metric surface is wide. The README describes in-depth metrics and links to docs/metrics.md for the full list, which is a signal that picking the metrics worth gating on is your job, not the tool's. A third constraint is environmental. Because Chromium ships alongside the package through puppeteer, the browser version tracks the installed phantomas version. The release names make this visible: v2.25.0 is labelled HeadlessChrome/149, v2.24.0 HeadlessChrome/146, and v2.23.0 HeadlessChrome/145. Upgrading phantomas can therefore change the engine underneath your measurements, which is a problem if you compare runs across a version bump without pinning. Finally, the README routes troubleshooting to a separate Troubleshooting.md, which suggests headless browser setup failures are common enough to warrant their own document.
phantomas and Lighthouse differ in what they hand back
Lighthouse is the obvious comparison, and the difference is not which one is faster. Lighthouse is an auditing tool: it runs a page and returns an opinionated report with scores and a set of predefined audits. phantomas is a metrics collector: it returns JSON metrics and offenders, and it lets you subscribe to the raw event stream while the page loads. If you want a score you can paste into a pull request, Lighthouse already made the judgement calls for you. If you want the count of DOM queries by selector type, or the number of jQuery-bound events, or duplicated CSS selectors via analyze-css, phantomas reports those as data and leaves the interpretation to you. The extension model differs in the same direction. Adding a check to Lighthouse means writing an audit within its plugin structure; adding one to phantomas means writing a module that hooks the core emitter, which the README presents as the central design idea. The trade-off is real in both directions: phantomas gives you more control and more assembly work, Lighthouse gives you less control and a finished opinion.
Maintenance, versioning and what the BSD-2-Clause licence leaves open
The licence is BSD-2-Clause, a permissive licence that in outline allows use, modification and redistribution provided the copyright notice and licence text are retained. That is the general shape of the licence, not legal advice; read the LICENSE file in the repository and involve counsel if you are redistributing the package inside a product. Two maintenance facts are visible from the repository metadata. The default branch is devel, not main or master, so the README's development instructions point at a branch that is ahead of what npm installs. And the project is not archived, with a last push timestamp of 2026-08-31 and releases at a fairly regular cadence through 2026. The upgrade cost is where the licence question becomes a practical one. Since each release is labelled with the Chromium version it bundles, a phantomas upgrade is also a browser upgrade. Teams that gate builds on metric thresholds should pin a version and re-baseline deliberately when they move, rather than letting a dependency bump silently change the engine. The README also links to xs:code for commercial support, which is worth knowing if you plan to depend on this in a production pipeline rather than as a local diagnostic.
Who should pick this up, and what to check before committing
phantomas fits teams that already have a performance question specific enough to name. If you have ever wanted to know how many DOM queries a page issues before its first paint, or how much of its CSS is duplicated, this tool was written for that. It also fits anyone building an internal dashboard, since JSON output and a CommonJS API make ingestion straightforward and the module system means you can add metrics your organisation cares about without forking the core. It fits less well as a first performance tool. If you have no baseline and no opinion about which metrics matter, the breadth described in docs/metrics.md will slow you down before it helps you. Before adopting, check four things. Confirm Node 16 or newer is available in your CI image and that the puppeteer-bundled Chromium launches there, since headless browser setup is the failure mode the project documents separately. Decide whether you need Docker or npm, because the two paths install the browser differently. Confirm your target metrics are listed in docs/metrics.md for the exact version you intend to pin. And decide up front which device profile you will run, because the user agent and viewport are set together and changing them changes what you are measuring.
Editorial conclusion
Adopt phantomas if you need scriptable, per-page diagnostics that go beyond Core Web Vitals, especially DOM query counts, jQuery event bindings, and CSS complexity via analyze-css. Skip it if you need field data from real users or a single opinionated score with an audit trail. Verify first that the Node 16+ and bundled Chromium pairing works in your CI image, that your chosen device profile matches the viewport you care about, and that the metrics you plan to gate on appear in docs/metrics.md for the release you pin.
Community notes