How to Build Your Own Wayback Machine Using ScreenshotAPI

Profile
Hanzala Saleem

23 Oct 2025 | 8 min read

Have you ever wondered how web pages looked years ago? Whether for compliance, archiving, research, or monitoring change over time, having such a system is highly valuable. While the Internet Archive's Wayback Machine is fantastic, what if you could build your own custom website archiving system?

In this post, we'll show you how you can use ScreenshotAPI.net as the screenshot engine behind your system. You'll learn why ScreenshotAPI is a good fit, how to design the architecture, and then walk through a full implementation guide with code samples.

What Is a Wayback Machine and Why Build One?

Before we dive into the technical details, let's understand what we're building. A wayback machine is essentially a web archive that captures and stores snapshots of websites over time. Think of it as a digital time capsule for the internet.

Why would you want to build your own?

  • Brand Monitoring: Track how your competitors' websites evolve over time.
  • Legal Documentation: Preserve evidence of web content for compliance or legal purposes.
  • Historical Research: Document the evolution of web design and content in your industry.
  • Personal Archive: Save important web pages before they disappear.
  • Client Reporting: Show clients the progress and changes made to their sites.

Why Choose ScreenshotAPI.net for Website Archiving?

While creating a website archiving system, you need a reliable screenshot API that can handle multiple challenges. Here's why ScreenshotAPI.net stands out:

Reliable Rendering: The API uses real browsers to capture screenshots, ensuring you get pixel-perfect representations exactly as users see them, including proper fonts and layout.

Flexible Capture Options: You can capture full page screenshots, specific sections, or viewports at different screen sizes – perfect for archiving both desktop and mobile versions. The service handles long pages and entire page capture automatically.

Scalability: Whether you're archiving ten websites or ten thousand, the API scales with your needs and supports developers with comprehensive documentation.

Understanding the Core Concept

Building a wayback machine involves three main components:

  1. Capture Engine: Takes screenshots of websites at scheduled intervals
  2. Storage System: Organizes and stores the captured images with timestamps
  3. Retrieval Interface: Allows you to browse and compare archived versions

ScreenshotAPI.net handles the complex rendering part, while you build the scheduling, storage, and interface around it.

Step-by-Step Guide to Building Your Wayback Machine

Step 1: Get Your ScreenshotAPI.net API Key

First of all you need access to the screenshot API. Go to ScreenshotAPI.net and sign up for a free account. Once registered, you can get an API key that authenticates your requests. Keep this key secure, as it's your gateway to the screenshot functionality.

Step 2: Set Up Your Development Environment

For this tutorial, I'll use Node.js because it's perfect for API integrations and has excellent async support for handling multiple captures. Here's what you'll need:

  • Node.js version 14 or higher installed
  • A code editor like VS Code
  • Basic understanding of REST APIs and JavaScript
  • A place to store your screenshots (local storage or cloud)

First, create a new project directory and initialize it:

mkdir wayback-machine
cd wayback-machine
npm init -y

Install the necessary Node.js packages:

npm install axios node-cron express sqlite3 fs-extra dotenv

These libraries will help you make API calls, schedule regular captures, handle file operations, and manage your database.

Step 3: Create Your Screenshot Capture Function

Now let's write the core function that captures website screenshots. Create a file called capture.js:

const axios = require('axios');
const fs = require('fs-extra');
const path = require('path');

async function captureWebsite(url, apiKey, outputFolder = 'archives') {
  try {
    // Create output folder if it doesn't exist
    await fs.ensureDir(outputFolder);

    // Prepare the API request
    const apiUrl = 'https://shot.screenshotapi.net/v3/screenshot';
    const params = {
      token: apiKey,
      url: url,
      full_page: 'true',
      output: 'image',
      file_type: 'png',
      no_cookie_banners:'true',
      wait_for_event: 'load'
    };

    // Make the request to capture the full page screen
    const response = await axios.get(apiUrl, {
      params: params,
      responseType: 'arraybuffer'
    });

    if (response.status === 200) {
      // Generate filename with timestamp
      const timestamp = new Date().toISOString().replace(/:/g, '-').split('.')[0];
      const safeUrl = url.replace(/https?:\/\//, '').replace(/\//g, '_');
      const filename = `${safeUrl}_${timestamp}.png`;
      const filepath = path.join(outputFolder, filename);

      // Save the screenshot as PNG format
      await fs.writeFile(filepath, response.data);

      console.log(`Screenshot saved: ${filename}`);
      return filepath;
    }
  } catch (error) {
    console.error(`Error capturing screenshot: ${error.message}`);
    return null;
  }
}

module.exports = { captureWebsite };

This function constructs a proper API request with your credentials, handles the response asynchronously, generates a meaningful filename with timestamps, and saves the full image to your archive folder. The service automatically handles cookie banners and ads during the screenshot capture process.

Step 4: Build the Scheduling System

A wayback machine isn't useful if you have to manually trigger it every time. Let's automate the capture process using node-cron. Create a file called scheduler.js:

const cron = require('node-cron');
const { captureWebsite } = require('./capture');

class ArchiveScheduler {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.tasks = [];
  }

  async captureAll(urls) {
    for (const url of urls) {
      await captureWebsite(url, this.apiKey);
      // Be respectful, don't hammer the API
      await this.sleep(5000);
    }
  }

  sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }

  scheduleDaily(urls, hour = 2, minute = 0) {
    // Schedule daily at specified time (default 2:00 AM)
    const task = cron.schedule(`${minute} ${hour} * * *`, async () => {
      console.log('Starting daily capture...');
      await this.captureAll(urls);
    });

    this.tasks.push(task);
    console.log(`Scheduled daily captures at ${hour}:${minute} for ${urls.length} websites`);
    return task;
  }

  scheduleHourly(urls, minute = 0) {
    // Schedule hourly at specified minute
    const task = cron.schedule(`${minute} * * * *`, async () => {
      console.log('Starting hourly capture...');
      await this.captureAll(urls);
    });

    this.tasks.push(task);
    console.log(`Scheduled hourly captures for ${urls.length} websites`);
    return task;
  }

  scheduleWeekly(urls, dayOfWeek = 1, hour = 2, minute = 0) {
    // Schedule weekly (default: Monday at 2:00 AM)
    const task = cron.schedule(`${minute} ${hour} * * ${dayOfWeek}`, async () => {
      console.log('Starting weekly capture...');
      await this.captureAll(urls);
    });

    this.tasks.push(task);
    console.log(`Scheduled weekly captures for ${urls.length} websites`);
    return task;
  }

  stopAll() {
    this.tasks.forEach(task => task.stop());
    console.log('All scheduled tasks stopped');
  }
}

module.exports = { ArchiveScheduler };

This scheduler runs in the background to automate screenshot capture at your specified intervals. Running captures at 2 AM when traffic is low is generally a good practice.

Step 5: Create a Database to Track Your Archives

While storing images is straightforward, you need a way to track metadata and log each capture. Let's use SQLite for simplicity. Create a file called database.js:

const sqlite3 = require('sqlite3').verbose();
const path = require('path');
const fs = require('fs-extra');

class ArchiveDatabase {
  constructor(dbPath = 'wayback_archive.db') {
    this.db = new sqlite3.Database(dbPath);
    this.initialize();
  }

  initialize() {
    return new Promise((resolve, reject) => {
      this.db.run(`
        CREATE TABLE IF NOT EXISTS archives (
          id INTEGER PRIMARY KEY AUTOINCREMENT,
          url TEXT NOT NULL,
          capture_date DATETIME DEFAULT CURRENT_TIMESTAMP,
          filepath TEXT NOT NULL,
          file_size INTEGER,
          status TEXT DEFAULT 'success'
        )
      `, (err) => {
        if (err) reject(err);
        else resolve();
      });
    });
  }

  async logCapture(url, filepath) {
    const stats = await fs.stat(filepath);
    const fileSize = stats.size;

    return new Promise((resolve, reject) => {
      this.db.run(`
        INSERT INTO archives (url, filepath, file_size)
        VALUES (?, ?, ?)
      `, [url, filepath, fileSize], function(err) {
        if (err) reject(err);
        else resolve(this.lastID);
      });
    });
  }

  getArchivesByUrl(url) {
    return new Promise((resolve, reject) => {
      this.db.all(`
        SELECT * FROM archives
        WHERE url = ?
        ORDER BY capture_date DESC
      `, [url], (err, rows) => {
        if (err) reject(err);
        else resolve(rows);
      });
    });
  }

  getAllUrls() {
    return new Promise((resolve, reject) => {
      this.db.all(`
        SELECT DISTINCT url FROM archives ORDER BY url
      `, (err, rows) => {
        if (err) reject(err);
        else resolve(rows.map(row => row.url));
      });
    });
  }

  close() {
    this.db.close();
  }
}

module.exports = { ArchiveDatabase };

Now every capture is logged with its URL, timestamp, location, and file size. This makes it easy to query your archive later and track the image size of each snapshot.

Step 6: Build a Simple Web Interface

Having all these screenshots is great, but you need a way to browse them. Here's a simple Express-based web interface. Create a file called server.js:

const express = require('express');
const path = require('path');
const { ArchiveDatabase } = require('./database');

const app = express();
const db = new ArchiveDatabase();

// Serve static files (screenshots)
app.use('/archives', express.static('archives'));
app.use(express.static('public'));

// Set view engine
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));

// Home page - list all archived URLs
app.get('/', async (req, res) => {
  try {
    const urls = await db.getAllUrls();
    res.render('index', { urls });
  } catch (error) {
    res.status(500).send('Error loading archives');
  }
});

// Timeline page - show all captures for a specific URL
app.get('/timeline', async (req, res) => {
  try {
    const url = req.query.url;
    const captures = await db.getArchivesByUrl(url);
    res.render('timeline', { url, captures });
  } catch (error) {
    res.status(500).send('Error loading timeline');
  }
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Wayback Machine running on http://localhost:${PORT}`);
});

This creates a simple web app interface where you can select a website and view its capture timeline. Users can easily download and print archived versions.

Step 7: Putting It All Together

Now let's create a main file that ties everything together. Create index.js:

require('dotenv').config();
const { captureWebsite } = require('./capture');
const { ArchiveScheduler } = require('./scheduler');
const { ArchiveDatabase } = require('./database');

// Configuration
const API_KEY = process.env.SCREENSHOTAPI_KEY;
const WEBSITES_TO_MONITOR = [
  'https://example.com',
  'https://competitor1.com',
  'https://competitor2.com'
];

async function main() {
  // Initialize database
  const db = new ArchiveDatabase();

  // Create scheduler
  const scheduler = new ArchiveScheduler(API_KEY);

  // Schedule daily captures at 2 AM
  scheduler.scheduleDaily(WEBSITES_TO_MONITOR, 2, 0);

  console.log('Wayback Machine initialized!');
  console.log(`Monitoring ${WEBSITES_TO_MONITOR.length} websites`);
  console.log('Scheduled captures will run daily at 2:00 AM');

  // Optional: Capture immediately on start
  console.log('Taking initial snapshots...');
  for (const url of WEBSITES_TO_MONITOR) {
    const filepath = await captureWebsite(url, API_KEY);
    if (filepath) {
      await db.logCapture(url, filepath);
    }
  }

  console.log('Initial snapshots complete!');
}

// Handle graceful shutdown
process.on('SIGINT', () => {
  console.log('Shutting down gracefully...');
  process.exit(0);
});

main().catch(console.error);

Create a .env file to store your API key:

SCREENSHOTAPI_KEY=your_api_key_here

Common Use Cases and Examples

Competitor Analysis: A marketing agency archives competitors' homepages weekly, tracking messaging changes, design updates, and promotional campaigns using full page screenshots.

Compliance Monitoring: A legal firm captures regulated websites daily to ensure compliance with advertising standards and maintain evidence for cases, storing each version as data for review.

Portfolio Documentation: A web design agency archives client websites before and after redesigns, creating compelling before-and-after showcases with full size page screenshots.

Price Tracking: An e-commerce consultant monitors competitor pricing pages, capturing changes and identifying pricing strategies through regular webpage snapshots.

Content Preservation: A journalist archives news articles and social media posts for investigative research before they can be deleted or modified, ensuring no online content is lost.

Conclusion: Your Time Machine Awaits

Building your own wayback machine with ScreenshotAPI.net gives you unexpected control over website archiving. Whether you're tracking competitors, preserving content for legal purposes, or simply documenting the evolution of the web, this system puts you in the driver's seat.

The beauty of this approach is its flexibility. Start simple with basic scheduled captures, then expand with comparison tools, mobile viewports, and cloud storage as your needs grow. The service supports various features including custom width parameters, scale adjustments, and zoom control. You can also export to different formats like JPEG or PDF based on your requirements.

The combination of ScreenshotAPI.net's reliable browser rendering engine and your custom Node.js code creates a powerful archiving tool tailored to your exact requirements. The documentation provides detailed instructions for integration, and support is available to help developers throughout the process.

Remember, the internet is constantly changing, and websites disappear or transform without warning. Your custom wayback machine ensures you never lose track of important content again. Start building today, and create your own window into the web's past, present, and future.

Ready to get started? Sign up for ScreenshotAPI.net, grab your API key, and begin archiving the websites that matter to you. Your digital time capsule awaits!