Screenshot API for Go: net/http, Goroutines & Worker Pools

Integrate SnapAPI screenshot and scraping endpoints in Go using only the standard net/http package. Concurrent batch captures with goroutines. No external dependencies.

Start Free — 200 captures/moView Docs

Screenshot API for Go — net/http and Standard Library

SnapAPI integrates with Go using only the standard net/http package. No external dependencies required — the entire integration fits in a single function that returns []byte.

Basic Screenshot in Go

package main

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

func Capture(targetURL, apiKey string) ([]byte, error) {
    params := url.Values{
        "url":       {targetURL},
        "full_page": {"true"},
        "format":    {"jpeg"},
    }
    req, err := http.NewRequest("GET",
        "https://api.snapapi.pics/v1/screenshot?"+params.Encode(), nil)
    if err != nil {
        return nil, err
    }
    req.Header.Set("X-Api-Key", apiKey)

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

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

func main() {
    data, err := Capture("https://example.com", os.Getenv("SNAPAPI_KEY"))
    if err != nil {
        panic(err)
    }
    os.WriteFile("screenshot.jpg", data, 0644)
    fmt.Printf("Captured %d bytes\n", len(data))
}

This function is safe to call from multiple goroutines because http.DefaultClient is concurrency-safe. For production use, create a custom http.Client with a timeout rather than relying on the default client which has no timeout:

client := &http.Client{Timeout: 30 * time.Second}

// Use client.Do(req) instead of http.DefaultClient.Do(req)

A 30-second timeout is appropriate for most screenshot requests. For video recording requests, extend to 120 seconds to accommodate longer render times.

Concurrent Batch Captures with Goroutines

Go's concurrency model makes batch screenshot jobs elegant. Use a worker pool pattern with a buffered channel to cap concurrent requests at a safe rate:

func CaptureAll(urls []string, apiKey string, workers int) []Result {
    jobs := make(chan string, len(urls))
    results := make(chan Result, len(urls))

    for w := 0; w < workers; w++ {
        go func() {
            for u := range jobs {
                data, err := Capture(u, apiKey)
                results <- Result{URL: u, Data: data, Err: err}
            }
        }()
    }

    for _, u := range urls {
        jobs <- u
    }
    close(jobs)

    out := make([]Result, len(urls))
    for i := range urls {
        out[i] = <-results
    }
    return out
}

Set workers to 5-10 for most plans. The worker pool pattern ensures you never exceed this concurrency ceiling regardless of input size. This is idiomatic Go concurrency and requires no third-party libraries.

Scraping and Extraction in Go

All SnapAPI endpoints are accessible from Go with the same pattern. Replace /v1/screenshot with /v1/scrape to get rendered HTML, or use /v1/extract with a POST body to extract structured data with CSS selectors:

type ExtractRequest struct {
    URL       string            `json:"url"`
    Selectors map[string]string `json:"selectors"`
}

func Extract(targetURL, apiKey string, selectors map[string]string) (map[string]interface{}, error) {
    body, _ := json.Marshal(ExtractRequest{URL: targetURL, Selectors: selectors})
    req, _ := http.NewRequest("POST", "https://api.snapapi.pics/v1/extract", bytes.NewReader(body))
    req.Header.Set("X-Api-Key", apiKey)
    req.Header.Set("Content-Type", "application/json")

    client := &http.Client{Timeout: 30 * time.Second}
    resp, err := client.Do(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    var result struct {
        Data map[string]interface{} `json:"data"`
    }
    json.NewDecoder(resp.Body).Decode(&result)
    return result.Data, nil
}

// Usage
data, _ := Extract("https://shop.example.com/product/1", apiKey, map[string]string{
    "title": "h1.product-title",
    "price": "span.price",
})
fmt.Println(data) // map[price:$29.99 title:Example Product]

Go's strong typing pairs well with SnapAPI's predictable response shapes. Define typed structs for each endpoint's request and response to get compile-time safety on all API parameters.

PDF Generation in Go

func GeneratePDF(pageURL, apiKey string) ([]byte, error) {
    params := url.Values{"url": {pageURL}, "format": {"A4"}, "print_background": {"true"}}
    req, _ := http.NewRequest("GET",
        "https://api.snapapi.pics/v1/pdf?"+params.Encode(), nil)
    req.Header.Set("X-Api-Key", apiKey)
    client := &http.Client{Timeout: 60 * time.Second}
    resp, err := client.Do(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()
    return io.ReadAll(resp.Body)
}

Extend the timeout to 60 seconds for PDF generation requests since rendering complex pages takes longer than screenshots. Stream the response body directly to an http.ResponseWriter using io.Copy to avoid buffering large PDFs in memory.

Go Error Handling and Retry

Production Go services should handle SnapAPI rate limits and transient errors with exponential backoff. The following wrapper implements retry logic using only the standard library:

func CaptureWithRetry(targetURL, apiKey string, maxRetries int) ([]byte, error) {
    client := &http.Client{Timeout: 30 * time.Second}
    params := url.Values{"url": {targetURL}, "format": {"jpeg"}}
    endpoint := "https://api.snapapi.pics/v1/screenshot?" + params.Encode()

    for attempt := 0; attempt <= maxRetries; attempt++ {
        req, _ := http.NewRequest("GET", endpoint, nil)
        req.Header.Set("X-Api-Key", apiKey)

        resp, err := client.Do(req)
        if err != nil {
            if attempt < maxRetries {
                time.Sleep(time.Duration(math.Pow(2, float64(attempt))) * time.Second)
                continue
            }
            return nil, err
        }
        defer resp.Body.Close()

        if resp.StatusCode == http.StatusOK {
            return io.ReadAll(resp.Body)
        }
        if resp.StatusCode == 429 {
            after, _ := strconv.Atoi(resp.Header.Get("Retry-After"))
            if after == 0 { after = 5 }
            time.Sleep(time.Duration(after) * time.Second)
            continue
        }
        body, _ := io.ReadAll(resp.Body)
        return nil, fmt.Errorf("snapapi %d: %s", resp.StatusCode, body)
    }
    return nil, fmt.Errorf("max retries exceeded")
}

This handles 429 by reading the Retry-After header, network errors with exponential backoff, and 4xx errors with a typed error that includes the response body for debugging. Import math, strconv, and time from the standard library — no external dependencies.

Go Use Cases and Pricing

Go developers typically use SnapAPI in microservices that generate screenshots for monitoring dashboards, PDF export services for SaaS billing systems, web scraping workers in data pipelines, and visual regression test runners in CI workflows. The zero-dependency integration is especially attractive in Go projects that value minimal module graphs.

Free: 200 captures/month. Starter $19/month: 5,000. Pro $79/month: 50,000. Business $299/month: 500,000. Sign up at snapapi.pics. SDK at github.com/Sleywill/snapapi-go. Docs at snapapi.pics/docs.html.

Go Microservice Architecture with SnapAPI

In Go microservice architectures, screenshot and scraping capabilities are natural candidates for a dedicated internal service. Define a capture service with gRPC or REST endpoints for screenshot, scrape, and PDF, backed by SnapAPI. Other internal services call this capture service rather than calling SnapAPI directly, centralizing API key management, rate limiting, and quota tracking in one place.

This pattern is especially useful in Kubernetes deployments: the capture service runs as a single deployment with its own HPA scaling policy, and API key rotation happens in one place rather than across every microservice that needs capture functionality. The capture service can also add in-memory or Redis caching, deduplicating requests for the same URL across the entire cluster.

Using the Official Go SDK

The official SnapAPI Go SDK at github.com/Sleywill/snapapi-go wraps the HTTP client with typed request and response structs, handles error parsing, and includes retry logic out of the box. Install with go get github.com/Sleywill/snapapi-go and call any endpoint with full type safety:

import "github.com/Sleywill/snapapi-go"

client := snapapi.New(os.Getenv("SNAPAPI_KEY"))

result, err := client.Screenshot(snapapi.ScreenshotRequest{
    URL:         "https://example.com",
    FullPage:    true,
    Format:      "jpeg",
    Device:      "Pixel_7",
    BlockAds:    true,
})
if err != nil {
    log.Fatal(err)
}
os.WriteFile("screenshot.jpg", result.Image, 0644)

Device Emulation in Go

SnapAPI's 30+ device presets are fully accessible from Go via the device query parameter. Common mobile presets include iPhone_15, Pixel_7, Galaxy_S23, and iPad_Air_5. This is useful for Go-based visual QA services that compare mobile and desktop renders during CI pipeline runs.

Register at snapapi.pics for 200 free captures per month, no credit card. Full Go documentation and examples at snapapi.pics/docs.html.

Streaming Screenshots in Go HTTP Handlers

For Go web services that proxy screenshot requests to clients, stream the SnapAPI response body directly to the HTTP response writer rather than buffering in memory. This reduces memory usage and time-to-first-byte for large screenshots:

func screenshotHandler(w http.ResponseWriter, r *http.Request) {
    targetURL := r.URL.Query().Get("url")
    params := url.Values{"url": {targetURL}, "format": {"jpeg"}, "quality": {"85"}}
    req, _ := http.NewRequest("GET",
        "https://api.snapapi.pics/v1/screenshot?"+params.Encode(), nil)
    req.Header.Set("X-Api-Key", os.Getenv("SNAPAPI_KEY"))

    client := &http.Client{Timeout: 30 * time.Second}
    resp, err := client.Do(req)
    if err != nil || resp.StatusCode != 200 {
        http.Error(w, "capture failed", http.StatusBadGateway)
        return
    }
    defer resp.Body.Close()

    w.Header().Set("Content-Type", "image/jpeg")
    w.Header().Set("Cache-Control", "public, max-age=3600")
    io.Copy(w, resp.Body)
}

io.Copy streams the response body without loading the entire image into memory. The Cache-Control header tells upstream CDNs and browsers to cache the screenshot for one hour, reducing repeat API calls for the same URL.

Go Screenshot API Summary

SnapAPI gives Go developers full-quality Chromium rendering without managing browser binaries or processes. The entire integration uses the standard library: net/http, net/url, io, and encoding/json. No external modules, no vendor lock-in, no binary packaging concerns. The official Go SDK at github.com/Sleywill/snapapi-go adds typed request and response structs if you prefer a more structured API surface. Sign up at snapapi.pics to start with 200 free captures per month.

golang screenshot api go http client web capture screenshot service go lang web scraping api goroutines concurrent screenshot
screenshot api golang integration example tutorial
go lang web screenshot capture api service free trial
golang http screenshot web service
go screenshot api web capture service golang
golang screenshot capture web rendering api free
go golang screenshot api concurrent web capture render goroutine http client
go screenshot api docs