DEV Community

Ozor
Ozor

Posted on

How to Build Website Uptime Monitoring in 10 Minutes (Free, No Dependencies)

You don't need Datadog, PagerDuty, or a $29/month plan to monitor your websites. With 40 lines of code and a free API, you can build uptime monitoring that actually alerts you when things break.

Here's the complete setup.

What We're Building

A script that:

  • Checks if your websites are up every 5 minutes
  • Takes a screenshot when something goes down (proof of the failure)
  • Sends you an alert via webhook (Slack, Discord, or email)
  • Logs response times so you can spot slow degradation
  • Runs on any machine (VPS, Raspberry Pi, GitHub Actions)

The Code (Node.js)

const https = require('https');

const API_KEY = 'your-api-key'; // Free at frostbyte-api.ozorown.com
const BASE = 'https://frostbyte-api.ozorown.com';
const WEBHOOK_URL = ''; // Your Slack/Discord webhook (optional)

const sites = [
  { name: 'Main Site', url: 'https://example.com' },
  { name: 'API', url: 'https://api.example.com/health' },
  { name: 'Blog', url: 'https://blog.example.com' },
];

async function fetchJSON(url) {
  return new Promise((resolve, reject) => {
    https.get(url, { headers: { 'x-api-key': API_KEY } }, (res) => {
      let data = '';
      res.on('data', (chunk) => data += chunk);
      res.on('end', () => resolve({ status: res.statusCode, body: data }));
    }).on('error', reject);
  });
}

async function checkSite(site) {
  const start = Date.now();
  try {
    const res = await fetchJSON(
      `${BASE}/api/scraper/fetch?url=${encodeURIComponent(site.url)}`
    );
    const elapsed = Date.now() - start;
    const ok = res.status === 200;

    console.log(
      `${ok ? '' : ''} ${site.name}${res.status} (${elapsed}ms)`
    );

    if (!ok) {
      // Take a screenshot of the broken page for evidence
      const screenshot = await fetchJSON(
        `${BASE}/api/screenshot?url=${encodeURIComponent(site.url)}&width=1280&height=800`
      );
      await sendAlert(site, res.status, elapsed, screenshot.body);
    }

    return { name: site.name, status: res.status, time: elapsed, ok };
  } catch (err) {
    console.log(`❌ ${site.name} — UNREACHABLE: ${err.message}`);
    await sendAlert(site, 0, 0, null);
    return { name: site.name, status: 0, time: 0, ok: false };
  }
}

async function sendAlert(site, status, time, screenshotData) {
  if (!WEBHOOK_URL) {
    console.log(`  ⚠️ ALERT: ${site.name} is DOWN (${status})`);
    return;
  }

  const payload = JSON.stringify({
    text: `🚨 *${site.name}* is DOWN!\nURL: ${site.url}\nStatus: ${status}\nResponse time: ${time}ms\nTime: ${new Date().toISOString()}`
  });

  return new Promise((resolve) => {
    const url = new URL(WEBHOOK_URL);
    const req = https.request({
      hostname: url.hostname,
      path: url.pathname,
      method: 'POST',
      headers: { 'Content-Type': 'application/json' }
    }, resolve);
    req.write(payload);
    req.end();
  });
}

async function runChecks() {
  console.log(`\n--- Check at ${new Date().toISOString()} ---`);
  const results = [];
  for (const site of sites) {
    results.push(await checkSite(site));
  }
  const down = results.filter(r => !r.ok);
  if (down.length === 0) {
    console.log('All sites healthy.');
  }
}

// Run every 5 minutes
runChecks();
setInterval(runChecks, 5 * 60 * 1000);
Enter fullscreen mode Exit fullscreen mode

Get Your Free API Key

curl https://frostbyte-api.ozorown.com/api/keys/create
Enter fullscreen mode Exit fullscreen mode

That's it. 200 free credits, no signup, no credit card.

Running It

Save as monitor.js and run:

node monitor.js
Enter fullscreen mode Exit fullscreen mode

Output:

--- Check at 2026-03-05T14:30:00.000Z ---
✅ Main Site — 200 (234ms)
✅ API — 200 (89ms)
❌ Blog — 503 (1205ms)
  ⚠️ ALERT: Blog is DOWN (503)
Enter fullscreen mode Exit fullscreen mode

Add Slack Alerts

  1. Create a Slack webhook at api.slack.com/messaging/webhooks
  2. Set WEBHOOK_URL in the script
  3. When a site goes down, you get an instant notification with the status code and response time

Discord works the same way — just use your Discord webhook URL instead.

Run It 24/7 (Free Options)

On a VPS with PM2

npm install -g pm2
pm2 start monitor.js --name "uptime-monitor"
pm2 save
pm2 startup
Enter fullscreen mode Exit fullscreen mode

Now it survives reboots and runs in the background.

On GitHub Actions (Free)

Create .github/workflows/monitor.yml:

name: Uptime Monitor
on:
  schedule:
    - cron: '*/5 * * * *'
  workflow_dispatch:

jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: node monitor.js
        env:
          API_KEY: ${{ secrets.FROSTBYTE_API_KEY }}
Enter fullscreen mode Exit fullscreen mode

GitHub gives you 2,000 free minutes per month — enough for checks every 5 minutes.

Adding Response Time Tracking

Want to track response times over time? Append to a CSV:

const fs = require('fs');

function logResult(result) {
  const line = `${new Date().toISOString()},${result.name},${result.status},${result.time}\n`;
  fs.appendFileSync('uptime.csv', line);
}
Enter fullscreen mode Exit fullscreen mode

Then graph it with any spreadsheet tool, or pipe it into Grafana.

Why Not Just Use Pingdom/UptimeRobot?

You can. But:

  • Free tiers are limited — usually 5 monitors, 5-minute intervals, no screenshots
  • No screenshot evidence — when your boss asks "what did the error page look like?", you have the proof
  • No customization — you can't add custom logic, chain checks, or integrate with your own tools
  • Vendor lock-in — your monitoring shouldn't depend on yet another SaaS subscription

This script is 40 lines, runs anywhere, and costs nothing.

What Else Can You Monitor?

The same API gives you:

  • DNS checks: Verify your DNS records haven't been tampered with
  • SSL certificate monitoring: Check certificate expiry dates
  • Content monitoring: Detect unauthorized changes to your pages
  • API response validation: Check that your API returns expected data

All through the same API key, same endpoint pattern.


The Frostbyte API is free (200 credits, no signup). Get your API key and start monitoring in 2 minutes.

Top comments (0)