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);
Get Your Free API Key
curl https://frostbyte-api.ozorown.com/api/keys/create
That's it. 200 free credits, no signup, no credit card.
Running It
Save as monitor.js and run:
node monitor.js
Output:
--- Check at 2026-03-05T14:30:00.000Z ---
✅ Main Site — 200 (234ms)
✅ API — 200 (89ms)
❌ Blog — 503 (1205ms)
⚠️ ALERT: Blog is DOWN (503)
Add Slack Alerts
- Create a Slack webhook at api.slack.com/messaging/webhooks
- Set
WEBHOOK_URLin the script - 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
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 }}
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);
}
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)