Go SDK

The official Go SDK for RenderScreenshot. Zero external dependencies.

Installation

go get github.com/Render-Screenshot/rs-go

Requirements

  • Go 1.21 or higher

Quick Start

package main

import (
    "context"
    "os"

    rs "github.com/Render-Screenshot/rs-go"
)

func main() {
    client, _ := rs.New("rs_live_xxxxx")

    // Take a screenshot
    image, _ := client.Take(context.Background(),
        rs.URL("https://example.com").Preset("og_card"),
    )

    os.WriteFile("screenshot.png", image, 0644)
}

Client

Constructor

import rs "github.com/Render-Screenshot/rs-go"

client, err := rs.New(apiKey, opts...)
Parameter Type Description
apiKey string Your API key (rs_live_* or rs_test_*)
WithBaseURL(url) Option API base URL (default: https://api.renderscreenshot.com)
WithTimeout(d) Option Request timeout (default: 30s)
WithMaxRetries(n) Option Max retries for retryable errors (default: 0)
WithRetryDelay(d) Option Base delay between retries in seconds (default: 1.0)
WithSigningKey(key) Option Secret key for signed URLs (rs_secret_*)
WithPublicKeyID(id) Option Public key ID for signed URLs (rs_pub_*)

Methods

Take(ctx, options)

Take a screenshot and return binary data.

image, err := client.Take(ctx,
    rs.URL("https://example.com").Preset("og_card"),
)

os.WriteFile("screenshot.png", image, 0644)

Returns: ([]byte, error)

TakeJSON(ctx, options)

Take a screenshot and return JSON metadata.

resp, err := client.TakeJSON(ctx,
    rs.URL("https://example.com").Preset("og_card"),
)

fmt.Println(resp.Image.URL)    // CDN URL
fmt.Println(resp.Image.Width)  // 1200
fmt.Println(resp.Image.Height) // 630
fmt.Println(resp.Cache.Hit)    // true/false

Returns: (*ScreenshotResponse, error)

GenerateURL(options, expiresAt, signingKey, publicKeyID)

Generate a signed URL for public embedding.

signedURL, err := client.GenerateURL(
    rs.URL("https://example.com").Preset("og_card"),
    time.Now().Add(24 * time.Hour), // 24 hours
    "", "",                          // use client-configured keys
)

// Use in HTML: <img src="signedURL" />

Returns: (string, error)

Batch(ctx, urls, options) / BatchAdvanced(ctx, requests)

Process multiple screenshots in a batch.

// Simple batch
resp, err := client.Batch(ctx,
    []string{"https://example1.com", "https://example2.com"},
    rs.URL("").Preset("og_card"),
)

// Advanced batch with per-URL options
resp, err = client.BatchAdvanced(ctx, []rs.BatchRequest{
    {URL: "https://example1.com", Options: rs.URL("").Preset("og_card")},
    {URL: "https://example2.com", Options: rs.URL("").Width(1920)},
})

Returns: (*BatchResponse, error)

GetBatch(ctx, batchID)

Get the status of a batch job.

status, err := client.GetBatch(ctx, "batch_abc123")
fmt.Printf("%d/%d\n", status.Completed, status.Total)

Returns: (*BatchResponse, error)

Presets(ctx) / Preset(ctx, id)

Get available presets.

presets, err := client.Presets(ctx)
ogCard, err := client.Preset(ctx, "og_card")

Devices(ctx)

Get available device presets.

devices, err := client.Devices(ctx)

TakeOptions

Mutable fluent builder for screenshot options. All setter methods return the same pointer for chaining.

Creating Options

import rs "github.com/Render-Screenshot/rs-go"

// From URL
options := rs.URL("https://example.com")

// From HTML
options := rs.HTML("<h1>Hello World</h1>")

// From config map
options := rs.FromConfig(map[string]interface{}{"url": "...", "width": 1200})

Viewport Options

rs.URL("...").
    Width(1200).           // Viewport width
    Height(630).           // Viewport height
    Scale(2).              // Device scale factor (1-3)
    Mobile()               // Enable mobile emulation

Capture Options

rs.URL("...").
    FullPage().            // Capture full scrollable page
    Element(".hero").      // Capture specific element
    Format(rs.FormatPNG).  // FormatPNG, FormatJPEG, FormatWebP, FormatPDF
    Quality(90)            // JPEG/WebP quality (1-100)

Wait Options

rs.URL("...").
    WaitFor(rs.WaitNetworkIdle).   // WaitLoad, WaitNetworkIdle, WaitDOMContentLoaded
    Delay(2000).                   // Additional delay (ms)
    WaitForSelector(".loaded").    // Wait for selector
    WaitForTimeout(30000)          // Max wait time (ms)

Presets & Devices

rs.URL("...").
    Preset("og_card").             // Use a preset
    Device("iphone_14_pro")        // Emulate a device

Content Blocking

rs.URL("...").
    BlockAds().                    // Block ad networks
    BlockTrackers().               // Block analytics
    BlockCookieBanners().          // Auto-dismiss cookie popups
    BlockChatWidgets().            // Block chat widgets
    BlockURLs([]string{"*.ads.com/*"}).   // Block URL patterns
    BlockResources([]string{"font"})      // Block resource types

Browser Emulation

rs.URL("...").
    DarkMode().                    // Enable dark mode
    ReducedMotion().               // Prefer reduced motion
    SetMediaType(rs.MediaPrint).   // MediaScreen or MediaPrint
    UserAgent("Custom UA").        // Custom user agent
    Timezone("America/New_York").
    Locale("en-US").
    SetGeolocation(40.7128, -74.006)

Network Options

rs.URL("...").
    Headers(map[string]string{"X-Custom": "value"}).
    Cookies([]rs.Cookie{{Name: "session", Value: "abc", Domain: "example.com"}}).
    AuthBasic("user", "pass").
    AuthBearer("token").
    BypassCSP()

Cache Options

rs.URL("...").
    CacheTTL(86400).               // Cache TTL in seconds
    CacheRefresh()                 // Force refresh

PDF Options

rs.URL("...").
    Format(rs.FormatPDF).
    PDFPaperSize(rs.PaperA4).     // PaperA4, PaperLetter, PaperLegal, etc.
    PDFLandscape().
    PDFMarginUniform("1in").
    PDFPrintBackground().
    PDFHeader("<div>Header</div>").
    PDFFooter("<div>Page</div>")

Storage Options (BYOS)

rs.URL("...").
    StorageEnabled().
    StoragePath("{year}/{month}/{hash}.{ext}").
    StorageACL(rs.ACLPublicRead)

Cache Management

cache := client.Cache()

// Get cached screenshot
image, err := cache.Get(ctx, "cache_xyz789")

// Delete single entry
deleted, err := cache.Delete(ctx, "cache_xyz789")

// Bulk purge by keys
result, err := cache.Purge(ctx, []string{"cache_abc", "cache_def"})
fmt.Println("Purged:", result.Purged)

// Purge by URL pattern
result, err = cache.PurgeURL(ctx, "https://mysite.com/blog/*")

// Purge by storage path pattern
result, err = cache.PurgePattern(ctx, "screenshots/2024/*")

// Purge by date
result, err = cache.PurgeBefore(ctx, time.Now().Add(-7 * 24 * time.Hour))

Webhook Helpers

import rs "github.com/Render-Screenshot/rs-go"

// Extract headers (case-insensitive)
headers := rs.ExtractWebhookHeaders(map[string]string{
    "X-Webhook-Signature": r.Header.Get("X-Webhook-Signature"),
    "X-Webhook-Timestamp": r.Header.Get("X-Webhook-Timestamp"),
    "X-Webhook-ID":        r.Header.Get("X-Webhook-ID"),
})

// Verify signature
isValid := rs.VerifyWebhook(payload, headers.Signature, headers.Timestamp,
    os.Getenv("WEBHOOK_SECRET"), rs.DefaultTolerance)

// Parse event
event, err := rs.ParseWebhook(payload)
if event.Event == "screenshot.completed" {
    fmt.Println(event.Data)
}

Error Handling

import rs "github.com/Render-Screenshot/rs-go"

image, err := client.Take(ctx, rs.URL("..."))
if err != nil {
    var apiErr *rs.Error
    if errors.As(err, &apiErr) {
        fmt.Println(apiErr.HTTPStatus)  // 400, 429, etc.
        fmt.Println(apiErr.Code)        // "invalid_url", "rate_limited"
        fmt.Println(apiErr.Message)     // Human-readable message
        fmt.Println(apiErr.IsRetryable()) // true/false
        fmt.Println(apiErr.RetryAfter)  // Seconds (for rate limits)
    }
}

// Helper functions
if rs.IsNotFound(err)       { /* 404 */ }
if rs.IsRetryable(err)      { /* transient error */ }
if rs.IsRateLimited(err)    { /* 429 */ }
if rs.IsAuthentication(err) { /* 401 */ }
if rs.IsValidation(err)     { /* 400/422 */ }

Error Codes

Code HTTP Retryable Description
invalid_request 400 No Malformed request
invalid_url 400 No Invalid URL provided
unauthorized 401 No Invalid API key
forbidden 403 No Access denied
not_found 404 No Resource not found
rate_limited 429 Yes Rate limit exceeded
timeout 408 Yes Screenshot timed out
render_failed 500 Yes Browser rendering failed
internal_error 500 Yes Internal server error

Was this page helpful?