Capture website screenshots in Go using only the standard library. No chromedp, no CGo, no Chrome dependency. Pure HTTP.
Get Free API Key →package main
import (
"fmt"
"io"
"net/http"
"net/url"
"os"
)
func main() {
params := url.Values{}
params.Set("url", "https://example.com")
params.Set("key", os.Getenv("GRABSHOT_API_KEY"))
resp, err := http.Get("https://grabshot.dev/v1/screenshot?" + params.Encode())
if err != nil {
fmt.Fprintf(os.Stderr, "request failed: %v\n", err)
os.Exit(1)
}
defer resp.Body.Close()
f, _ := os.Create("screenshot.png")
defer f.Close()
io.Copy(f, resp.Body)
fmt.Println("Saved screenshot.png")
}
package grabshot
import (
"fmt"
"io"
"net/http"
"net/url"
"time"
)
type Client struct {
APIKey string
HTTP *http.Client
}
type Options struct {
Width string
Height string
Format string
FullPage bool
DarkMode bool
DeviceFrame string
}
func NewClient(apiKey string) *Client {
return &Client{
APIKey: apiKey,
HTTP: &http.Client{Timeout: 30 * time.Second},
}
}
func (c *Client) Capture(targetURL string, opts *Options) ([]byte, error) {
params := url.Values{}
params.Set("url", targetURL)
params.Set("key", c.APIKey)
if opts != nil {
if opts.Width != "" { params.Set("width", opts.Width) }
if opts.Height != "" { params.Set("height", opts.Height) }
if opts.Format != "" { params.Set("format", opts.Format) }
if opts.FullPage { params.Set("fullPage", "true") }
if opts.DarkMode { params.Set("darkMode", "true") }
if opts.DeviceFrame != "" { params.Set("deviceFrame", opts.DeviceFrame) }
}
resp, err := c.HTTP.Get("https://grabshot.dev/v1/screenshot?" + params.Encode())
if err != nil {
return nil, fmt.Errorf("request failed: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
body, _ := io.ReadAll(resp.Body)
return nil, fmt.Errorf("API error %d: %s", resp.StatusCode, body)
}
return io.ReadAll(resp.Body)
}
// Usage:
// client := grabshot.NewClient(os.Getenv("GRABSHOT_API_KEY"))
// img, err := client.Capture("https://github.com", &grabshot.Options{
// Width: "1920", FullPage: true, DeviceFrame: "macbook",
// })
import "github.com/gin-gonic/gin"
func screenshotHandler(c *gin.Context) {
targetURL := c.Query("url")
if targetURL == "" {
c.JSON(400, gin.H{"error": "url required"})
return
}
client := NewClient(os.Getenv("GRABSHOT_API_KEY"))
img, err := client.Capture(targetURL, nil)
if err != nil {
c.JSON(500, gin.H{"error": err.Error()})
return
}
c.Data(200, "image/png", img)
}
Free: 25 screenshots/month. No credit card.
Starter: $9/mo for 2,500 screenshots.
Pro: $29/mo for 10,000 screenshots with AI cleanup.
Start Free — No Credit Card →