Introduction
In this guide, we’ll create a Next.js API that takes a webpage URL and generates a PNG screenshot using puppeteer and chrome-aws-lambda. This setup is optimized for both local and serverless environments.
Prerequisites
- Basic understanding of Next.js
- Node.js installed on your system
Step 1: Set Up Your Next.js Project
Run the following commands to create a new Next.js app and install necessary packages:
npx create-next-app@latest capture-image-app
cd capture-image-app
npm install puppeteer puppeteer-core chrome-aws-lambda busboy
Step 2: Create the API Route
In pages/api folder, create a file named generate-png.ts and add this code:
import { NextApiRequest, NextApiResponse } from "next";
import busboy from "busboy";
import chromium from "chrome-aws-lambda";
import puppeteerCore from "puppeteer-core";
import puppeteer from "puppeteer";
const puppeteerModule = process.env.NODE_ENV === "production" ? puppeteerCore : puppeteer;
export const config = { api: { bodyParser: false } };
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method !== "POST") return res.status(405).end("Method Not Allowed");
const bb = busboy({ headers: req.headers });
let htmlContent = "";
bb.on("file", (_, file) => {
file.on("data", (data) => htmlContent += data.toString());
});
bb.on("finish", async () => {
const browser = await puppeteerModule.launch({
args: ["--no-sandbox"],
executablePath: process.env.NODE_ENV === "production" ? await chromium.executablePath : undefined,
headless: true,
});
const page = await browser.newPage();
await page.setContent(htmlContent, { waitUntil: "networkidle0" });
const screenshot = await page.screenshot({ type: "png" });
await browser.close();
res.setHeader("Content-Type", "image/png");
res.setHeader("Content-Disposition", "attachment; filename=screenshot.png");
res.end(screenshot);
});
req.pipe(bb);
}
Step 3: Build the Frontend
Create a form that captures the screenshot:
import { useState } from "react";
export default function CaptureComponent() {
const [isLoading, setLoading] = useState(false);
async function captureScreenshot() {
setLoading(true);
const response = await fetch("/api/generate-png", { method: "POST" });
const blob = await response.blob();
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = "screenshot.png";
link.click();
setLoading(false);
}
return (
<div>
<h2>Capture Screenshot</h2>
<button onClick={captureScreenshot} disabled={isLoading}>
{isLoading ? "Capturing..." : "Capture"}
</button>
</div>
);
}
Conclusion
You’ve successfully built a webpage screenshot tool using Next.js and Puppeteer. This method works in both local and serverless environments, providing a scalable way to capture images from web pages.
Leave a reply to Kevin Hurdle Cancel reply