Pxshot

Hex.pmDocsLicense

Official Elixir SDK for the Pxshot screenshot API.

Installation

Add pxshot to your list of dependencies in mix.exs:

def deps do
  [
    {:pxshot, "~> 0.1.0"}
  ]
end

Configuration

Application Config

Configure your API key in config/config.exs:

config :pxshot,
  api_key: "px_your_api_key"

Or use environment variables:

config :pxshot,
  api_key: System.get_env("PXSHOT_API_KEY")

Runtime Config

You can also pass the API key directly when creating a client:

client = Pxshot.client(api_key: "px_your_api_key")

Usage

Basic Screenshot

# Create client (uses configured API key)
client = Pxshot.client()

# Take a screenshot - returns PNG binary
{:ok, image} = Pxshot.screenshot(client, url: "https://example.com")
File.write!("screenshot.png", image)

Screenshot Options

# Full page JPEG with custom viewport
{:ok, image} = Pxshot.screenshot(client,
  url: "https://example.com",
  format: "jpeg",
  quality: 90,
  width: 1280,
  height: 720,
  full_page: true
)

# Wait for specific element
{:ok, image} = Pxshot.screenshot(client,
  url: "https://example.com",
  wait_for_selector: ".main-content",
  wait_until: "networkidle"
)

# Retina screenshot
{:ok, image} = Pxshot.screenshot(client,
  url: "https://example.com",
  device_scale_factor: 2
)

Store Screenshot (Get URL)

# Store screenshot and get a URL instead of binary data
{:ok, result} = Pxshot.screenshot(client,
  url: "https://example.com",
  store: true
)

IO.puts("Screenshot URL: #{result.url}")
IO.puts("Expires at: #{result.expires_at}")
IO.puts("Size: #{result.size_bytes} bytes")

Check Usage

{:ok, usage} = Pxshot.usage(client)

IO.puts("Period: #{usage.period}")
IO.puts("Screenshots: #{usage.screenshots_used}/#{usage.screenshots_limit}")
IO.puts("Storage: #{usage.storage_used_bytes} bytes")

# Calculate percentage
percent = Pxshot.Response.Usage.usage_percent(usage)
IO.puts("Usage: #{Float.round(percent, 1)}%")

Health Check

{:ok, health} = Pxshot.health(client)

if Pxshot.Response.Health.healthy?(health) do
  IO.puts("API is healthy!")
end

Bang Variants

All functions have bang variants that raise on error:

# Raises Pxshot.Error on failure
image = Pxshot.screenshot!(client, url: "https://example.com")
usage = Pxshot.usage!(client)
health = Pxshot.health!(client)

Error Handling

case Pxshot.screenshot(client, url: "https://example.com") do
  {:ok, image} ->
    File.write!("screenshot.png", image)

  {:error, %Pxshot.Error{} = error} ->
    IO.puts("Error: #{error.message}")
    IO.puts("Status: #{error.status}")
    IO.puts("Code: #{error.code}")

    if Pxshot.Error.rate_limited?(error) do
      IO.puts("Rate limited! Retry after: #{error.rate_limit.retry_after}s")
    end
end

Rate Limit Information

Rate limit info is included in responses:

{:ok, usage} = Pxshot.usage(client)

if usage.rate_limit do
  IO.puts("Rate limit: #{usage.rate_limit.remaining}/#{usage.rate_limit.limit}")
  IO.puts("Resets at: #{usage.rate_limit.reset}")
end

Screenshot Options Reference

Option Type Default Description
url string required URL to screenshot
format string "png" Image format: "png", "jpeg", "webp"
quality integer 80 JPEG/WebP quality (1-100)
width integer 1920 Viewport width in pixels
height integer 1080 Viewport height in pixels
full_page boolean false Capture full scrollable page
wait_until string "load""load", "domcontentloaded", "networkidle"
wait_for_selector string - CSS selector to wait for
wait_for_timeout integer - Additional wait time (ms)
device_scale_factor number 1 Device scale for retina
store boolean false Return URL instead of binary
block_ads boolean false Block ads and trackers

Advanced Configuration

# Custom timeout and base URL
client = Pxshot.client(
  api_key: "px_your_api_key",
  base_url: "https://api.pxshot.com",
  timeout: 60_000  # 60 seconds
)

Requirements

License

MIT License - see LICENSE for details.