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.
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.