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
| Parameter | Type | Required | Description |
|---|---|---|---|
| url | string | required | The URL to capture. https:// is assumed when the protocol is missing. |
| api_key | string | required | Your API key. Alternatively pass as an X-API-Key request header. |
| format | string | optional | Output format: png (default), jpeg, webp, or pdf. Pro/Business plan required for non-PNG. |
| width | integer | optional | Viewport width in pixels. Default: 1280. Min: 320. Max by plan: Free 1280, Pro 1920, Business 3840. |
| height | integer | optional | Viewport height in pixels. Default: 720. Min: 200. Max by plan: Free 720, Pro 1080, Business 2160. |
| full_page | boolean | optional | Capture the full scrollable page instead of only the viewport. Default: false. Pro/Business required. |
| delay | integer | optional | Milliseconds to wait after page load before capturing. Default: 0. Max: 10000. Pro/Business required. |
| quality | integer | optional | Image quality 1-100 for JPEG/WebP output. Default: 80. Ignored for PNG and PDF. |
| transparent | boolean | optional | Omit the page background for a transparent PNG. PNG format only. Pro/Business required. |
| headers | string | optional | JSON object of extra HTTP headers to send to the target page, e.g. {"X-Auth-Token":"secret"}. URL-encode it. Pro/Business required. |
| block_js | boolean | optional | Disable JavaScript on the target page before rendering. Business plan required. |
| selector | string | optional | CSS selector to clip the screenshot to one element, e.g. #chart. If it does not match, the full viewport is returned. Business plan required. |
Response Format
Successful responses (HTTP 200) return raw binary image or PDF data. The following headers are always included:
Content-Type: image/png, orimage/jpeg,image/webp,application/pdfContent-Length: byte size of the response bodyX-Screenshot-Id: unique ID for this screenshot, logged in your dashboardX-Duration-Ms: time in milliseconds taken to capture the pageX-RateLimit-Remaining: requests remaining in the current per-minute windowX-Monthly-Used: screenshots used so far this billing periodX-Monthly-Limit: total monthly limit on your current planCache-Control: public, max-age=300: responses are cacheable for 5 minutes
Error responses return JSON: { "ok": false, "error": "message" }
Error Codes
| Status | Name | Description |
|---|---|---|
| 400 | Bad Request | Missing required parameter (url or api_key), or invalid URL. |
| 401 | Unauthorized | Invalid, inactive, or missing API key. |
| 403 | Forbidden | Origin restriction violation, or plan does not support the requested feature (e.g. non-PNG format on Free plan). |
| 429 | Too Many Requests | Monthly screenshot limit exceeded or per-minute rate limit hit. Check X-Monthly-Used / X-RateLimit-Remaining headers. |
| 502 | Bad Gateway | The target site could not be loaded: domain does not resolve, connection refused or reset, invalid SSL certificate, or a redirect loop. |
| 504 | Gateway Timeout | The target page took too long to load. Retry, or use the delay parameter for slow pages. |
| 500 | Internal Server Error | Screenshot capture failed (e.g. page unreachable, browser timeout). |
Rate Limits
Two separate limits apply: a monthly quota, enforced per account, and a per-minute burst limit, enforced per API key. Exceeding either returns HTTP 429.
| Plan | Monthly | Per Minute | API Keys | Formats |
|---|---|---|---|---|
| Free | 50 | 5 | 1 | PNG |
| Pro | 2,000 | 30 | 3 | PNG, JPEG, WebP, PDF |
| Business | 10,000 | 100 | 10 | All |
Official SDK
pxshot-api is the official JavaScript/TypeScript client. Zero dependencies, typed options for every parameter, works in Node 18+, browsers, and edge runtimes. Source on GitHub.
npm install pxshot-api
import Pxshot from 'pxshot-api';
import { writeFile } from 'node:fs/promises';
const pxshot = new Pxshot('px_your_key');
const shot = await pxshot.capture('https://example.com', {
format: 'png',
fullPage: true,
});
await writeFile('example.png', Buffer.from(shot.data));
console.log(`${shot.durationMs}ms, ${shot.monthlyUsed} of ${shot.monthlyLimit} used`);Errors throw a typed PxshotError with the HTTP status and the API's message. Prefer streaming? captureResponse() returns the raw Response.
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 imageJavaScript, using the 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')