Building a Website Screenshot API with Puppeteer and Google Cloud Functions

Here’s the source of a Google Cloud function that, using Puppeteer, takes a screenshot of a given website and store the resulting screenshot in a bucket on Google Cloud Storage:

const puppeteer = require('puppeteer');
const { Storage } = require('@google-cloud/storage');

const GOOGLE_CLOUD_PROJECT_ID = "screenshotapi";
const BUCKET_NAME = "screenshot-api-net"; = async (req, res) => {
  res.setHeader("content-type", "application/json");
  try {
    const buffer = await takeScreenshot(req.body);
    let screenshotUrl = await uploadToGoogleCloud(buffer, "screenshot.png");
      'screenshotUrl': screenshotUrl
  } catch(error) {
      error: error.message,

async function uploadToGoogleCloud(buffer, filename) {
    const storage = new Storage({
        projectId: GOOGLE_CLOUD_PROJECT_ID,

    const bucket = storage.bucket(BUCKET_NAME);

    const file = bucket.file(filename);
    await uploadBuffer(file, buffer, filename);
    await file.makePublic();

  	return `https://${BUCKET_NAME}${filename}`;

async function takeScreenshot(params) {
	const browser = await puppeteer.launch({
		args: ['--no-sandbox']
	const page = await browser.newPage();
	await page.goto(params.url, {waitUntil: 'networkidle2'});

	const buffer = await page.screenshot();

	await page.close();
	await browser.close();
  	return buffer;

async function uploadBuffer(file, buffer, filename) {
    return new Promise((resolve) => {, { destination: filename }, () => {


curl -X POST -d '{"url": ""}' https://google-cloud-endpoint/my-function

Building a Website Screenshot API →

💡 If I were to run this in production I’d extend the code to first check the presence of an existing screenshot in the bucket or not, and – if the screenshot is not too old – redirect to it.

Published by Bramus!

Bramus is a frontend web developer from Belgium, working as a Chrome Developer Relations Engineer at Google. From the moment he discovered view-source at the age of 14 (way back in 1997), he fell in love with the web and has been tinkering with it ever since (more …)

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.