Using Go and chromedp to Control Headless Chrome for Screenshots, PDF Export, and Device Emulation
This article demonstrates how to use the Go programming language together with the chromedp library to drive a headless Chrome instance for web page screenshots, PDF generation, full‑page capture, and device emulation, providing complete code examples and deployment tips.
The author was inspired by a 360 technology article about server‑side browser screenshots using Selenium and wanted to achieve the same functionality with Go. After researching, they found that Go is a suitable choice for headless browser automation.
Traditional Selenium/PhantomJS approaches require installing multiple components (Selenium, ChromeDriver, PhantomJS) and have version‑matching issues. By contrast, a Go‑based solution using only Chrome as the runtime simplifies the environment to just a Chrome browser.
Headless Browser refers to a browser without a UI that can still fetch HTML, execute JavaScript, render pages, and retrieve cookies. The article focuses on headless Chrome.
Main framework : The author selected the chromedp library because it provides a fast, simple way to drive Chrome via the Chrome DevTools Protocol (CDP), offers rich low‑level APIs, flexible high‑level actions similar to Selenium, has no external dependencies, and benefits from Go’s single‑binary compilation.
Installation
go get -u github.com/chromedp/chromedpScreenshot implementation
package main
import (
"context"
"io/ioutil"
"log"
cdp "github.com/chromedp/chromedp"
)
func main() {
ctx, cancel := cdp.NewContext(context.Background())
defer cancel()
urlstr := `https://www.so.com/`
var buf []byte
selector := `#main`
if err := cdp.Run(ctx, elementScreenshot(urlstr, selector, &buf)); err != nil {
log.Fatal(err)
}
if err := ioutil.WriteFile("360_so.png", buf, 0644); err != nil {
log.Fatal(err)
}
}
func elementScreenshot(urlstr, sel string, res *[]byte) cdp.Tasks {
return cdp.Tasks{
cdp.Navigate(urlstr),
cdp.WaitVisible(sel, cdp.ByID),
cdp.Screenshot(sel, res, cdp.NodeVisible, cdp.ByID),
}
}The resulting PNG shows a screenshot of the target element.
PDF export
// Export specified element as PDF
func elementPDFPrint(urlstr, sel string, res *[]byte) cdp.Tasks {
var err error
return cdp.Tasks{
cdp.Navigate(urlstr),
cdp.Sleep(time.Duration(5) * time.Second),
cdp.ActionFunc(func(ctx context.Context) error {
*res, _, err = page.PrintToPDF().Do(ctx)
if err != nil {
return err
}
return nil
}),
}
}The article also shows how to capture a full‑page screenshot by adjusting device metrics and using page.CaptureScreenshot with a calculated viewport.
func fullScreenshot(urlstr string, quality int64, res *[]byte) cdp.Tasks {
return cdp.Tasks{
cdp.Navigate(urlstr),
cdp.ActionFunc(func(ctx context.Context) error {
_, _, contentSize, err := page.GetLayoutMetrics().Do(ctx)
if err != nil { return err }
width, height := int64(math.Ceil(contentSize.Width)), int64(math.Ceil(contentSize.Height))
if err = emulation.SetDeviceMetricsOverride(width, height, 1, false).
WithScreenOrientation(&emulation.ScreenOrientation{Type: emulation.OrientationTypePortraitPrimary, Angle: 0}).Do(ctx); err != nil {
return err
}
*res, err = page.CaptureScreenshot().WithQuality(quality).
WithClip(&page.Viewport{X: contentSize.X, Y: contentSize.Y, Width: contentSize.Width, Height: contentSize.Height, Scale: 1}).Do(ctx)
return err
}),
}
}Device emulation is also supported; the following code emulates an iPhone 7 and captures a screenshot of the user‑agent page.
func main() {
ctx, cancel := cdp.NewContext(context.Background())
defer cancel()
var b []byte
if err := cdp.Run(ctx,
cdp.Emulate(device.IPhone7landscape),
cdp.Navigate(`https://www.whatsmyua.info/`),
cdp.CaptureScreenshot(&b),
); err != nil { log.Fatal(err) }
if err := ioutil.WriteFile("iphone7_ua.png", b, 0644); err != nil { log.Fatal(err) }
}All examples together demonstrate that with less than 40 lines of Go code you can perform server‑side screenshot, PDF export, full‑page capture, and device emulation without any external tools besides Chrome.
Conclusion Using Go and chromedp leverages Chrome’s CDP interface to achieve almost any browser operation in a headless environment, making it ideal for building reusable screenshot/PDF services, automated testing platforms, and other backend automation tasks.
360 Tech Engineering
Official tech channel of 360, building the most professional technology aggregation platform for the brand.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.