Did you realize that you can monitor a Starlink dish using just Zabbix? The idea (or rather the need) to use Starlink came to me almost as soon as I moved to a fairly rural area. Local internet providers have not yet “provided” fiberoptic or stable mobile connectivity to places like this, and while searching for a solution I accidentally discovered that Starlink was already providing service to some local companies. As I later found out, they also offered service in my area for residential customers.
To make a long story short, since internet access is crucial in the IT field, I decided to acquire and then monitor my very own Starlink dish. At first, this proved challenging because regular user data access is quite limited. However, thanks to Zabbix browser monitoring, I managed to solve it fairly easily. In this post I will share my solution with you, including the template.
Table of Contents
Monitoring configuration
First, you need to make sure you have Zabbix installed (either a Zabbix proxy or server) on the same network that the Starlink dish and router are on. The next step is to configure Zabbix for browser monitoring.
WebDriver installation
# podman run --name webdriver -d \ -p 4444:4444 \ -p 7900:7900 \ --shm-size="2g" \ --restart=always -d docker.io/selenium/standalone-chrome:latest
Port 4444 will be the port on which the WebDriver will be listening, and port 7900 will be used by NoVNC, which allows us to observe browser behavior in case a browser with a GUI is used.
Zabbix server/proxy configuration
After WebDriver is installed, we need to set up the communication between Zabbix and the driver. This can be done by editing the Zabbix server/proxy configuration file and updating the following parameters:
### Option: WebDriverURL # WebDriver interface HTTP[S] URL. For example http://localhost:4444 used with # Selenium WebDriver standalone server. # # WebDriverURL= WebDriverURL=http://localhost:4444 ### Option: StartBrowserPollers # Number of pre-forked instances of browser item pollers. # # Range: 0-1000 # StartBrowserPollers=1 StartBrowserPollers=5
With the configuration parameters in place, restart the Zabbix server/proxy to apply the changes:
systemctl restart zabbix-server
Creating a host
First, we need to navigate to the “Data collection” > “Hosts” section and create a host that represents our Starlink dish. The host in my example will look like this:

The host also has a user macro:
{$LINK} with value: http://webapp.starlink.com to point to the correct Starlink dish web app:

Creating a browser item
We will now configure our browser item to collect and monitor the list of metrics exposed in the Starlink browser app:

We are using the bare minimum here, so make sure the update intervals are as frequent as you need. However, I would not recommend updating it more frequently than every 5 minutes. It’s also not a good idea to store the history, since it is already stored trough dependent items.
The most important part of the item is the script itself:
var browser, result;
var opts = Browser.chromeOptions();
opts.capabilities.alwaysMatch['goog:chromeOptions'].args = [];
browser = new Browser(opts);
browser.setScreenSize(Number(1980), Number(1020));
try {
var params = JSON.parse(value);
browser.navigate(params.url);
// Wait for the dish to report status
Zabbix.sleep(2000);
// Find the JSON text element(s)
var jsonElements = browser.findElements("xpath", "//div[@id='root']/div[@class='App']/div[@class='Main']/div[2]/div[@class='Section'][2]/pre[@class='Json-Format']/div[@class='Json-Text']");
var extractedData = [];
for (var i = 0; i < jsonElements.length; i++) {
var text = jsonElements[i].getText();
// Try parsing JSON
try {
extractedData.push(JSON.parse(text));
} catch (e) {
// If not valid JSON, include raw text instead
extractedData.push({ raw: text, error: "Invalid JSON format" });
}
}
// Collect result
result = browser.getResult();
// Replace with parsed JSON data
result.extractedJsonData = extractedData.length === 1 ? extractedData[0] : extractedData;
}
catch (err) {
if (!(err instanceof BrowserError)) {
browser.setError(err.message);
}
result = browser.getResult();
}
finally {
// Return a clean JSON object
return JSON.stringify(result.extractedJsonData);
}
So what does this script do? It opens the Starlink web app, waits for the Starlink dish to output all the status data, and, after a bit of parsing, returns the data highlighted in the screenshot:

Now we can click on the three dots on the left of our newly created item in the items page and proceed to create dependent items for each value we are interested in!
Creating dependent items
Now we just click here:
As an example, to create an item that monitors the hardware version we can create an item like this:

With JSONPath preprocessing:

In the end we get the data in Zabbix:

All other items (except alerts) will follow the same logic – just update the item name, key, and JSONPath in preprocessing to extract the required values.
Creating dependent LLD item prototypes
To automate the alerts items creation, we can create a dependent discovery rule. In the “Discovery” section, create a new discovery rule:

With preprocessing using Java Script:
var data = JSON.parse(value);
var alerts = data.alerts;
var lld = [];
for (var key in alerts) {
if (alerts.hasOwnProperty(key)) {
lld.push({
"{#ALERT}": key
});
}
}
return JSON.stringify({ data: lld });
This will provide us with following JSON data:
{
"data": [
{
"{#ALERT}": "dishIsHeating"
},
{
"{#ALERT}": "dishThermalThrottle"
},
{
"{#ALERT}": "dishThermalShutdown"
},
{
"{#ALERT}": "powerSupplyThermalThrottle"
},
{
"{#ALERT}": "motorsStuck"
},
{
"{#ALERT}": "mastNotNearVertical"
},
{
"{#ALERT}": "slowEthernetSpeeds"
},
{
"{#ALERT}": "softwareInstallPending"
},
{
"{#ALERT}": "movingTooFastForPolicy"
},
{
"{#ALERT}": "obstructed"
}
]
}
All that’s left ‘to do is to create a dependent item prototype:

With preprocessing, of course:
JSONPath will transform to extract each specific alert and “Boolean to Decimal” will save us some space in the database by tranforming true/false booleans to digits.
Result
In the end, we can monitor all the data:

Even more data can be collected using exporters – if you are willing to do a bit of extra configuration, of course! Let me know if you are interested, and I will show you a completely different approach with a template.
Before I forget, the template used in this tutorial can be found here.


Hello,
I’m trying to follow the same steps as you, but I’m not having any success, as shown in the error below.
I’ve already tested the connection to Podman port 4444 and everything is working, but I’m simply getting the error: Cannot execute script: undefined return value
I have updated the template a bit, please use the newer version on the same link.
But first thing I would check, make sure the user macro {$LINK} is configured with value http://webapp.starlink.com
Hello, thank you very much for your support.
It is currently working, but there are a few things I would like to clarify.
Regarding disk monitoring, given that the address for monitoring ishttp://webapp.starlink.com/, is it possible to add more than one Starlink to be monitored in Zabbix?
Another question is about how monitoring is done. Is it possible to monitor without being directly connected to the Starlink router?
This is because there are infrastructures where Starlink is used as an ISP router and then there are more network devices that take on the role of DHCP.
I would appreciate your clarification.
You most certainly can monitor more than one Starlink, but with approach described in the post, you need to put a Zabbix proxy in each Starlink provided network, create a host monitored by that proxy and link the template. But as far as I know, Starlink provides API access to business clients, which might produce more data in an easier to monitor way, alas I don’t have to API, so cannot say for sure.
But even using these proxies, if they are not on the same network as the server, it won’t be possible.
For example, in a situation where I have a VPN connection between three sites and each of them has Starlink.
Here, I don’t see how it would be possible to monitor the Starlink antennas because the VPN is made at the router after the Starlink ISP.
Thus, the proxies will remain outside the network since they need to be directly connected to the antenna’s network, and the server will also not have visibility of the other proxies except for the proxy that is on the same site as it.
And regarding Starlink Business, do you have any information about that API? I don’t find very relevant content.
Hello,
I tried to follow your guide but you didn’t show the configuration for ‘alert status’ in value mapping. How should it be configured?
If I run a test, I get all the values but they are not handled correctly.
I’ve updated the template to include the alert value mapping, plus some trigger prototypes. Try the new version and let me know if that is what you were looking for!
Thank you for updating the template; it works now, but the step-by-step guide above is not updated. Good evening.
The guide mainly covers how to get the Starlink dish data, rather than create a template. But I will keep a note on that for the future posts!