Take a Screenshot of a Webpage with Headless Chrome

· 275 words · 2 minutes read

In this post we will look at leveraging Chrome’s debug protocol to load up a webpage and take a screenshot. This is all made possible from a package called chromedp which allows us to control a Chrome instance through our Go code. You will also need Chrome installed or to be using something akin to the chrome/headless-shell docker image.

We’ve split the process in code up into:

  • Start Chrome
  • Run tasks: like loading the webpage and taking a screenshot
  • Saving the screenshot to file
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package main

import (
	"context"
	"io/ioutil"
	"log"

	"github.com/chromedp/cdproto/page"
	"github.com/chromedp/chromedp"
)

func main() {

	// Start Chrome
	// Remove the 2nd param if you don't need debug information logged
	ctx, cancel := chromedp.NewContext(context.Background(), chromedp.WithDebugf(log.Printf))
	defer cancel()

	url := "https://golangcode.com/"
	filename := "golangcode.png"

	// Run Tasks
	// List of actions to run in sequence (which also fills our image buffer)
	var imageBuf []byte
	if err := chromedp.Run(ctx, ScreenshotTasks(url, &imageBuf)); err != nil {
		log.Fatal(err)
	}

	// Write our image to file
	if err := ioutil.WriteFile(filename, imageBuf, 0644); err != nil {
		log.Fatal(err)
	}
}

func ScreenshotTasks(url string, imageBuf *[]byte) chromedp.Tasks {
	return chromedp.Tasks{
		chromedp.Navigate(url),
		chromedp.ActionFunc(func(ctx context.Context) (err error) {
			*imageBuf, err = page.CaptureScreenshot().WithQuality(90).Do(ctx)
			return err
		}),
	}
}

take screenshot with headless chrome

As an added bonus, if you wanted to save the page as a pdf instead of an image, you can replace the CaptureScreenshot line with following:

1
*imageBuf, _, err = page.PrintToPDF().WithPrintBackground(false).Do(ctx)

Image of Author Edd Turtle

Author:  Edd Turtle

Edd is the Lead Developer at Hoowla, a prop-tech startup, where he spends much of his time working on production-ready Go and PHP code. He loves coding, but also enjoys cycling and camping in his spare time.

See something which isn't right? You can contribute to this page on GitHub or just let us know in the comments below - Thanks for reading!