Quickstart
This guide will get you all set up and ready to use the ScreenshotBuddy API. We'll cover how our API works, how to authenticate with it, and how to make your first API request.
Every option a request accepts is listed on two pages: Taking screenshots for images and Creating PDFs for documents. The OpenAPI document is the complete reference, generated from the same definitions the API validates against.
If you are an agent rather than a person, /llms.txt indexes this
documentation for machine readers, and every page of it is also served as markdown at its own URL
with .md on the end.
Making your first API request
After obtaining your API key, you can make your first API request. Below, we'll show you how you can take a screenshot of a website using the API.
The API is served from a host of its own, api.screenshotbuddy.io,
rather than from the site you are reading this on. Every path below is relative to that base URL, and it is the
only host you ever send a token to.
Endpoint: https://api.screenshotbuddy.io/v1/snap
Note: Replace {token} with your API key. The response body is the image itself,
so write it straight to a file instead of parsing it as JSON.
curl "https://api.screenshotbuddy.io/v1/snap?url=https%3A%2F%2Fexample.com" \
-H "Authorization: Bearer {token}" \
--output screenshot.png
import { writeFile } from 'node:fs/promises';
const response = await fetch('https://api.screenshotbuddy.io/v1/snap?url=https%3A%2F%2Fexample.com', {
headers: { Authorization: 'Bearer {token}' },
});
if (!response.ok) {
throw new Error(`Request failed with status ${response.status}`);
}
await writeFile('screenshot.png', Buffer.from(await response.arrayBuffer()));
import requests
response = requests.get(
'https://api.screenshotbuddy.io/v1/snap',
params={'url': 'https://example.com'},
headers={'Authorization': 'Bearer {token}'},
)
response.raise_for_status()
with open('screenshot.png', 'wb') as file:
file.write(response.content)
<?php
$endpoint = 'https://api.screenshotbuddy.io/v1/snap?url=' . urlencode('https://example.com');
$curl = curl_init($endpoint);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, ['Authorization: Bearer {token}']);
$response = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
if ($status !== 200) {
exit('Request failed with status ' . $status);
}
file_put_contents('screenshot.png', $response);
$response = Http::withToken(config('services.screenshotbuddy.token'))
->get('https://api.screenshotbuddy.io/v1/snap', [
'url' => 'https://example.com',
])
->throw();
Storage::put('screenshot.png', $response->body());
The Laravel example uses ->throw() so a failed request raises a
RequestException. Prefer $response->failed() if you would rather handle the error
yourself.
Rate limits
Every account can ask for up to 20 renders per minute by
default. Higher plans and custom arrangements can have higher limits. Repeats we answer out of your cache are
counted apart from that, against a flat 300 per minute, so a
burst of captures you already hold does not eat into the renders you were saving. A conditional request we can
answer 304 out of that cache counts against neither; one we had to render before we could answer
it counts as the render it was.
Every response to a request that carried your token includes an X-RateLimit-Limit header with the
size of the budget that answer was counted against, and an X-RateLimit-Remaining header with what
is left of it. A signed URL is answered without them, because its answer goes to
whoever you handed the URL to rather than to you.
If you go over a limit, the API returns HTTP status 429 together with a
Retry-After header telling you how many seconds to wait before trying again.
To see where you stand before you send anything, ask /usage: it reports your credits, your plan
and both of your per-minute limits, under a limit of its own.
The rate limits page covers this in full, including the separate limit the playground runs under.
If you are rendering slow pages, or a whole list of them at once, submit them as a batch instead and collect the results afterwards, rather than holding a request open and pacing the calls yourself.
Try it in the playground
Rather than pasting a request together by hand, run one from your browser. The playground fires a real API call and hands you the matching cURL, PHP, JavaScript and Python code to paste into your project.