How to Screenshot a Website Using Go
Go is a strong fit for screenshot automation because the standard library already handles the HTTP and file work cleanly. If your app needs thumbnails, QA evidence, documentation images, or scheduled page archives, you can call a screenshot API from Go and treat the result like any other binary download.
1. Use net/http to make the API request
The Go documentation for net/http shows the pattern: create a request when you need headers, client settings, and response handling. Build the screenshot URL with query parameters, reuse an http.Client, and set a timeout so a slow render cannot tie up a worker forever.
package main
import (
"fmt"
"io"
"net/http"
"net/url"
"os"
"time"
)
func main() {
endpoint, _ := url.Parse("https://framesnap.dev/v1/screenshot")
q := endpoint.Query()
q.Set("url", "https://example.com")
q.Set("format", "png")
q.Set("full_page", "true")
q.Set("viewport_width", "1440")
q.Set("viewport_height", "900")
endpoint.RawQuery = q.Encode()
req, err := http.NewRequest("GET", endpoint.String(), nil)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("FRAMESNAP_API_KEY"))
client := &http.Client{Timeout: 45 * time.Second}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
body, _ := io.ReadAll(resp.Body)
panic(fmt.Sprintf("screenshot failed: %s: %s", resp.Status, body))
}
out, err := os.Create("screenshot.png")
if err != nil {
panic(err)
}
defer out.Close()
if _, err := io.Copy(out, resp.Body); err != nil {
panic(err)
}
}
2. Set Authorization header with your API key
Keep the API key outside source control. Load it from an environment variable locally and from a secret manager in production. FrameSnap accepts the standard bearer-token pattern, so the Go client only needs one header: Authorization: Bearer fs_your_key.
FrameSnap's API docs and free tool are useful for testing parameters before you commit them to Go. Once the URL, viewport, full-page setting, and output format look right, copy those choices into your request builder.
3. Handle the response body as image data
The response body is binary image data, not JSON. The Go io package gives you two practical options. Use io.Copy to stream directly to a file or cloud object. Use io.ReadAll when you need bytes in memory for hashing, uploads, or further processing.
For larger PDF or full-page captures, streaming is safer. Always close resp.Body, and inspect non-2xx responses before saving the output. Otherwise an error page can quietly become a file named screenshot.png, which is funny exactly once.
4. Save to file or process as needed in your Go app
os.Create plus io.Copy is enough for a local file. For server workflows, replace the file writer with any io.Writer: object storage, a buffer, a multipart attachment, or a test artifact writer. The screenshot call stays ordinary HTTP, so your app can store the result with the same patterns it already uses for generated media.
Use FrameSnap when you want browser rendering handled outside your Go service. You still control the timeout, output format, viewport, and downstream processing, but you do not have to operate headless Chrome in every deployment. Get a FrameSnap API key or try the free screenshot tool before wiring the capture into Go.
FAQ
Can Go take website screenshots without running Chrome locally?
Yes. Your Go app can call a hosted screenshot API over HTTP, then save or process the returned image bytes.
Should I use io.Copy or io.ReadAll for screenshot responses?
Use io.Copy for files or storage writers. Use io.ReadAll when the app needs the complete image in memory.
How do I authenticate a screenshot API request in Go?
Create an http.Request and set Authorization to Bearer plus your API key. Load the key from an environment variable or secret manager.
What output formats can I request from FrameSnap?
FrameSnap supports PNG, JPEG, and PDF, with controls for full-page capture, viewport size, retina output, dark mode, and more.
Capture Screenshots with FrameSnap
One API call. PNG, JPEG, or PDF. Free tier included.