README.md

# Pxshot

[![Hex.pm](https://img.shields.io/hexpm/v/pxshot.svg)](https://hex.pm/packages/pxshot)
[![Docs](https://img.shields.io/badge/hex-docs-blue.svg)](https://hexdocs.pm/pxshot)
[![License](https://img.shields.io/hexpm/l/pxshot.svg)](LICENSE)

Official Elixir SDK for the [Pxshot](https://pxshot.com) screenshot API.

## Installation

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

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

## Configuration

### Application Config

Configure your API key in `config/config.exs`:

```elixir
config :pxshot,
  api_key: "px_your_api_key"
```

Or use environment variables:

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

### Runtime Config

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

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

## Usage

### Basic Screenshot

```elixir
# 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

```elixir
# 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)

```elixir
# 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

```elixir
{: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

```elixir
{: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:

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

### Error Handling

```elixir
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:

```elixir
{: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

```elixir
# 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

- Elixir 1.14+
- OTP 25+

## License

MIT License - see [LICENSE](LICENSE) for details.