Full-Page Screenshot

by kuligaposten 2025-02-01

Building a Full-Page Screenshot Capture Tool with Puppeteer and Express

Capturing full-page screenshots of websites can be incredibly useful for various purposes, such as website archiving, UI testing, and content monitoring. In this post, we'll explore how to build a simple web-based screenshot capture tool using Node.js, Express, and Puppeteer.

Overview of the Script

The script consists of an Express.js router that provides two main functionalities:

  1. A homepage (GET /) that renders a form for users to enter a URL.
  2. A screenshot route (POST /) that uses Puppeteer to capture a full-page screenshot of the given website and displays the result.

Technologies Used:

  • Express.js: Web framework for handling routes.
  • Puppeteer: Headless Chrome automation for taking screenshots.
  • EJS Layouts: Used for rendering dynamic pages.
  • Path & URL Modules: Manage file paths and resolve module URLs.

Setting Up the Express Router

Importing Required Modules

import express from "express";
import puppeteer from "puppeteer";
import path from "path";
import { fileURLToPath } from "url";
import { renderWithLayout } from "../utils/renderWithLayout.js";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const router = express.Router();

We import necessary modules, including puppeteer for browser automation, path for handling file paths, and fileURLToPath for module resolution in ES modules.

Homepage Route - Rendering the Form

router.get("/", (req, res) => {
  renderWithLayout(res, "layouts/main", {
    page: "screenshot",
    title: "Screenshot",
    description: `taking a screenshot`,
  });
});

This route serves the form page where users can input the URL, select an image format, and specify the viewport width.


Capturing Screenshots with Puppeteer

Handling Screenshot Requests

router.post("/", async (req, res) => {
  let { url, format, width } = req.body;

  if (!url) return res.status(400).send("URL is required");

  // Auto-add "https://" if missing
  if (!/^https?:\/\//i.test(url)) {
    url = `https://${url}`;
  }

  const timestamp = Date.now();
  const screenshotPath = path.join(
    __dirname,
    "../public/screenshots",
    `screenshot-${timestamp}.${format}`,
  );
  let browser = null;
  try {
    console.log(
      `📸 Capturing full-page screenshot: ${url} | Format: ${format} | Width: ${width}px`,
    );

    browser = await puppeteer.launch({
      headless: "new",
      args: ["--no-sandbox", "--disable-setuid-sandbox"],
    });
    const page = await browser.newPage();

    await page.setViewport({ width: parseInt(width), height: 1080 });
    await page.goto(url, { waitUntil: "networkidle2" });

    // Get full page height
    const pageHeight = await page.evaluate(
      () => document.documentElement.scrollHeight,
    );
    await page.setViewport({ width: parseInt(width), height: pageHeight });

    // Capture Screenshot with Selected Format
    await page.screenshot({
      path: screenshotPath,
      fullPage: true,
      type: format,
    });

    console.log(`Screenshot saved: ${screenshotPath}`);

    // Render result page
    renderWithLayout(res, "layouts/main", {
      page: "result",
      title: "Captured screenshot",
      description: `Captured screenshot of ${url}`,
      screenshotPath: `/screenshots/screenshot-${timestamp}.${format}`,
      format,
    });
  } catch (error) {
    console.error("❌ Error capturing screenshot:", error);
    renderWithLayout(res, "layouts/main", {
      page: "500",
      title: "Internal error",
      description: `Internal error`,
    });
  } finally {
    if (browser) await browser.close(); // Ensure browser closes
  }
});

Key Features:

  • Auto-adds HTTPS: Ensures URLs are properly formatted before navigation.
  • Dynamic Viewport Adjustment: Captures the full height of the page dynamically.
  • Format Selection: Allows users to choose PNG, JPEG, or WebP output.
  • Handles Errors Gracefully: Catches exceptions and renders an error page if anything fails.

Running the Screenshot Tool

Install Dependencies

npm install express puppeteer

Start the Server

node server.js

Make sure to configure your Express app to use this router.


Enhancements & Next Steps

  • Add an Image Preview: Display the captured screenshot directly on the result page.
  • Allow Custom Image Quality: Enable users to choose compression levels for JPEG/WebP formats.
  • Store Screenshots in Cloud Storage: Save images to AWS S3 or Cloudinary instead of local storage.
  • Optimize Performance: Implement caching to avoid redundant screenshots of the same URL.

Conclusion

This script provides a straightforward way to capture full-page screenshots using Puppeteer and Express. With additional optimizations, it can be expanded into a powerful screenshot API for developers or a simple online tool for users.

check it out here

Back to Home