ScreenshotAPI

Go

Use ScreenshotAPI from Go with the standard library net/http package.

Overview

These examples use Go's standard library — no external dependencies required.

Quick Start

Set your API key

export SCREENSHOTAPI_KEY="sk_live_your_key_here"

Take a screenshot

package main

import (
	"fmt"
	"io"
	"net/http"
	"net/url"
	"os"
)

func main() {
	apiKey := os.Getenv("SCREENSHOTAPI_KEY")

	params := url.Values{}
	params.Set("url", "https://example.com")

	req, err := http.NewRequest("GET",
		"https://screenshotapi.to/api/v1/screenshot?"+params.Encode(), nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("x-api-key", apiKey)

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		body, _ := io.ReadAll(resp.Body)
		fmt.Fprintf(os.Stderr, "Error %d: %s\n", resp.StatusCode, body)
		os.Exit(1)
	}

	file, err := os.Create("screenshot.png")
	if err != nil {
		panic(err)
	}
	defer file.Close()

	io.Copy(file, resp.Body)
	fmt.Printf("Credits remaining: %s\n", resp.Header.Get("x-credits-remaining"))
}

Client Package

A reusable client with all screenshot options:

package screenshot

import (
	"fmt"
	"io"
	"net/http"
	"net/url"
	"strconv"
)

type ImageFormat string

const (
	PNG  ImageFormat = "png"
	JPEG ImageFormat = "jpeg"
	WebP ImageFormat = "webp"
)

type Options struct {
	URL             string
	Width           int
	Height          int
	FullPage        bool
	Format          ImageFormat
	Quality         int
	ColorScheme     string // "light" or "dark"
	WaitUntil       string
	WaitForSelector string
	Delay           int
}

type Result struct {
	Body             io.ReadCloser
	ContentType      string
	CreditsRemaining int
	ScreenshotID     string
	DurationMs       int
}

type Client struct {
	apiKey  string
	baseURL string
	http    *http.Client
}

func NewClient(apiKey string) *Client {
	return &Client{
		apiKey:  apiKey,
		baseURL: "https://screenshotapi.to",
		http:    &http.Client{},
	}
}

func (c *Client) Capture(opts Options) (*Result, error) {
	params := url.Values{}
	params.Set("url", opts.URL)

	if opts.Width > 0 {
		params.Set("width", strconv.Itoa(opts.Width))
	}
	if opts.Height > 0 {
		params.Set("height", strconv.Itoa(opts.Height))
	}
	if opts.FullPage {
		params.Set("fullPage", "true")
	}
	if opts.Format != "" {
		params.Set("type", string(opts.Format))
	}
	if opts.Quality > 0 {
		params.Set("quality", strconv.Itoa(opts.Quality))
	}
	if opts.ColorScheme != "" {
		params.Set("colorScheme", opts.ColorScheme)
	}
	if opts.WaitUntil != "" {
		params.Set("waitUntil", opts.WaitUntil)
	}
	if opts.WaitForSelector != "" {
		params.Set("waitForSelector", opts.WaitForSelector)
	}
	if opts.Delay > 0 {
		params.Set("delay", strconv.Itoa(opts.Delay))
	}

	req, err := http.NewRequest("GET",
		c.baseURL+"/api/v1/screenshot?"+params.Encode(), nil)
	if err != nil {
		return nil, fmt.Errorf("creating request: %w", err)
	}
	req.Header.Set("x-api-key", c.apiKey)

	resp, err := c.http.Do(req)
	if err != nil {
		return nil, fmt.Errorf("executing request: %w", err)
	}

	if resp.StatusCode != http.StatusOK {
		body, _ := io.ReadAll(resp.Body)
		resp.Body.Close()
		return nil, fmt.Errorf("API error %d: %s", resp.StatusCode, body)
	}

	credits, _ := strconv.Atoi(resp.Header.Get("x-credits-remaining"))
	duration, _ := strconv.Atoi(resp.Header.Get("x-duration-ms"))

	return &Result{
		Body:             resp.Body,
		ContentType:      resp.Header.Get("Content-Type"),
		CreditsRemaining: credits,
		ScreenshotID:     resp.Header.Get("x-screenshot-id"),
		DurationMs:       duration,
	}, nil
}

Usage

package main

import (
	"io"
	"log"
	"os"

	"yourpackage/screenshot"
)

func main() {
	client := screenshot.NewClient(os.Getenv("SCREENSHOTAPI_KEY"))

	result, err := client.Capture(screenshot.Options{
		URL:     "https://github.com",
		Width:   1280,
		Height:  720,
		Format:  screenshot.WebP,
		Quality: 85,
	})
	if err != nil {
		log.Fatal(err)
	}
	defer result.Body.Close()

	file, err := os.Create("github.webp")
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()

	io.Copy(file, result.Body)
	log.Printf("Credits remaining: %d", result.CreditsRemaining)
	log.Printf("Duration: %dms", result.DurationMs)
}

Common Patterns

Concurrent Screenshots

Capture multiple URLs concurrently with goroutines:

package main

import (
	"fmt"
	"io"
	"os"
	"sync"

	"yourpackage/screenshot"
)

func main() {
	client := screenshot.NewClient(os.Getenv("SCREENSHOTAPI_KEY"))

	urls := []string{
		"https://example.com",
		"https://github.com",
		"https://news.ycombinator.com",
	}

	var wg sync.WaitGroup
	for i, url := range urls {
		wg.Add(1)
		go func(idx int, u string) {
			defer wg.Done()

			result, err := client.Capture(screenshot.Options{URL: u})
			if err != nil {
				fmt.Fprintf(os.Stderr, "✗ %s: %v\n", u, err)
				return
			}
			defer result.Body.Close()

			filename := fmt.Sprintf("screenshot-%d.png", idx)
			file, err := os.Create(filename)
			if err != nil {
				fmt.Fprintf(os.Stderr, "✗ %s: %v\n", u, err)
				return
			}
			defer file.Close()

			io.Copy(file, result.Body)
			fmt.Printf("✓ %s%s\n", u, filename)
		}(i, url)
	}

	wg.Wait()
}

HTTP Handler

Serve screenshots in a Go HTTP server:

func screenshotHandler(w http.ResponseWriter, r *http.Request) {
	targetURL := r.URL.Query().Get("url")
	if targetURL == "" {
		http.Error(w, `{"error":"url is required"}`, http.StatusBadRequest)
		return
	}

	result, err := client.Capture(screenshot.Options{
		URL:     targetURL,
		Format:  screenshot.WebP,
		Quality: 80,
	})
	if err != nil {
		http.Error(w, `{"error":"screenshot failed"}`, http.StatusBadGateway)
		return
	}
	defer result.Body.Close()

	w.Header().Set("Content-Type", result.ContentType)
	w.Header().Set("Cache-Control", "public, max-age=3600")
	io.Copy(w, result.Body)
}

Error Handling

result, err := client.Capture(screenshot.Options{URL: "https://example.com"})
if err != nil {
	// err.Error() contains the status code and error body
	// e.g., "API error 402: {"error":"Insufficient credits"}"
	log.Printf("Screenshot failed: %v", err)
	return
}
defer result.Body.Close()

On this page