Features Pricing Docs Blog Playground Log In Sign Up

SDKs & Libraries

Integrate ScreenshotAPI into your application using the language or framework of your choice. Below you'll find complete, production-ready examples for popular platforms.

PHP

Laravel / PHP (with Guzzle)

Create a reusable service class for your Laravel application:

php
namespace App\Services;

use Illuminate\Support\Facades\Http;

class ScreenshotApiClient
{
    private string $baseUrl = 'https://screenshotrun.com/api/v1';
    private string $apiKey;

    public function __construct()
    {
        $this->apiKey = config('services.screenshotapi.key');
    }

    /**
     * Take a screenshot of a URL.
     */
    public function capture(string $url, array $options = []): array
    {
        $response = Http::withToken($this->apiKey)
            ->post("{$this->baseUrl}/screenshots", array_merge(
                ['url' => $url],
                $options,
            ));

        $response->throw();

        return $response->json('data');
    }

    /**
     * Get screenshot details by ID.
     */
    public function get(string $id): array
    {
        $response = Http::withToken($this->apiKey)
            ->get("{$this->baseUrl}/screenshots/{$id}");

        $response->throw();

        return $response->json('data');
    }

    /**
     * Download the screenshot image.
     */
    public function download(string $id, string $savePath): void
    {
        $response = Http::withToken($this->apiKey)
            ->get("{$this->baseUrl}/screenshots/{$id}/image");

        $response->throw();

        file_put_contents($savePath, $response->body());
    }

    /**
     * List screenshots with optional filters.
     */
    public function list(array $filters = []): array
    {
        $response = Http::withToken($this->apiKey)
            ->get("{$this->baseUrl}/screenshots", $filters);

        $response->throw();

        return $response->json();
    }

    /**
     * Delete a screenshot.
     */
    public function delete(string $id): bool
    {
        $response = Http::withToken($this->apiKey)
            ->delete("{$this->baseUrl}/screenshots/{$id}");

        return $response->status() === 204;
    }

    /**
     * Wait for a screenshot to complete (polling).
     */
    public function captureAndWait(string $url, array $options = [], int $timeout = 60): array
    {
        $screenshot = $this->capture($url, $options);
        $startTime = time();

        while (time() - $startTime < $timeout) {
            $screenshot = $this->get($screenshot['id']);

            if ($screenshot['status'] === 'completed') {
                return $screenshot;
            }

            if ($screenshot['status'] === 'failed') {
                throw new \RuntimeException(
                    "Screenshot failed: " . ($screenshot['error']['message'] ?? 'Unknown error')
                );
            }

            sleep(2);
        }

        throw new \RuntimeException("Screenshot timed out after {$timeout} seconds");
    }
}

Usage

php
// config/services.php
'screenshotapi' => [
    'key' => env('SCREENSHOT_API_KEY'),
],

// In your controller or service
$client = new ScreenshotApiClient();

// Simple capture
$screenshot = $client->capture('https://example.com', [
    'format' => 'webp',
    'full_page' => true,
]);

// Capture and wait for result
$screenshot = $client->captureAndWait('https://example.com');
$client->download($screenshot['id'], storage_path('screenshots/example.png'));

Python

Python (requests)

python
import os
import time
import requests

class ScreenshotAPI:
    def __init__(self, api_key=None):
        self.api_key = api_key or os.environ.get("SCREENSHOT_API_KEY")
        self.base_url = "https://screenshotrun.com/api/v1"
        self.session = requests.Session()
        self.session.headers.update({
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json",
        })

    def capture(self, url, **options):
        """Take a screenshot of a URL."""
        response = self.session.post(
            f"{self.base_url}/screenshots",
            json={"url": url, **options},
        )
        response.raise_for_status()
        return response.json()["data"]

    def get(self, screenshot_id):
        """Get screenshot details by ID."""
        response = self.session.get(f"{self.base_url}/screenshots/{screenshot_id}")
        response.raise_for_status()
        return response.json()["data"]

    def download(self, screenshot_id, save_path):
        """Download the screenshot image to a file."""
        response = self.session.get(f"{self.base_url}/screenshots/{screenshot_id}/image")
        response.raise_for_status()
        with open(save_path, "wb") as f:
            f.write(response.content)

    def list(self, **filters):
        """List screenshots with optional filters."""
        response = self.session.get(f"{self.base_url}/screenshots", params=filters)
        response.raise_for_status()
        return response.json()

    def delete(self, screenshot_id):
        """Delete a screenshot."""
        response = self.session.delete(f"{self.base_url}/screenshots/{screenshot_id}")
        return response.status_code == 204

    def capture_and_wait(self, url, timeout=60, **options):
        """Take a screenshot and wait for it to complete."""
        screenshot = self.capture(url, **options)
        start_time = time.time()

        while time.time() - start_time < timeout:
            screenshot = self.get(screenshot["id"])

            if screenshot["status"] == "completed":
                return screenshot
            if screenshot["status"] == "failed":
                raise Exception(f"Screenshot failed: {screenshot['error']['message']}")

            time.sleep(2)

        raise TimeoutError(f"Screenshot timed out after {timeout} seconds")

    def get_usage(self):
        """Get current usage statistics."""
        response = self.session.get(f"{self.base_url}/account/usage")
        response.raise_for_status()
        return response.json()["data"]

Usage

python
api = ScreenshotAPI("sk_live_your_key_here")

# Simple capture
screenshot = api.capture("https://example.com", format="webp", full_page=True)
print(f"Screenshot ID: {screenshot['id']}")

# Capture and wait
screenshot = api.capture_and_wait("https://example.com")
api.download(screenshot["id"], "example.png")

# List completed screenshots
result = api.list(status="completed", per_page=10)
for s in result["data"]:
    print(f"{s['id']}: {s['url']}")

# Check usage
usage = api.get_usage()
print(f"Used: {usage['screenshots_used']}/{usage['screenshots_limit']}")

JavaScript / TypeScript

Node.js (Fetch API)

javascript
import fs from "fs";

class ScreenshotAPI {
  constructor(apiKey) {
    this.apiKey = apiKey || process.env.SCREENSHOT_API_KEY;
    this.baseUrl = "https://screenshotrun.com/api/v1";
  }

  async #request(method, path, { body, params } = {}) {
    const url = new URL(`${this.baseUrl}${path}`);
    if (params) {
      Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v));
    }

    const response = await fetch(url.toString(), {
      method,
      headers: {
        Authorization: `Bearer ${this.apiKey}`,
        "Content-Type": "application/json",
      },
      body: body ? JSON.stringify(body) : undefined,
    });

    if (!response.ok) {
      const error = await response.json();
      throw new Error(`[${error.error.code}] ${error.error.message}`);
    }

    if (response.status === 204) return null;
    return response;
  }

  async capture(url, options = {}) {
    const response = await this.#request("POST", "/screenshots", {
      body: { url, ...options },
    });
    return (await response.json()).data;
  }

  async get(id) {
    const response = await this.#request("GET", `/screenshots/${id}`);
    return (await response.json()).data;
  }

  async download(id, savePath) {
    const response = await this.#request("GET", `/screenshots/${id}/image`);
    const buffer = Buffer.from(await response.arrayBuffer());
    fs.writeFileSync(savePath, buffer);
  }

  async list(filters = {}) {
    const response = await this.#request("GET", "/screenshots", { params: filters });
    return await response.json();
  }

  async delete(id) {
    await this.#request("DELETE", `/screenshots/${id}`);
    return true;
  }

  async captureAndWait(url, options = {}, timeout = 60000) {
    let screenshot = await this.capture(url, options);
    const startTime = Date.now();

    while (Date.now() - startTime < timeout) {
      screenshot = await this.get(screenshot.id);

      if (screenshot.status === "completed") return screenshot;
      if (screenshot.status === "failed") {
        throw new Error(`Screenshot failed: ${screenshot.error.message}`);
      }

      await new Promise((r) => setTimeout(r, 2000));
    }

    throw new Error(`Screenshot timed out after ${timeout}ms`);
  }
}

Usage

javascript
const api = new ScreenshotAPI("sk_live_your_key_here");

// Simple capture
const screenshot = await api.capture("https://example.com", {
  format: "webp",
  full_page: true,
});
console.log(`Screenshot ID: ${screenshot.id}`);

// Capture and wait
const completed = await api.captureAndWait("https://example.com");
await api.download(completed.id, "example.png");

// List screenshots
const { data } = await api.list({ status: "completed", per_page: 10 });
data.forEach((s) => console.log(`${s.id}: ${s.url}`));

Ruby

Ruby (net/http)

ruby
require "net/http"
require "json"
require "uri"

class ScreenshotAPI
  BASE_URL = "https://screenshotrun.com/api/v1"

  def initialize(api_key = nil)
    @api_key = api_key || ENV["SCREENSHOT_API_KEY"]
  end

  def capture(url, **options)
    response = post("/screenshots", { url: url, **options })
    JSON.parse(response.body)["data"]
  end

  def get(id)
    response = request(:get, "/screenshots/#{id}")
    JSON.parse(response.body)["data"]
  end

  def download(id, save_path)
    response = request(:get, "/screenshots/#{id}/image")
    File.binwrite(save_path, response.body)
  end

  def list(**filters)
    query = URI.encode_www_form(filters)
    response = request(:get, "/screenshots?#{query}")
    JSON.parse(response.body)
  end

  def delete(id)
    response = request(:delete, "/screenshots/#{id}")
    response.code == "204"
  end

  def capture_and_wait(url, timeout: 60, **options)
    screenshot = capture(url, **options)
    start_time = Time.now

    loop do
      screenshot = get(screenshot["id"])

      return screenshot if screenshot["status"] == "completed"

      if screenshot["status"] == "failed"
        raise "Screenshot failed: #{screenshot['error']['message']}"
      end

      raise "Timeout after #{timeout}s" if Time.now - start_time > timeout

      sleep 2
    end
  end

  private

  def request(method, path)
    uri = URI("#{BASE_URL}#{path}")
    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = uri.scheme == "https"

    req = case method
          when :get then Net::HTTP::Get.new(uri)
          when :delete then Net::HTTP::Delete.new(uri)
          end
    req["Authorization"] = "Bearer #{@api_key}"
    http.request(req)
  end

  def post(path, body)
    uri = URI("#{BASE_URL}#{path}")
    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = uri.scheme == "https"

    req = Net::HTTP::Post.new(uri)
    req["Authorization"] = "Bearer #{@api_key}"
    req["Content-Type"] = "application/json"
    req.body = body.to_json
    http.request(req)
  end
end

Usage

ruby
api = ScreenshotAPI.new("sk_live_your_key_here")

# Capture and wait
screenshot = api.capture_and_wait("https://example.com", format: "webp")
api.download(screenshot["id"], "example.webp")

# List completed screenshots
result = api.list(status: "completed", per_page: 10)
result["data"].each { |s| puts "#{s['id']}: #{s['url']}" }

Go

Go (net/http)

go
package screenshotapi

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
	"time"
)

const baseURL = "https://screenshotrun.com/api/v1"

type Client struct {
	APIKey     string
	HTTPClient *http.Client
}

type Screenshot struct {
	ID              string                 `json:"id"`
	Status          string                 `json:"status"`
	URL             string                 `json:"url"`
	Options         map[string]interface{} `json:"options"`
	FileSize        int64                  `json:"file_size,omitempty"`
	MimeType        string                 `json:"mime_type,omitempty"`
	Width           int                    `json:"width,omitempty"`
	Height          int                    `json:"height,omitempty"`
	ProcessingTime  int                    `json:"processing_time_ms,omitempty"`
	Error           *ErrorInfo             `json:"error,omitempty"`
	CreatedAt       string                 `json:"created_at"`
}

type ErrorInfo struct {
	Message string `json:"message"`
	Code    string `json:"code"`
}

func NewClient(apiKey string) *Client {
	return &Client{
		APIKey:     apiKey,
		HTTPClient: &http.Client{Timeout: 30 * time.Second},
	}
}

func (c *Client) Capture(url string, options map[string]interface{}) (*Screenshot, error) {
	if options == nil {
		options = make(map[string]interface{})
	}
	options["url"] = url

	body, _ := json.Marshal(options)
	req, _ := http.NewRequest("POST", baseURL+"/screenshots", bytes.NewReader(body))
	req.Header.Set("Authorization", "Bearer "+c.APIKey)
	req.Header.Set("Content-Type", "application/json")

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

	var result struct{ Data Screenshot `json:"data"` }
	json.NewDecoder(resp.Body).Decode(&result)
	return &result.Data, nil
}

func (c *Client) Get(id string) (*Screenshot, error) {
	req, _ := http.NewRequest("GET", baseURL+"/screenshots/"+id, nil)
	req.Header.Set("Authorization", "Bearer "+c.APIKey)

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

	var result struct{ Data Screenshot `json:"data"` }
	json.NewDecoder(resp.Body).Decode(&result)
	return &result.Data, nil
}

func (c *Client) Download(id, savePath string) error {
	req, _ := http.NewRequest("GET", baseURL+"/screenshots/"+id+"/image", nil)
	req.Header.Set("Authorization", "Bearer "+c.APIKey)

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

	file, err := os.Create(savePath)
	if err != nil {
		return err
	}
	defer file.Close()

	_, err = io.Copy(file, resp.Body)
	return err
}

func (c *Client) CaptureAndWait(url string, options map[string]interface{}, timeout time.Duration) (*Screenshot, error) {
	screenshot, err := c.Capture(url, options)
	if err != nil {
		return nil, err
	}

	deadline := time.Now().Add(timeout)
	for time.Now().Before(deadline) {
		screenshot, err = c.Get(screenshot.ID)
		if err != nil {
			return nil, err
		}
		if screenshot.Status == "completed" {
			return screenshot, nil
		}
		if screenshot.Status == "failed" {
			return nil, fmt.Errorf("screenshot failed: %s", screenshot.Error.Message)
		}
		time.Sleep(2 * time.Second)
	}
	return nil, fmt.Errorf("screenshot timed out after %v", timeout)
}

Usage

go
client := screenshotapi.NewClient("sk_live_your_key_here")

// Capture and wait
screenshot, err := client.CaptureAndWait("https://example.com", map[string]interface{}{
    "format":    "webp",
    "full_page": true,
}, 60*time.Second)
if err != nil {
    log.Fatal(err)
}

// Download the image
err = client.Download(screenshot.ID, "example.webp")
if err != nil {
    log.Fatal(err)
}

fmt.Printf("Screenshot saved! Size: %d bytes\n", screenshot.FileSize)

cURL

For quick testing and scripting, cURL is the simplest way to interact with the API:

Complete workflow

bash
#!/bin/bash
API_KEY="sk_live_your_key_here"
BASE_URL="https://screenshotrun.com/api/v1"

# 1. Create screenshot
RESPONSE=$(curl -s -X POST "$BASE_URL/screenshots" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com", "format": "png", "full_page": true}')

SCREENSHOT_ID=$(echo $RESPONSE | python3 -c "import sys,json; print(json.load(sys.stdin)['data']['id'])")
echo "Screenshot ID: $SCREENSHOT_ID"

# 2. Poll until ready
while true; do
  STATUS_RESPONSE=$(curl -s "$BASE_URL/screenshots/$SCREENSHOT_ID" \
    -H "Authorization: Bearer $API_KEY")

  STATUS=$(echo $STATUS_RESPONSE | python3 -c "import sys,json; print(json.load(sys.stdin)['data']['status'])")

  if [ "$STATUS" = "completed" ]; then
    echo "Screenshot ready!"
    break
  elif [ "$STATUS" = "failed" ]; then
    echo "Screenshot failed!"
    exit 1
  fi

  echo "Status: $STATUS, waiting..."
  sleep 2
done

# 3. Download the image
curl -s "$BASE_URL/screenshots/$SCREENSHOT_ID/image" \
  -H "Authorization: Bearer $API_KEY" \
  -o screenshot.png

echo "Saved to screenshot.png"