API Documentation

PxShot captures any webpage and returns a raw image or PDF file via a simple HTTP GET request.

Quick Start

1. Sign up at pxshot.dev/register.

2. Create an API key in your dashboard.

3. Make your first request:

curl "https://pxshot.dev/api/capture?url=https://example.com&api_key=YOUR_KEY" \
  --output screenshot.png

Authentication

PxShot authenticates requests using API keys. You can pass your key in either of two ways:

  • Query parameter: api_key=YOUR_KEY
  • Request header: X-API-Key: YOUR_KEY

API keys have the format px_.... Keep your key secret — do not commit it to source code or expose it in client-side JavaScript unless you have set an origin lock.

Origin locking: In the dashboard you can restrict an API key to only work from specific HTTP origins (e.g. https://yourapp.com). Requests from any other origin are rejected with 403. This makes it safe to include the key in client-side code.

GET /api/capture

The capture endpoint. Returns raw image bytes (or PDF bytes) with the appropriate Content-Type header. All parameters are passed as query string parameters.

GET https://pxshot.dev/api/capture?url=URL&api_key=KEY[&format=png][&width=1280][&height=720]

On success the response is HTTP 200 with the raw image or PDF binary. Errors return JSON with { "ok": false, "error": "message" }.

Parameters

ParameterTypeRequiredDescription
urlstringrequiredThe fully-qualified URL to capture. Must include protocol (https://).
api_keystringrequiredYour API key. Alternatively pass as an X-API-Key request header.
formatstringoptionalOutput format: png (default), jpeg, webp, or pdf. Pro/Business plan required for non-PNG.
widthintegeroptionalViewport width in pixels. Default: 1280. Min: 320. Max by plan — Free: 1280, Pro: 1920, Business: 3840.
heightintegeroptionalViewport height in pixels. Default: 720. Min: 200. Max by plan — Free: 720, Pro: 1080, Business: 2160.
full_pagebooleanoptionalCapture the full scrollable page instead of only the viewport. Default: false. Pro/Business required.
delayintegeroptionalMilliseconds to wait after page load before capturing. Default: 0. Max: 10000. Pro/Business required.
qualityintegeroptionalImage quality 1–100 for JPEG/WebP output. Default: 80. Ignored for PNG and PDF.

Response Format

Successful responses (HTTP 200) return raw binary image or PDF data. The following headers are always included:

  • Content-Type: image/png — or image/jpeg, image/webp, application/pdf
  • Content-Length — byte size of the response body
  • X-Screenshot-Id — unique ID for this screenshot, logged in your dashboard
  • X-Duration-Ms — time in milliseconds taken to capture the page
  • X-RateLimit-Remaining — requests remaining in the current per-minute window
  • X-Monthly-Used — screenshots used so far this billing period
  • X-Monthly-Limit — total monthly limit on your current plan
  • Cache-Control: public, max-age=300 — responses are cacheable for 5 minutes

Error responses return JSON: { "ok": false, "error": "message" }

Error Codes

StatusNameDescription
400Bad RequestMissing required parameter (url or api_key), or invalid URL.
401UnauthorizedInvalid, inactive, or missing API key.
403ForbiddenOrigin restriction violation, or plan does not support the requested feature (e.g. non-PNG format on Free plan).
429Too Many RequestsMonthly screenshot limit exceeded or per-minute rate limit hit. Check X-Monthly-Used / X-RateLimit-Remaining headers.
500Internal Server ErrorScreenshot capture failed (e.g. page unreachable, browser timeout).

Rate Limits

Two separate limits apply: a monthly quota and a per-minute burst limit. Both are enforced per API key. Exceeding either returns HTTP 429.

PlanMonthlyPer MinuteAPI KeysFormats
Free5051PNG
Pro2,000303PNG, JPEG, WebP, PDF
Business10,00010010All

Code Examples

cURL

curl "https://pxshot.dev/api/capture?url=https://example.com&api_key=YOUR_KEY&format=png&width=1280&height=720" \
  --output screenshot.png

JavaScript (fetch)

const params = new URLSearchParams({
  url: 'https://example.com',
  api_key: 'YOUR_KEY',
  format: 'webp',
  width: '1280',
  height: '720',
});

const response = await fetch(`https://pxshot.dev/api/capture?${params}`);

if (!response.ok) {
  const err = await response.json();
  throw new Error(err.error);
}

const blob = await response.blob();
const imageUrl = URL.createObjectURL(blob);
// Use imageUrl to display or download the image

JavaScript — using X-API-Key header

const params = new URLSearchParams({
  url: 'https://example.com',
  format: 'png',
  width: '1920',
  height: '1080',
  full_page: 'true',
});

const response = await fetch(`https://pxshot.dev/api/capture?${params}`, {
  headers: { 'X-API-Key': 'YOUR_KEY' },
});

const blob = await response.blob();

Node.js

import fs from 'fs';

const params = new URLSearchParams({
  url: 'https://example.com',
  api_key: 'YOUR_KEY',
  format: 'png',
  width: '1920',
  height: '1080',
  full_page: 'true',
});

const res = await fetch(`https://pxshot.dev/api/capture?${params}`);
if (!res.ok) throw new Error(`PxShot error: ${res.status}`);

const buffer = await res.arrayBuffer();
fs.writeFileSync('screenshot.png', Buffer.from(buffer));
console.log('Duration:', res.headers.get('X-Duration-Ms'), 'ms');

Python

import requests

params = {
    'url': 'https://example.com',
    'api_key': 'YOUR_KEY',
    'format': 'jpeg',
    'width': 1280,
    'height': 720,
    'quality': 90,
}

response = requests.get('https://pxshot.dev/api/capture', params=params)
response.raise_for_status()

with open('screenshot.jpg', 'wb') as f:
    f.write(response.content)

print('Duration:', response.headers.get('X-Duration-Ms'), 'ms')