# Latchshot API

Latchshot renders public web pages as PNG, JPEG, or PDF through a guarded Chromium service. It offers an instant Free plan for developers building reports, link previews, QA artifacts, social images, and page archives.

- Base URL: `https://latchshot.fly.dev`
- OpenAPI 3.1: `https://latchshot.fly.dev/openapi.json`
- Public contract, examples, and support: `https://github.com/BaiqingL/latchshot`
- Data handling and retention: `https://latchshot.fly.dev/data-handling.html`
- Health: `https://latchshot.fly.dev/healthz`
- Authentication: Bearer API key

## Get 100 free renders each month

The endpoint creates one Free-plan key per email and returns it once in its `201` response. Save the key immediately: only its hash is stored, so it cannot be recovered. The allowance replenishes to 100 successful renders at the start of every UTC calendar month. Only email is required; workflow context and contact permission are optional.

```sh
curl --fail-with-body https://latchshot.fly.dev/api/trials \
  -H 'Content-Type: application/json' \
  --data '{
    "email": "you@example.com"
  }'
```

The JSON response contains `apiKey`, the internal `trial` plan identifier, the 100-render monthly limit, `quotaPeriod: "calendar_month"`, the next UTC reset time, and a quickstart URL. Issuance is limited to three attempts per client IP per hour; repeated requests for an email that already received a free key return `409`. Optional fields are `name`, `useCase`, `consent`, and `expectedRenders`; accepted volume values are `under 1,000`, `1,000–10,000`, `10,000–50,000`, `over 50,000`, and `not sure`.

The website form adds an allowlisted `X-Latchshot-Acquisition` header only when a visitor arrives through a measured credential path. Exact values `thumbnail`, `mcpguide`, and `actionguide` become coarse sources `owned_thumbnail`, `owned_mcp_guide`, and `owned_github_action`; `openconnector`, `goose`, `claudecode`, `geminicli`, `vscode`, `cursor`, `piwebsearch`, `githubaction`, `githubcli`, `mcpmetadata`, `mcpso`, `lobehub`, and `kilo` become their corresponding fixed `community_*` categories. Unknown values are ignored. The source is not stored on the lead or key, and no cookie, client identifier, raw referrer, target URL, or browsing history is retained.

## Capture a screenshot

```sh
export LATCHSHOT_API_KEY='ls_live_replace_me'

curl --fail-with-body \
  -H "Authorization: Bearer $LATCHSHOT_API_KEY" \
  'https://latchshot.fly.dev/v1/screenshot?url=https%3A%2F%2Fexample.com&width=1440&height=900&format=png' \
  --output example.png
```

## Hosted MCP server

AI clients that support MCP Streamable HTTP can use Latchshot without installing Chromium or a local MCP package:

- Endpoint: `https://latchshot.fly.dev/mcp`
- Authentication: `Authorization: Bearer ls_live_...`
- Tools: `capture_page` and `get_usage`
- Output: PNG/JPEG as inline MCP image content; PDF as an embedded MCP resource
- Registry name: [`io.github.BaiqingL/latchshot`](https://registry.modelcontextprotocol.io/v0.1/servers?search=io.github.BaiqingL%2Flatchshot)
- Public metadata and setup: [`BaiqingL/latchshot-mcp`](https://github.com/BaiqingL/latchshot-mcp)
- Setup and tool-contract guide: [Hosted screenshot MCP server](https://latchshot.fly.dev/guides/screenshot-mcp-server.html), including exact paths for VS Code, Cursor, Claude Code, Gemini CLI, and goose

Use your client's secret or credential manager for the header. A representative remote-server configuration is:

```json
{
  "mcpServers": {
    "latchshot": {
      "type": "http",
      "url": "https://latchshot.fly.dev/mcp",
      "headers": {
        "Authorization": "Bearer ls_live_replace_me"
      }
    }
  }
}
```

Configuration keys vary between MCP clients. The endpoint is stateless and implements Streamable HTTP with JSON responses. `capture_page` accepts a public URL, `png`, `jpeg`, or `pdf`, bounded viewport and delay controls, dark mode, and PDF paper/orientation. It returns render diagnostics and remaining quota alongside the artifact. The server exposes no payment or upgrade tool.

Claude Code users can install the reviewed [Latchshot plugin](https://github.com/BaiqingL/latchshot-claude-code), which fixes this endpoint and reads the key from `LATCHSHOT_API_KEY` without local executable code. The [integration recipe](https://latchshot.fly.dev/integrations.md) includes the exact install sequence and the community-marketplace acceptance boundary.

Gemini CLI users can install the reviewed [Latchshot extension](https://github.com/BaiqingL/latchshot-gemini-cli), which fixes the endpoint, declares the key as a sensitive extension setting, and adds no executable code or always-on prompt content. The [integration recipe](https://latchshot.fly.dev/integrations.md#gemini-cli) includes the exact install sequence and current gallery-discovery boundary.

VS Code and GitHub Copilot users can use the [secure one-click MCP definition](https://latchshot.fly.dev/integrations.md#vs-code-and-github-copilot), which fixes the endpoint and stores the key through a password input variable. The same recipe documents the CLI install and the current GitHub/VS Code registry-sync boundary.

Cursor users can use the [one-click authenticated MCP definition](https://latchshot.fly.dev/integrations.md#cursor), which fixes the endpoint and interpolates `LATCHSHOT_API_KEY` from the environment that launches Cursor. The recipe also provides the native `cursor --add-mcp` command and a copyable user-level configuration without embedding a key.

## CLI and Node client

The dependency-free [Latchshot CLI and Node client](https://github.com/BaiqingL/latchshot-cli) supports screenshots, PDFs, quota inspection, paid-plan requests, bounded retries, JSON diagnostics, and atomic output writes on Node.js 18.17 or newer.

Run the immutable GitHub release without installing it globally:

```sh
export LATCHSHOT_API_KEY='ls_live_replace_me'
npx --yes github:BaiqingL/latchshot-cli#v0.2.1 \
  capture https://example.com example.png
```

The package is not published to npm. Use the full GitHub package spec above; `npx latchshot` does not currently install this client.

## Render with JSON

```sh
curl --fail-with-body https://latchshot.fly.dev/v1/render \
  -H "Authorization: Bearer $LATCHSHOT_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{
    "url": "https://example.com",
    "kind": "screenshot",
    "format": "jpeg",
    "width": 1200,
    "height": 800,
    "darkMode": false,
    "delay": 250
  }' \
  --output example.jpg
```

For PDF output, set `kind` to `pdf` and optionally choose `paper` as `A4`, `Letter`, or `Legal`.

## JavaScript

```js
import { writeFile } from 'node:fs/promises';

const response = await fetch('https://latchshot.fly.dev/v1/render', {
  method: 'POST',
  headers: {
    authorization: `Bearer ${process.env.LATCHSHOT_API_KEY}`,
    'content-type': 'application/json',
  },
  body: JSON.stringify({
    url: 'https://example.com',
    format: 'png',
    width: 1440,
    height: 900,
  }),
});

if (!response.ok) throw new Error(await response.text());
await writeFile('example.png', Buffer.from(await response.arrayBuffer()));
```

For bounded retries and response diagnostics, download the [dependency-free Node adapter](https://latchshot.fly.dev/examples/node.mjs).

## Python

```python
import os
import requests

response = requests.post(
    "https://latchshot.fly.dev/v1/render",
    headers={"Authorization": f"Bearer {os.environ['LATCHSHOT_API_KEY']}"},
    json={
        "url": "https://example.com",
        "format": "png",
        "width": 1440,
        "height": 900,
    },
    timeout=45,
)
response.raise_for_status()
open("example.png", "wb").write(response.content)
```

For a standard-library-only version with bounded retries, download the [dependency-free Python adapter](https://latchshot.fly.dev/examples/python.py).

Migrating an existing screenshot integration? See the [option map and production cutover checklist](https://latchshot.fly.dev/migrate.md).

## Integration recipes

- [GitHub Actions, n8n, and scheduled reports](https://latchshot.fly.dev/integrations.md)
- [Reusable Latchshot Screenshot Action](https://github.com/BaiqingL/latchshot-action)
- [Dependency-free Latchshot CLI and Node client](https://github.com/BaiqingL/latchshot-cli)
- [Hosted Latchshot MCP server metadata](https://github.com/BaiqingL/latchshot-mcp)
- [Latchshot Claude Code plugin](https://github.com/BaiqingL/latchshot-claude-code)
- [Latchshot Gemini CLI extension](https://github.com/BaiqingL/latchshot-gemini-cli)
- [VS Code and GitHub Copilot MCP installation](https://latchshot.fly.dev/integrations.md#vs-code-and-github-copilot)
- [VS Code MCP definition](https://latchshot.fly.dev/integrations/vscode-mcp.json)
- [Cursor MCP installation](https://latchshot.fly.dev/integrations.md#cursor)
- [Cursor MCP definition](https://latchshot.fly.dev/integrations/cursor-mcp.json)
- [Ready-to-run GitHub Actions workflow](https://latchshot.fly.dev/integrations/github-actions.yml)
- [n8n HTTP Request configuration](https://latchshot.fly.dev/integrations/n8n.md)
- [Importable n8n screenshot workflow](https://latchshot.fly.dev/integrations/n8n-website-screenshot.json)
- [Versioned n8n workflow source and releases](https://github.com/BaiqingL/latchshot-n8n)
- [Scheduled-report operating pattern](https://latchshot.fly.dev/integrations/scheduled-reports.md)

## Implementation guides

- [URL to screenshot API](https://latchshot.fly.dev/guides/url-to-screenshot-api.html) — runnable GET and POST examples, stable-output controls, limits, and quota economics.
- [Website thumbnail and hosted-HTML artifact previews](https://latchshot.fly.dev/guides/website-thumbnail-api.html) — fixed-viewport capture, readiness signals, stable storage keys, bounded background generation, downstream resize guidance, fallbacks, and cache-first serving.
- [URL to PDF API](https://latchshot.fly.dev/guides/url-to-pdf-api.html) — runnable PDF request, paper options, print-layout guidance, retries, and boundaries.
- [Website screenshot GitHub Action](https://latchshot.fly.dev/guides/website-screenshot-github-action.html) — complete workflow YAML, secret setup, artifact outputs, scheduling, and hosted-versus-local tradeoffs.
- [Hosted screenshot MCP server](https://latchshot.fly.dev/guides/screenshot-mcp-server.html) — client-specific install paths, secret handling, verification boundaries, Streamable HTTP configuration, inline artifacts, network limits, and quota behavior.
- [n8n website screenshot workflow](https://latchshot.fly.dev/guides/n8n-website-screenshot-workflow.html) — secret-safe import, Bearer credential, typed inputs, binary file routing, PDF changes, retries, and verified n8n 2.30.7 execution.

## Options

| Option | Values | Default |
| --- | --- | --- |
| `url` | Public `http` or `https` URL on port 80/443 | required |
| `kind` | `screenshot`, `pdf` | `screenshot` |
| `format` | `png`, `jpeg` | `png` |
| `width` | 320–2560 | 1440 |
| `height` | 240–1440 | 900 |
| `scale` | 1–2 | 1 |
| `fullPage` | boolean | false |
| `waitUntil` | `load`, `domcontentloaded`, `networkidle` | `domcontentloaded` |
| `delay` | 0–3000 ms | 0 |
| `timeout` | 3000–30000 ms | 15000 |
| `darkMode` | boolean | false |
| `reducedMotion` | boolean | true |
| `paper` | `A4`, `Letter`, `Legal` | `A4` |
| `landscape` | boolean | false |

## Usage and limits

Only successful renders consume monthly quota. Automatic overages are disabled during beta.

```sh
curl --fail-with-body \
  -H "Authorization: Bearer $LATCHSHOT_API_KEY" \
  https://latchshot.fly.dev/v1/usage
```

## Request a paid plan

Use the existing key to request a higher tier. The request is deduplicated per key and limited to five submissions per hour. No payment is taken by this endpoint.

```sh
curl --fail-with-body https://latchshot.fly.dev/v1/upgrade-requests \
  -H "Authorization: Bearer $LATCHSHOT_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{
    "requestedPlan": "build",
    "note": "Weekday screenshots for public client reports.",
    "consent": true
  }'
```

The key must have a contact email, and the requested plan must be higher than its current plan. The owner replies to that email with payment and activation steps. After the owner confirms payment, the same key receives the paid plan; no key rotation is required. The `GET /v1/usage` response includes the current upgrade-request state.

The CLI performs the same request and requires the consent flag explicitly:

```sh
npx --yes github:BaiqingL/latchshot-cli#v0.2.1 \
  upgrade build --consent-contact \
  --note 'Weekday screenshots for public client reports.'
```

Successful render responses include rate-limit and monthly-quota headers. A `429` response includes the next reset time. A pathological page is terminated at a hard execution deadline and returns `504 render_timeout` without retaining a render slot.

## Response diagnostics

- `X-Latchshot-Render-Ms`: server-side render duration.
- `X-Latchshot-Navigation`: `complete` or `timed-out` when received content was still capturable.
- `X-Latchshot-Fonts`: `original` or `fallback` if stalled web fonts required a system-font retry.
- `X-Latchshot-Scripts`: `active` or `paused` if continuous navigation required a stabilized capture.
- `X-Quota-Limit`, `X-Quota-Remaining`, `X-Quota-Reset`: current monthly allowance.

## Beta evidence and boundaries

The latest production benchmark rendered 197 of 200 preflighted public HTML roots successfully at concurrency two. End-to-end p50 was 2.42 seconds and p95 was 7.68 seconds. This is engineering evidence, not an SLA.

Latchshot does not offer CAPTCHA solving, proxy rotation, anti-bot bypass, arbitrary browser scripts, or private-network access. Customers must have the right to capture their target content and comply with the target site’s terms and applicable law. Review the current [data handling and retention boundary](https://latchshot.fly.dev/data-handling.html) before submitting a target or requesting a key.

## Plans

| Plan | Monthly price | Successful renders |
| --- | ---: | ---: |
| Free | $0 | 100 per UTC calendar month |
| Launch | $19 | 2,500 |
| Build | $49 | 12,000 |
| Scale | $149 | 50,000 |

Payment and plan activation are handled directly by the owner during private beta.
