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 fully-qualified URL to capture. Must include protocol (https://). |
| 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. |
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. |
| 500 | Internal Server Error | Screenshot 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.
| 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 |
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 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')