How to take website screenshots with Go
Tags: go, playwright
Published: 2022-06-01 15:20:50

Today, there are many options to make screenshots of any URL with Go:

1. Selenium WebDriver client for Go.
  
2. You can use the Go analog of Puppeteer.
  
3. Playwright library.
  
4. Or Screenshot API as a service.
  

They might overlap, but there is no best solution. Each depends on your use case and requirements.

## Selenium WebDriver client for Go

Selenium is a well-known kid in the QA automation area, so it is easy to start taking screenshots if you plan to write automation tests or already do it.

Install [Selenium WebDriver client for Go](https://github.com/tebeka/selenium) into your project:

```go
go get github.com/tebeka/selenium
```

Download the latest version [ChromeDriver](https://sites.google.com/chromium.org/driver/) and the latest [remote Selenium WebDriver standalone server](https://selenium-release.storage.googleapis.com/index.html), place them in the same source directory, and you are ready to Go:

```go
package main

import (
	"fmt"
	"os"

	"github.com/tebeka/selenium"
)

func main() {
	const (
		seleniumPath     = "./selenium-server-standalone-3.5.3.jar"
		chromeDriverPath = "./chromedriver"
		port             = 8080
	)
	opts := []selenium.ServiceOption{
		selenium.ChromeDriver(chromeDriverPath),
		selenium.Output(os.Stderr),
	}
	selenium.SetDebug(true)
	service, err := selenium.NewSeleniumService(seleniumPath, port, opts...)
	if err != nil {
		panic(err) // panic is used only as an example and is not otherwise recommended
	}
	defer service.Stop()

	// connect to the WebDriver instance running locally
	caps := selenium.Capabilities{"browserName": "chrome"}
	wd, err := selenium.NewRemote(caps, fmt.Sprintf("http://localhost:%d/wd/hub", port))
	if err != nil {
		panic(err)
	}
	defer wd.Quit()

	if err := wd.Get("https://scalabledeveloper.com"); err != nil {
		panic(err)
	}

	screenshot, err := wd.Screenshot()
	if err != nil {
		panic(err)
	}

	out, err := os.Create("scalabledeveloper.jpg")
	if err != nil {
		panic(err)
	}
	defer out.Close()

	_, err = out.Write(screenshot)
	if err != nil {
		panic(err)
	}
}
```

If you just want to take one or two screenshots locally, the Selenium WebDriver client is not the best fit. As I wrote earlier, it better serves you already write automation tests with Selenium or plan to write them.

## Go analog of Puppeteer

[chromedp](https://github.com/chromedp/chromedp) is the closest analog to [Node.js Puppeteer](https://screenshotone.com/blog/how-to-take-a-screenshot-with-puppeteer/) in Go, a faster, more straightforward way to drive browsers supporting the [Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/) in Go without external dependencies.

While you can also use `chromedp` for automation testing, it is much light weighter and simpler than Selenium and allows any automation over the browser. Everything you can do manually with a browser, you can also do with `chromedp`.

And it is super easy to use:

```shell
go get github.com/chromedp/chromedp
```

And then just:

```go
func main() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	var buf []byte
	if err := chromedp.Run(ctx,
		chromedp.Navigate(`https://example.com`),
		chromedp.FullScreenshot(&buf, 95),
	); err != nil {
		log.Fatal(err)
	}

	if err := ioutil.WriteFile("example.jpg", buf, 0644); err != nil {
		log.Fatal(err)
	}
}
```

It is very lightweight compared to Selenium and allows a broad spectrum for automation of the browser. You can use it for crawling, scrapping, taking screenshots, etc.
If you need the simplest way to take screenshots, you do not expect to take millions of them, and I would go with `chromedp`. But if you want to take screenshots from different browsers or think about managing instances of browsers, there is a more straightforward way to go.

## Playwright

[Playwright](https://github.com/playwright-community/playwright-go) is the best Go library to automate [Chromium](https://www.chromium.org/Home), [Firefox](https://www.mozilla.org/en-US/firefox/new/), and [WebKit](https://webkit.org/) with a unified API. It is built to enable cross-browser web automation.

If you want to take screenshots in different browsers, Playwright is the best choice.

Install the library with `go get`:

```shell
go get github.com/playwright-community/playwright-go
```

Do not forget to install browser and OS dependencies:

```shell
go run github.com/playwright-community/playwright-go/cmd/playwright install --with-deps
```

And then take a screenshot:

```go
package main

import (
	"log"

	"github.com/playwright-community/playwright-go"
)

func main() {
	pw, err := playwright.Run()
	if err != nil {
		log.Fatalf("could not launch playwright: %v", err)
	}
	browser, err := pw.Chromium.Launch()
	if err != nil {
		log.Fatalf("could not launch Chromium: %v", err)
	}
	page, err := browser.NewPage()
	if err != nil {
		log.Fatalf("could not create page: %v", err)
	}
	if _, err = page.Goto("https://example.com/", playwright.PageGotoOptions{
		WaitUntil: playwright.WaitUntilStateNetworkidle,
	}); err != nil {
		log.Fatalf("could not goto: %v", err)
	}
	if _, err = page.Screenshot(playwright.PageScreenshotOptions{
		Path: playwright.String("example.png"),
	}); err != nil {
		log.Fatalf("could not create screenshot: %v", err)
	}
	if err = browser.Close(); err != nil {
		log.Fatalf("could not close browser: %v", err)
	}
	if err = pw.Stop(); err != nil {
		log.Fatalf("could not stop Playwright: %v", err)
	}
}
```

`Playwright` is the best choice. It is as powerful as `chromedp` but allows you to run different browser instances if needed.
If you plan to take millions of screenshots and manage browser instances, you can do it yourself, but it is better to outsource to well-established services.

## Screenshot API as a service

I specialize in taking screenshots and managing browser instances at scale. I provide a high-quality Go client to screenshots and cover a variety of use cases.

Easy to install:

```shell
go get github.com/screenshotone/gosdk
```

And easy to use:

```go
client, err := screenshots.NewClient("IVmt2ghj9TG_jQ", "Sxt94yAj9aQSgg")
if err != nil {
    // ...
}

options := screenshots.NewTakeOptions("https://example.com").
    Format("png").
    FullPage(true).
    DeviceScaleFactor(2).
    BlockAds(true).
    BlockTrackers(true)

image, _, err := client.Take(context.TODO(), options)
if err != nil {
    // ...
}

out, err := os.Create("example.png")
if err != nil {
    // ...
}
defer out.Close()

_, err = out.Write(out, image)
if err != nil {
    // ...
}
```

If you feel that it is the best fit for you, feel free [to sign up for our screenshot API](https://screenshotone.com/) and get the access key.

## Summary

Pick the solution which suits your needs best. And have a nice day 👋