Tracking ISP performance with Playwright and Prometheus
Published at Jan 24, 2026 · 3 min read
We’ve all been there: the internet feels slow, but when you call the ISP, they say “everything looks fine on our end.”
I wanted to monitor my connection speed consistently over time, not just when I felt a lag. My ISP, Unifique, provides a speed test page, but I wanted those numbers in Prometheus.
The Tool
Since the speed test is a web application, I couldn’t just curl an endpoint. I needed something that could interact with the page, click “Start”, and read the results.
Enter Playwright.
Playwright is fantastic for browser automation. I built a simple Node.js application that:
- Launches a headless browser.
- Navigates to the speed test page.
- Clicks the start button.
- Waits for the test to complete.
- Scrapes the Download, Upload, and Ping results.
Architecture
The unifique-speedtest-exporter exposes a metrics endpoint. When scraped, it triggers the Playwright flow.
Note: Because speed tests take time (30s+), you’ll need to increase the scrape timeout in your Prometheus configuration.
Implementation Details
Here is a snippet of the core logic using Playwright:
await page.goto('https://speed.unifique.com.br');
await page.click('#start-button');
await page.waitForSelector('.result-finished');
const download = await page.$eval('.download-speed', el => el.innerText);
const upload = await page.$eval('.upload-speed', el => el.innerText);await page.goto('https://speed.unifique.com.br');
await page.click('#start-button');
await page.waitForSelector('.result-finished');
const download = await page.$eval('.download-speed', el => el.innerText);
const upload = await page.$eval('.upload-speed', el => el.innerText);This isn’t the exact code, but it gives you an idea of how simple the interaction is.
Running it
I packaged this as a Docker container to make it easy to deploy.
docker run -p 3000:3000 ghcr.io/mateuxlucax/unifique-speedtest-exporter:latestdocker run -p 3000:3000 ghcr.io/mateuxlucax/unifique-speedtest-exporter:latestIt exposes metrics on port 3000.
Prometheus Configuration
This is the tricky part. Since the speed test takes a while to complete, you must increase the scrape_timeout.
scrape_configs:
- job_name: 'unifique_speedtest'
scrape_interval: 1h # Don't run this too often!
scrape_timeout: 2m # Give it plenty of time to finish
static_configs:
- targets: ['192.168.1.100:3000']scrape_configs:
- job_name: 'unifique_speedtest'
scrape_interval: 1h # Don't run this too often!
scrape_timeout: 2m # Give it plenty of time to finish
static_configs:
- targets: ['192.168.1.100:3000']Future Plans
Currently, this is a Proof of Concept (PoC) written in Node.js. It works, but running a full headless browser is resource-intensive.
In the future, I plan to:
- Reverse engineer the WebSocket/API calls the speed test page uses.
- Rewrite the exporter in Go or Rust to remove the browser dependency.
- Add more robust error handling for network flakes.
Conclusion
Now I have a graph that shows my internet speed every hour. If I ever need to call support, I have the data to back up my claims!
Check out the repository: MateuxLucax/unifique-speedtest-exporter