Building A Website Screenshot API With Puppeteer And Google Cloud Functions

In this blog post, I describe the steps I took to set up this API, let’s dive in!


Puppeteer is a node package that allows you to control a headless chrome browser using Javascript. A headless chrome browser is just a browser without a window.

I can use this package to spin up a headless chrome instance, navigate to a website and take a screenshot.

To start I’m going to create a local node project and install the puppeteer package.

npm init
npm install puppeteer

Now I can create a file called index.js and add the following code.

const puppeteer = require('puppeteer');

.then(() => {
console.log("Screenshot taken");
.catch((err) => {
console.log("Error occured!");

async function takeScreenshot() {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto("", {waitUntil: 'networkidle2'});

const buffer = await page.screenshot({
path: './screenshot.png'
await page.close();
await browser.close();

Note that I am making the takeScreenshot() function async. This way I can use the await keyword in the function to wait for all the promises.

After running the code I get the following screenshot! 🎉

Google Cloud Functions

So I now have a local script that I can call to take a screenshot, but I want to build an API. The next logical step is to put this script on a server somewhere.

I don’t want to worry about my server running out of memory, so I’m going to put it on Google Cloud Functions. This way it can handle a huge number of requests without me having to worry about buying more RAM memory.

Once I have the cloud function running, I can call it with an HTTP request — meaning that I will have a working screenshot API 🚀

Let’s port the previous code to the Google Cloud Function format. The cloud function I created is async and called run().

So far I have a working screenshot API. But I’m going to extend it by uploading the screenshots directly to Google Storage.

I’m going to use the @google-cloud/storage npm package for this.

Note that I have created a Google Cloud Storage bucket called screenshot-api checkout this page for how to set up a storage bucket.

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

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

async function uploadToGoogleCloud(buffer, filename) {
	const storage = new Storage({
	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 }, () => {

The new result — My postman client is showing the URL to the screenshot 🚀

Note that in the code above each screenshot is saved as screenshot.png on Google Storage. In the real world, you would need to generate a random id for each image.


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.
This was a fun project to do.
You can find the source code of the completed Google Cloud function and package.json here.
Thanks for reading!