Automated Website Monitoring with Screenshots

Set up visual monitoring to catch UI bugs before your users do.

📋 Table of Contents

Why Visual Monitoring?

Traditional monitoring checks if your website is "up" - but what about visual issues? A deployment might succeed while:

Visual monitoring with screenshots catches these issues before users report them.

📊 Stat: Visual bugs account for 23% of all production issues, yet most monitoring tools miss them entirely.

System Architecture

Here's a simple architecture for screenshot-based monitoring:

  1. Scheduler - Runs every 5-15 minutes (cron, GitHub Actions, etc.)
  2. Screenshot API - Captures current state of your pages
  3. Storage - Saves screenshots with timestamps
  4. Comparison - Detects visual changes
  5. Alerting - Notifies you of issues (Slack, email, etc.)

Implementation

Step 1: Define Pages to Monitor

const PAGES_TO_MONITOR = [
  { name: 'Homepage', url: 'https://yoursite.com/', device: 'desktop' },
  { name: 'Homepage Mobile', url: 'https://yoursite.com/', device: 'mobile' },
  { name: 'Pricing', url: 'https://yoursite.com/pricing', device: 'desktop' },
  { name: 'Login', url: 'https://yoursite.com/login', device: 'desktop' },
];

Step 2: Capture Screenshots

const fs = require('fs');
const path = require('path');

async function captureScreenshots() {
  const API_KEY = process.env.SNAPAPI_KEY;
  const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
  
  for (const page of PAGES_TO_MONITOR) {
    const params = new URLSearchParams({
      url: page.url,
      api_key: API_KEY,
      device: page.device,
      response: 'binary'
    });
    
    const response = await fetch(
      `https://snapapi.alterra-solutions.com/v1/screenshot?${params}`
    );
    
    const buffer = await response.arrayBuffer();
    const filename = `${page.name.toLowerCase().replace(/\s+/g, '-')}_${timestamp}.png`;
    
    fs.writeFileSync(
      path.join('./screenshots', filename),
      Buffer.from(buffer)
    );
    
    console.log(`✅ Captured: ${page.name}`);
  }
}

captureScreenshots();

Step 3: Compare Screenshots

const pixelmatch = require('pixelmatch');
const { PNG } = require('pngjs');

async function compareScreenshots(current, previous) {
  const img1 = PNG.sync.read(fs.readFileSync(previous));
  const img2 = PNG.sync.read(fs.readFileSync(current));
  
  const { width, height } = img1;
  const diff = new PNG({ width, height });
  
  const numDiffPixels = pixelmatch(
    img1.data,
    img2.data,
    diff.data,
    width,
    height,
    { threshold: 0.1 }
  );
  
  const diffPercentage = (numDiffPixels / (width * height)) * 100;
  
  return {
    diffPercentage,
    diffImage: diff,
    hasMajorChanges: diffPercentage > 5 // Alert if >5% changed
  };
}

⚠️ Tip: Set your threshold carefully. Small changes (like timestamps or ads) might cause false positives. A 5% threshold works well for most sites.

Setting Up Alerts

Slack Webhook Alert

async function sendSlackAlert(page, diffPercentage, screenshotUrl) {
  const webhookUrl = process.env.SLACK_WEBHOOK_URL;
  
  await fetch(webhookUrl, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      text: `🚨 Visual change detected!`,
      attachments: [{
        color: 'danger',
        fields: [
          { title: 'Page', value: page.name, short: true },
          { title: 'Change', value: `${diffPercentage.toFixed(2)}%`, short: true },
          { title: 'URL', value: page.url }
        ],
        image_url: screenshotUrl
      }]
    })
  });
}

GitHub Actions Scheduler

# .github/workflows/visual-monitor.yml
name: Visual Monitoring

on:
  schedule:
    - cron: '*/15 * * * *'  # Every 15 minutes
  workflow_dispatch:

jobs:
  monitor:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
      
      - name: Install dependencies
        run: npm install
      
      - name: Run visual monitoring
        env:
          SNAPAPI_KEY: ${{ secrets.SNAPAPI_KEY }}
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
        run: node monitor.js

Best Practices

✅ Result: With this setup, you'll catch visual issues within minutes of deployment - before users notice!

Start Monitoring Your Site

Get 100 free screenshots per month - enough for basic monitoring of 3-4 pages.

Get Your API Key →