Application Development

Introducing headless Chrome support in Cloud Functions and App Engine

headless chrome

Earlier this year, Google Cloud announced support for the Node.js 8 runtime in the App Engine standard environment. Since then, we've been excited to see how web developers have been using the platform.

One of the more interesting use cases that was unlocked with the new Node.js runtime for App Engine is the ability to run headless Chrome without having to do any setup or configuration. Previously, developers would need to run xvfb and X11, create a complicated Dockerfile, or configure OS dependencies themselves to get Chrome working on GCP—but not anymore.

Now, we're pleased to announce that the Google Cloud Functions and Cloud Functions for Firebase Node.js 8 runtimes have also been upgraded with the OS packages required to run headless Chrome. This means that you can now author Cloud Functions that use headless Chrome---and utilize all the features of a web browser in a fully serverless environment. Headless Chrome lets you take advantage of the modern web platform features from Chromium and the Blink rendering engine too.

We have seen developers using headless Chrome for a variety of use cases:

  • taking screenshots of web pages

  • server-side rendering

  • generating PDFs

  • implementing web crawlers

  • end-to-end performance and UI testing

Using Puppeteer in a Cloud Function

One way to use headless Chrome with Cloud Functions is with Puppeteer. Puppeteer is a Node.js library built by the Chrome DevTools team that provides a high-level API to control headless Chrome (or Chromium) over the DevTools Protocol. It also installs a recent version of Chromium alongside the library by default.

Using Puppeteer to control headless Chrome is ideal for environments like Cloud Functions, because you spend less time configuring Chrome (and its required dependencies) and more time writing your own code.

One useful example of using Puppeteer in a Cloud Function is to create a service that takes screenshots of web pages. The code snippet below creates an HTTP handler that takes a screenshot of a web page and returns the image as the response.

Main index.js file:


  const puppeteer = require('puppeteer');
let page;

async function getBrowserPage() {
  // Launch headless Chrome. Turn off sandbox so Chrome can run under root.
  const browser = await puppeteer.launch({args: ['--no-sandbox']});
  return browser.newPage();
}

exports.screenshot = async (req, res) => {
  const url = req.query.url;

  if (!url) {
    return res.send('Please provide URL as GET parameter, for example: <a 
href="?url=https://example.com">?url=https://example.com</a>');
  }

  if (!page) {
    page = await getBrowserPage();
  }

  await page.goto(url);
  const imageBuffer = await page.screenshot();
  res.set('Content-Type', 'image/png');
  res.send(imageBuffer);
};

List puppeteer as a dependency in your package.json:


  { 
  "name": "screenshot",
  "version": "0.0.1",
  "dependencies": { 
    "puppeteer": "^1.6.2" 
  }
}

Deploy it to a function that has enough memory:

gcloud beta functions deploy screenshot --trigger-http --runtime nodejs8 --memory 1024MB

That's it! Now you have headless Chrome and Puppeteer available to use in Cloud Functions. Have fun trying out headless Chrome.

For more information, check out these resources: