How to Monitor Uptime Without Paying for Expensive Tools

How to Monitor Uptime Without Paying for Expensive Tools

You can monitor website uptime without paying for expensive tools because the core of uptime checking is just a scheduled HTTP request and a comparison of the response. The expensive tools add dashboards, alerting channels, and historical graphs, but the underlying mechanism is something you can run on a cron job or a simple script on any machine you already control.

This article shows you how to monitor website uptime using free, standard Unix utilities and a few lines of configuration. You will learn how to check HTTP status codes, measure response times, and set up a basic alerting loop, all without leaving your terminal or spending a cent on a monitoring service.

How to monitor website uptime with curl and a cron job

The simplest approach is to use curl in a cron job. curl is installed on virtually every Linux and macOS system, and it can give you the HTTP status code, the total time for the request, and the size of the response. The key is to parse the output correctly and act on it.

Here is a shell script that checks a URL and logs the result. Save it as check_uptime.sh and make it executable with chmod +x check_uptime.sh.

#!/bin/bash
URL="https://example.com"
LOG="/var/log/uptime.log"
TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")

HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" --max-time 10 "$URL")
TIME_TOTAL=$(curl -s -o /dev/null -w "%{time_total}" --max-time 10 "$URL")

echo "$TIMESTAMP code=$HTTP_CODE time=${TIME_TOTAL}s" >> "$LOG"

if [ "$HTTP_CODE" -ne 200 ]; then
    echo "$TIMESTAMP ALERT: $URL returned $HTTP_CODE" >> "$LOG"
    # Add your notification command here, e.g. mail, curl to a webhook
fi

The -w flag in curl writes the specified format string to stdout. Here you extract %{http_code} and %{time_total}. The -o /dev/null discards the body, which keeps the script fast and quiet. The --max-time 10 prevents the script from hanging if the server stops responding. A non-200 status code triggers the alert block, where you can insert a mail command or a call to a messaging webhook.

Add this to your crontab with crontab -e. A common schedule is every minute for critical sites, but every five minutes is usually enough for most small businesses. The line looks like this:

*/5 * * * * /home/you/bin/check_uptime.sh

This gives you a log file you can tail, grep, or feed into a simple graphing tool. It does not give you a pretty dashboard, but it gives you the raw data you need to verify your host's uptime claim.

How to monitor website uptime with a TCP check for deeper insight

An HTTP status code tells you the web server responded, but it does not tell you whether the connection itself is healthy. A TCP check on port 443 (or 80) can catch network-level failures that an HTTP check might mask, especially if the server is behind a load balancer that returns a generic error page.

Use nc (netcat) or timeout with bash's /dev/tcp pseudo-device. The latter is pure bash and has no external dependency. Here is a one-liner that tests whether a port is open:

timeout 5 bash -c 'echo > /dev/tcp/example.com/443' && echo "port open" || echo "port closed"

This attempts to open a TCP connection to example.com on port 443. If the connection succeeds, the echo writes a newline and the shell reports success. If it fails or times out, the || branch runs. You can combine this with the HTTP check in the same script to distinguish between "server is down" and "network path is broken".

For a more detailed view, you can use openssl s_client to inspect the TLS handshake. This is useful when you suspect the certificate has expired or the server is presenting the wrong certificate. The command below connects, prints the certificate subject and issuer, and exits.

echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -subject -issuer -dates

The -servername flag is essential for virtual hosts, because it sends the SNI extension that tells the server which certificate to present. The output shows the certificate's validity period, which you can compare against the current date. A certificate that expires in a week is a ticking time bomb for uptime, because browsers will refuse to connect.

How to monitor website uptime with a headless browser for JavaScript-heavy sites

Plain curl checks the raw HTML, but many modern sites render content with JavaScript. If your site is a single-page application, a curl check might return a 200 with an empty shell, while a real user sees a blank page. For those cases, you need a headless browser.

You do not need a commercial monitoring service for this. A small Node.js script using the built-in http module cannot execute JavaScript, but you can use a headless browser via the command line. The exact tool depends on your environment, but the pattern is the same: launch a browser, navigate to the URL, wait for a specific DOM element, and report success or failure.

A minimal script in Node.js using the puppeteer library (which you install locally with npm) looks like this:

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  try {
    await page.goto('https://example.com', { waitUntil: 'networkidle0', timeout: 15000 });
    await page.waitForSelector('#app-content', { timeout: 5000 });
    console.log('UP');
  } catch (err) {
    console.log('DOWN: ' + err.message);
  } finally {
    await browser.close();
  }
})();

This script waits for the network to be idle and then for a specific element with id="app-content" to appear. If either step fails, it prints DOWN with the error. You can run this from cron just like the curl script. The tradeoff is that headless browsers use more memory and CPU, so you should not run them every minute on a small VPS. Every five minutes is a reasonable compromise.

What to do with the data you collect

Once you have a log file with timestamps, status codes, and response times, you can turn it into a simple report. A weekly awk command can count how many checks failed and compute the average response time. You can also use grep to find all alert lines and email them to yourself.

The important thing is to keep the log on a different machine from the one you are monitoring. If your server goes down, you lose the log that proves it. Run the cron job from your laptop, a Raspberry Pi, or a small cloud instance that is not your hosting provider. That way, your monitoring is independent of the thing you are monitoring.

Start with the curl script and a five-minute cron job. Run it for a week, then look at the log. You will see patterns: slow responses during peak hours, occasional timeouts, maybe a maintenance window your host did not announce. That data is your evidence. When you talk to your host about a refund or a service credit, you bring the log, not a screenshot of a third-party dashboard.

Related articles

Subscribe to our newsletter

Get the latest hosting tips, performance insights, and industry news.