Screenshot API quickstart (curl, JavaScript, Python, PHP)
1. Get an API key
Section titled “1. Get an API key”- Request access by email at support@shotvik.com.
- Once you have access, you get an API key (it looks like
shotvik_<key_id>_<secret>) and its signing secret, which you only need for signed OG image links. Shotvik can’t show either of them again later, so store them safely. - Store the key as an environment variable. Don’t commit it to your repository:
export SHOTVIK_API_KEY="shotvik_..."2. Take your first screenshot
Section titled “2. Take your first screenshot”This request renders https://example.com and saves it as a PNG (POST /v1/screenshot, key in the Authorization: Bearer header).
curl https://api.shotvik.com/v1/screenshot \ -H "Authorization: Bearer $SHOTVIK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"url": "https://example.com", "format": "png"}' \ --fail-with-body --output screenshot.pngNode.js 18+ (native fetch, no dependencies):
import { writeFile } from 'node:fs/promises';
const res = await fetch('https://api.shotvik.com/v1/screenshot', { method: 'POST', headers: { Authorization: `Bearer ${process.env.SHOTVIK_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ url: 'https://example.com', format: 'png' }),});
if (!res.ok) { const { error } = await res.json(); throw new Error(`Shotvik ${res.status} ${error.code}: ${error.message} (${error.request_id})`);}await writeFile('screenshot.png', Buffer.from(await res.arrayBuffer()));import { writeFile } from 'node:fs/promises';
interface ScreenshotRequest { url: string; format?: 'png' | 'jpeg' | 'pdf'; width?: number; // 100–3840, default 1280 height?: number; // 100–3840, default 800 full_page?: boolean; device_scale_factor?: number; // 1–3 jpeg_quality?: number; // 1–100, only with format 'jpeg' wait_until?: 'load' | 'domcontentloaded' | 'networkidle' | 'commit'; delay_ms?: number; // 0–10000 dark_mode?: boolean; block_ads?: boolean; block_cookie_banners?: boolean; cache?: boolean; cache_ttl?: number; // 60–2592000 seconds}
interface ShotvikError { error: { code: string; message: string; request_id: string; reason?: string; retry_after?: number };}
async function screenshot(body: ScreenshotRequest): Promise<Buffer> { const apiKey = process.env.SHOTVIK_API_KEY; if (!apiKey) throw new Error('SHOTVIK_API_KEY is not set');
const res = await fetch('https://api.shotvik.com/v1/screenshot', { method: 'POST', headers: { Authorization: `Bearer ${apiKey}`, 'Content-Type': 'application/json' }, body: JSON.stringify(body), }); if (!res.ok) { const { error } = (await res.json()) as ShotvikError; throw new Error(`Shotvik ${res.status} ${error.code}: ${error.message} (${error.request_id})`); } return Buffer.from(await res.arrayBuffer());}
await writeFile('screenshot.png', await screenshot({ url: 'https://example.com', format: 'png' }));Uses requests (pip install requests):
import osimport requests
res = requests.post( "https://api.shotvik.com/v1/screenshot", headers={"Authorization": f"Bearer {os.environ['SHOTVIK_API_KEY']}"}, json={"url": "https://example.com", "format": "png"}, timeout=60,)if not res.ok: err = res.json()["error"] raise RuntimeError(f"Shotvik {res.status_code} {err['code']}: {err['message']} ({err['request_id']})")
with open("screenshot.png", "wb") as f: f.write(res.content)Uses the built-in cURL extension:
<?php$ch = curl_init('https://api.shotvik.com/v1/screenshot');curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . getenv('SHOTVIK_API_KEY'), 'Content-Type: application/json', ], CURLOPT_POSTFIELDS => json_encode(['url' => 'https://example.com', 'format' => 'png']), CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 60,]);
$body = curl_exec($ch);$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);curl_close($ch);
if ($body === false || $status >= 400) { $err = json_decode((string) $body, true)['error'] ?? null; throw new RuntimeException($err ? "Shotvik $status {$err['code']}: {$err['message']} ({$err['request_id']})" : "Shotvik request failed (HTTP $status)");}file_put_contents('screenshot.png', $body);3. Check the result
Section titled “3. Check the result”Open screenshot.png. If the request fails, you get a JSON error with a code, a message and a request_id. See Errors.
Useful response headers:
X-Usage-Used/X-Usage-Remaining: your monthly usage;X-Shotvik-Warnings: only present if fonts or images on the page were skipped (details);X-Target-Status: the status the target site returned;X-Request-Id: include it if you contact support.
A request counts toward your monthly quota only when you get an image or PDF back, even if the target page itself returned a 4xx/5xx status. Timeouts, errors on our side, blocked requests and cache hits don’t count. See Rate limits and plans.
Next steps
Section titled “Next steps”- All options (JPEG, PDF, full page, dark mode, ad and cookie-banner blocking): Screenshot a URL.
- Render your own HTML: Render HTML.
- OG images and
<meta>tags without leaking your key: OG images and Signed URLs.
Shotvik is in private beta. Request access: support@shotvik.com · Privacy