🔵 Go SDK — Quick Start

Install the SnapAPI Go module and capture your first screenshot in under a minute. Zero dependencies, idiomatic error handling, and full context support.

On This Page

Installation

Install the official SnapAPI Go module:

go get github.com/snapapi/snapapi-go

Requires Go 1.21 or later. The module has zero external dependencies.

Authentication

Get your API key from the SnapAPI dashboard and initialize the client:

package main

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

func main() {
    // Initialize with your API key
    client := snapapi.NewClient("YOUR_API_KEY")

    // Or use an environment variable (recommended)
    client := snapapi.NewClient(os.Getenv("SNAPAPI_KEY"))
}
💡 Tip: Never hardcode your API key. Use environment variables or a config file. The client is safe for concurrent use across goroutines.

Take Screenshots

Basic Screenshot

package main

import (
    "log"
    "os"

    "github.com/snapapi/snapapi-go"
)

func main() {
    client := snapapi.NewClient(os.Getenv("SNAPAPI_KEY"))

    screenshot, err := client.Screenshot(snapapi.ScreenshotOptions{
        URL:    "https://example.com",
        Format: "png",
        Width:  1280,
        Height: 800,
    })
    if err != nil {
        log.Fatal(err)
    }

    os.WriteFile("screenshot.png", screenshot, 0644)
    log.Println("Screenshot saved!")
}

Full Page Screenshot

screenshot, err := client.Screenshot(snapapi.ScreenshotOptions{
    URL:      "https://example.com",
    Format:   "png",
    FullPage: true,
    Width:    1280,
})

Screenshot with Options

screenshot, err := client.Screenshot(snapapi.ScreenshotOptions{
    URL:           "https://example.com",
    Format:        "avif",        // png, jpeg, webp, avif
    Width:         1440,
    Height:        900,
    FullPage:      false,
    BlockAds:      true,          // Block ads
    BlockCookies:  true,          // Block cookie banners
    Delay:         2000,          // Wait 2s before capture
    DevicePreset:  "iPhone15",    // Mobile device emulation
    CSS:           "body { background: white; }",
    ResponseType:  "url",         // Get hosted URL instead of binary
})

Get Hosted URL Instead of Binary

result, err := client.ScreenshotURL(snapapi.ScreenshotOptions{
    URL:    "https://example.com",
    Format: "png",
})
if err != nil {
    log.Fatal(err)
}

fmt.Println(result.URL)
// → https://cdn.snapapi.pics/screenshots/abc123.png

Generate PDFs

pdf, err := client.PDF(snapapi.PDFOptions{
    URL:             "https://example.com",
    Format:          "A4",
    PrintBackground: true,
    Margin: snapapi.Margin{
        Top:    "20mm",
        Bottom: "20mm",
        Left:   "15mm",
        Right:  "15mm",
    },
})
if err != nil {
    log.Fatal(err)
}

os.WriteFile("page.pdf", pdf, 0644)

PDF from HTML String

pdf, err := client.PDF(snapapi.PDFOptions{
    HTML:            "<h1>Invoice #1234</h1><p>Total: $99.00</p>",
    Format:          "A4",
    PrintBackground: true,
})

Extract Content

Extract clean markdown or structured data from any webpage — perfect for LLM pipelines.

content, err := client.Extract(snapapi.ExtractOptions{
    URL:    "https://example.com/blog-post",
    Format: "markdown",
})
if err != nil {
    log.Fatal(err)
}

fmt.Println(content.Markdown)
// → # Blog Post Title\n\nArticle content here...

Extract Structured Data

data, err := client.Extract(snapapi.ExtractOptions{
    URL:    "https://example.com/product",
    Format: "structured",
    Schema: map[string]string{
        "title":       "string",
        "price":       "number",
        "description": "string",
    },
})

Record Video

Record a video of a webpage loading, scrolling, or interacting with elements.

video, err := client.Video(snapapi.VideoOptions{
    URL:      "https://example.com",
    Duration: 5,          // seconds
    Width:    1280,
    Height:   720,
    Format:   "mp4",
})
if err != nil {
    log.Fatal(err)
}

os.WriteFile("recording.mp4", video, 0644)

Video with Scroll Action

video, err := client.Video(snapapi.VideoOptions{
    URL:      "https://example.com",
    Duration: 8,
    Width:    1280,
    Height:   720,
    Format:   "mp4",
    Actions: []snapapi.Action{
        {Type: "wait", Duration: 1000},
        {Type: "scroll", Y: 500},
        {Type: "wait", Duration: 2000},
        {Type: "scroll", Y: 1000},
    },
})

Error Handling

The SDK returns typed errors for common issues:

import "errors"

screenshot, err := client.Screenshot(snapapi.ScreenshotOptions{
    URL: "https://example.com",
})
if err != nil {
    var apiErr *snapapi.APIError
    if errors.As(err, &apiErr) {
        switch apiErr.StatusCode {
        case 401:
            log.Fatal("Invalid API key")
        case 429:
            log.Printf("Rate limit exceeded. Retry after: %s", apiErr.RetryAfter)
        case 400:
            log.Printf("Bad request: %s", apiErr.Message)
        default:
            log.Printf("API error %d: %s", apiErr.StatusCode, apiErr.Message)
        }
    } else {
        log.Printf("Network error: %v", err)
    }
    return
}

os.WriteFile("screenshot.png", screenshot, 0644)
⚠️ Rate Limits: Free tier allows 200 requests/month. If you hit the limit, the API returns 429 Too Many Requests with a Retry-After header. Upgrade your plan for higher limits.

Concurrent Requests

The client is goroutine-safe. Use sync.WaitGroup or errgroup to capture multiple pages concurrently.

With errgroup

import (
    "context"
    "fmt"
    "os"

    "golang.org/x/sync/errgroup"
    "github.com/snapapi/snapapi-go"
)

func main() {
    client := snapapi.NewClient(os.Getenv("SNAPAPI_KEY"))

    urls := []string{
        "https://example.com",
        "https://example.org",
        "https://example.net",
    }

    g, ctx := errgroup.WithContext(context.Background())

    for i, url := range urls {
        i, url := i, url // capture loop vars
        g.Go(func() error {
            screenshot, err := client.ScreenshotWithContext(ctx, snapapi.ScreenshotOptions{
                URL:    url,
                Format: "png",
                Width:  1280,
            })
            if err != nil {
                return fmt.Errorf("failed %s: %w", url, err)
            }
            return os.WriteFile(fmt.Sprintf("screenshot_%d.png", i), screenshot, 0644)
        })
    }

    if err := g.Wait(); err != nil {
        fmt.Println("Error:", err)
    } else {
        fmt.Println("All screenshots captured!")
    }
}

With WaitGroup and Channel

import (
    "fmt"
    "os"
    "sync"

    "github.com/snapapi/snapapi-go"
)

type Result struct {
    Index int
    Data  []byte
    Err   error
}

func main() {
    client := snapapi.NewClient(os.Getenv("SNAPAPI_KEY"))

    urls := []string{"https://example.com", "https://example.org"}
    results := make(chan Result, len(urls))
    var wg sync.WaitGroup

    for i, url := range urls {
        wg.Add(1)
        go func(i int, url string) {
            defer wg.Done()
            data, err := client.Screenshot(snapapi.ScreenshotOptions{
                URL: url, Format: "png", Width: 1280,
            })
            results <- Result{Index: i, Data: data, Err: err}
        }(i, url)
    }

    wg.Wait()
    close(results)

    for r := range results {
        if r.Err != nil {
            fmt.Printf("Error on %d: %v\n", r.Index, r.Err)
            continue
        }
        os.WriteFile(fmt.Sprintf("shot_%d.png", r.Index), r.Data, 0644)
    }
}

Context & Timeouts

All methods accept a context.Context via the WithContext variants. Use this for timeouts, cancellation, and deadline propagation.

Request Timeout

ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

screenshot, err := client.ScreenshotWithContext(ctx, snapapi.ScreenshotOptions{
    URL:    "https://example.com",
    Format: "png",
})
if err != nil {
    if errors.Is(err, context.DeadlineExceeded) {
        log.Println("Request timed out after 30s")
    } else {
        log.Fatal(err)
    }
}

Cancellation

ctx, cancel := context.WithCancel(context.Background())

// Cancel from another goroutine
go func() {
    time.Sleep(5 * time.Second)
    cancel() // abort the request
}()

screenshot, err := client.ScreenshotWithContext(ctx, snapapi.ScreenshotOptions{
    URL: "https://slow-website.com",
})
if errors.Is(err, context.Canceled) {
    log.Println("Request was cancelled")
}

HTTP Server with Request Context

func screenshotHandler(w http.ResponseWriter, r *http.Request) {
    url := r.URL.Query().Get("url")
    if url == "" {
        http.Error(w, "missing url parameter", http.StatusBadRequest)
        return
    }

    // Use the request context — auto-cancels if client disconnects
    screenshot, err := client.ScreenshotWithContext(r.Context(), snapapi.ScreenshotOptions{
        URL:    url,
        Format: "png",
        Width:  1280,
    })
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    w.Header().Set("Content-Type", "image/png")
    w.Write(screenshot)
}

Advanced Options

Custom Headers & Cookies

screenshot, err := client.Screenshot(snapapi.ScreenshotOptions{
    URL: "https://example.com/dashboard",
    Headers: map[string]string{
        "Authorization": "Bearer your-token",
        "Cookie":        "session=abc123",
    },
})

Viewport & Device Emulation

// Use a device preset
mobile, err := client.Screenshot(snapapi.ScreenshotOptions{
    URL:          "https://example.com",
    DevicePreset: "iPhone15",  // 26+ presets available
})

// Or set custom viewport
custom, err := client.Screenshot(snapapi.ScreenshotOptions{
    URL:              "https://example.com",
    Width:            375,
    Height:           812,
    DeviceScaleFactor: 3,
})

Custom HTTP Client

import "net/http"

httpClient := &http.Client{
    Timeout: 60 * time.Second,
}

client := snapapi.NewClientWithHTTP("YOUR_API_KEY", httpClient)

Next Steps