DEV Community

Cover image for How to screenshot webpages in Golang
Mathias Jiya
Mathias Jiya

Posted on • Updated on

How to screenshot webpages in Golang

Hello there,
So, I've been lazy to publish an article for about a month or probably more but today is that day :).
This article is about my recent project. Wondering what that is?
Well, it is about Urlbox.
I wanted to implement a website screenshotting functionality. So, I got into googling, and at the end of it all, I came across Urlbox. Here is a little explanation as to what Urlbox is about.
Urlbox is a lightweight REST API built to automate the process of capturing website screenshots on your product.
The reason why I am so excited about this project is that Urlbox seems to be the answer to the problem I had at hand. But then, I realized that Urlbox doesn't have a Golang library. And so, just as I always do, I decided to build one. Now, you can add this functionality to your application. Well, I mean for Golang developers anyways. You should know me by now. I'm all about Golang ;).
Below are sample screenshots taken with the library:

Urlbox website Image screenshot

Iqquee github's profile Image screenshot

Youtube website image screenshot

So here's how to setup Urlbox in your Golang application:
NOTE: This Golang library supports the two ways of taking the screenshot of websites supported by Urlbox.

Installation

This package can in installed using the go command below.

go get github.com/iqquee/urlbox
Enter fullscreen mode Exit fullscreen mode

List of file formats you could use for the Format field in the Request{} struct.

const (
    //FileFormatPng for png file format
    FileFormatPng string = "png"
    //FileFormatJpeg for jpeg file format
    FileFormatJpeg string = "jpeg"
    // FileFormatAvif for avif file format
    FileFormatAvif string = "avif"
    //FileFormatWebp for webp file format
    FileFormatWebp string = "webp"
    //FileFormatWebm for webm file format
    FileFormatWebm string = "webm"
    // FileFormatPdf for pdf file format
    FileFormatPdf string = "pdf"
    //FileFormatSvg for svg file format
    FileFormatSvg string = "svg"
    // FileFormatHtml for html file format
    FileFormatHtml string = "html"
    // FileFormatMd for md file format
    FileFormatMd string = "md"
    // FileFormatMp4 for mp4 file format
    FileFormatMp4 string = "mp4"
)
Enter fullscreen mode Exit fullscreen mode

Screenshot

Screenshot takes the screenshot of a website synchronously.
Inother words, whenever you make a request using this method, you wait to get the screenshotted data([]byte) from the server.

This method takes in the Request{} struct as a parameter.

List of all the fields available in the Request{} struct.

type (
    // Request parameter for the ScreenshotAsync method
    Request struct {
        Url     string  `json:"url"`    // url of website to screenshot
        Format  string  `json:"format"` // screenshot file format
        Options Options // optional params for the request
    }
    // optional parameter
    Options struct {
        FullPage        bool // for full page screenshot
        Width           int  // the viewport width of the browser, in pixels
        Height          int // the viewport height of the browser, in pixels
        BlockingOptions Blocking // options for blocking or dismissing certain page elements, such as cookie banners
        SelectorOption  Selector // take a screenshot of the element that matches this selector. By default, if the selector is not found, Urlbox will take a normal viewport screenshot. If you prefer Urlbox to fail the request when the selector is not found, pass fail_if_selector_missing=true.
        ImageOption     Image    // options relating to the outputted PNG, WebP or JPEG file
        WaitOption      Wait // options relating to waiting before taking the screenshot 
    }
    // blocking option parameter
    Blocking struct {
        BlockAds          bool `json:"block_ads"`           // remove ads from page
        HideCookieBanners bool `json:"hide_cookie_banners"` // remove cookie banners if any
        ClickAccept       bool `json:"click_accept"`        // click accept buttons to dismiss pop-upsSelector
    }
    // selector option parameter
    Selector struct {
        Selector              string `json:"selector"`                 // for css selectors e.g #playground for id of playground
        FailIfSelectorMissing bool   `json:"fail_if_selector_missing"` // fail the request when the selector is not found
    }
    // image option parameter
    Image struct {
        Retina      bool `json:"retina"`      // take a 'retina' or high-definition screenshot, equivalent to setting a device pixel ratio of 2.0 or @2x. Please note that retina screenshots will be double the normal dimensions and will normally take slightly longer to process due to the much bigger image size.
        Quality     int  `json:"quality"`     // the image quality of the resulting screenshot (JPEG/WebP only)
        Transparent bool `json:"transparent"` // if a website has no background color set, the image will have a transparent background (PNG/WebP only)
    }

    // wait option parameter
    Wait struct {
        Delay   int // the amount of time to wait before Urlbox takes the screenshot or PDF, in milliseconds.
        TimeOut int // the amount of time to wait for the requested URL to respond, in milliseconds.
    }
)
Enter fullscreen mode Exit fullscreen mode
package main

import (
    "fmt"
    "log"
    "net/http"
    "os"
    "strings"
    "time"

    "github.com/iqquee/urlbox"
)

func main() {
    apiKey := ""
    secreteKey := ""
    client := urlbox.New(*http.DefaultClient, apiKey, secreteKey)

    request := urlbox.Request{
        Url:    "https://urlbox.io",
        Format: urlbox.FileFormatPng,
        Options: urlbox.Options{
            ImageOption: urlbox.Image{
                Retina:  true,
                Quality: 100,
            },
        },
    }

    data, err := client.Screenshot(request)
    if err != nil {
        fmt.Println("an error occured: ", err)
        return
    }

    fmt.Println("This is the response byte: ", data)

    filename := fmt.Sprintf("%s-%d.%s", strings.Replace(request.Url, "/", "-", -1), time.Now().UTC().Unix(), request.Format)

    if err := os.WriteFile(filename, data, 0666); err != nil {
        fmt.Println("error writing to disk: ", err)
        return
    }
}
Enter fullscreen mode Exit fullscreen mode

ScreenshotAsync

ScreenshotAsync allows your application to receive information when a screenshot has been rendered.
This allows you to render screenshots asynchronously.

This method takes in the RequestAsync{} struct as a parameter.

Use this object payload to implement the ScreenshotAsync() method

type RequestAsync struct {
    Url        string `json:"url"`         // url of website to screenshot
    WebhookUrl string `json:"webhook_url"` // Pass a webhook URL in as the webhook_url option and Urlbox will send a POST request back to that URL with data about the screenshot in JSON format once it has completed rendering
}
Enter fullscreen mode Exit fullscreen mode
package main

import (
    "fmt"
    "net/http"

    "github.com/iqquee/urlbox"
)

func main() {
    apiKey := ""
    secreteKey := ""
    client := urlbox.New(*http.DefaultClient, apiKey, secreteKey)

    request := urlbox.RequestAsync{
        Url:        "https://urlbox.io",
        WebhookUrl: "https://example.com/webhooks/urlbox",
    }

    message, err := client.ScreenshotAsync(request)
    if err != nil {
        fmt.Println("an error occured: ", err)
        return
    }

    fmt.Println("This is the response message: ", message)

}
Enter fullscreen mode Exit fullscreen mode

I have put in some work to make sure that this library was properly documented so that Golang developers out there can find it quite easy to use and without much stress. And as such, sample code were added for each methods.
Do have a great day ahead.

Top comments (0)