Keyword: batch screenshot API · By SnapshotFlow team · Updated July 3, 2026
Batch Screenshot API: How to Capture Multiple URLs in One Request
A release report, link preview service, or website inventory rarely needs one screenshot. It needs the same capture settings applied to a list of pages, with clear results for each URL. SnapshotFlow's batch screenshot API accepts up to 10 URLs in one request, runs captures through its browser pool, and returns one result per input.
Why Batch Capture Matters in 2026
Browser automation has moved from occasional test scripts into scheduled services and agent workflows. In March 2026, Cloudflare raised its paid Browser Rendering REST limit from 3 to 10 requests per second. Google followed in May with new Chrome tooling for agent-driven web development and automated debugging.
Those releases do not measure keyword volume. They provide current evidence that vendors are investing in higher-throughput browser work. A batch endpoint helps when your application needs several consistent outputs but does not need a programmable browser session.
- Create page thumbnails for a sitemap, CMS, or client portal.
- Capture a fixed group of public pages for a release report.
- Generate visual evidence for a scheduled website inventory.
- Capture representative pages for a release report, then use separate
/diffcalls for pages that need pixel-level comparison.
What POST /batch Does
Send a JSON object with a urls array and one shared set of capture options. SnapshotFlow validates the URLs first, then processes valid targets in parallel up to the browser pool's available capacity.
| Field | Accepted value | Default |
|---|---|---|
urls | 1 to 10 public HTTP or HTTPS URLs | Required |
format | png, jpeg, webp, or pdf | png |
width | 100 to 3840 pixels | 1280 |
height | 100 to 2160 pixels | 800 |
quality | 1 to 100; useful for JPEG and WebP | 80 |
full_page | Boolean | false |
response_type | base64, paths, or image_urls | base64 |
full_page value. Put mobile and desktop captures in separate batches. The current endpoint does not accept per-URL cookies, selectors, delays, or headers.
Step 1: Send Your First Batch with cURL
Start with three public URLs and response_type=base64. This response type is portable because each successful result contains its image data.
curl -X POST "https://api.snapshotflow.com/batch" \
-H "X-Api-Key: $SNAPSHOTFLOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"urls": [
"https://example.com/",
"https://www.iana.org/help/example-domains",
"https://snapshotflow.com/docs"
],
"format": "webp",
"quality": 80,
"width": 1440,
"height": 900,
"full_page": false,
"response_type": "base64"
}' \
-o batch.json
The endpoint returns JSON rather than a multipart archive. That makes partial failures visible and lets your application decide which images to retry.
Step 2: Read Every Result
A successful response includes total and a results array. Each successful base64 item carries the normalized URL, output format, cache status, and a data URL.
{
"total": 3,
"results": [
{
"url": "https://example.com/",
"format": "webp",
"cached": false,
"image": "data:image/webp;base64,UklGR..."
},
{
"url": "https://www.iana.org/help/example-domains",
"format": "webp",
"cached": true,
"image": "data:image/webp;base64,UklGR..."
},
{
"url": "https://snapshotflow.com/docs",
"format": "webp",
"cached": false,
"image": "data:image/webp;base64,UklGR..."
}
]
}
Base64 encodes each three-byte group as four characters, as defined by RFC 4648 section 4. Budget about one-third more payload than the binary files, plus JSON overhead. Choose WebP or JPEG when response size matters, and avoid full-page images unless the workflow needs the entire document.
base64 when you need image data in the response. paths exposes storage-local paths, while the current image_urls branch returns result metadata without a public image URL.
Step 3: Save a Batch with the Node.js SDK
The official SnapshotFlow Node.js SDK exposes the same operation as client.batch(). The SDK converts camelCase options to the API request shape.
import { mkdir, writeFile } from "node:fs/promises";
import { SnapshotFlow } from "snapshotflow";
const client = new SnapshotFlow({
apiKey: process.env.SNAPSHOTFLOW_API_KEY!,
});
const batch = await client.batch({
urls: [
"https://example.com/",
"https://www.iana.org/help/example-domains",
"https://snapshotflow.com/docs",
],
format: "webp",
quality: 80,
width: 1440,
height: 900,
responseType: "base64",
});
await mkdir("captures", { recursive: true });
for (const [index, item] of batch.results.entries()) {
if (item.error) {
console.error(`${item.url}: ${item.error}`);
continue;
}
if (!item.image) {
console.error(`${item.url}: response did not include image data`);
continue;
}
const comma = item.image.indexOf(",");
const bytes = Buffer.from(item.image.slice(comma + 1), "base64");
await writeFile(`captures/${index + 1}.webp`, bytes);
}
Do not treat an HTTP 200 response as proof that every page rendered. Inspect item.error and item.image for each entry.
Step 4: Scale Beyond 10 URLs
Split larger jobs into groups of 10. Submit groups in sequence first. Add limited group concurrency only after you have measured response size, timeout behavior, and account limits.
function chunks<T>(items: T[], size: number): T[][] {
const groups: T[][] = [];
for (let i = 0; i < items.length; i += size) {
groups.push(items.slice(i, i + size));
}
return groups;
}
const failed: string[] = [];
for (const urls of chunks(allUrls, 10)) {
const batch = await client.batch({
urls,
format: "jpeg",
quality: 75,
width: 1280,
height: 800,
responseType: "base64",
});
for (const item of batch.results) {
if (item.error) failed.push(item.url);
// Save or upload item.image here.
}
}
console.log({ failed });
This loop keeps only one batch response in memory. Upload or write each decoded image before requesting the next group. A list of 1,000 base64 screenshots can exhaust a Node process if you retain every payload.
Caching and Deterministic Captures
SnapshotFlow builds a cache key from the URL and capture options. Repeating the same item with the same settings can return cached: true; cache hits do not consume another screenshot quota unit. Change the width, height, format, quality, or full-page setting and the request produces a different cache key.
Pin every option you care about. Browser rendering can differ across operating systems, browser versions, fonts, and settings. The Playwright visual comparison guide gives the same operational warning for screenshot baselines. A hosted API centralizes the browser environment, but your application should still record capture settings beside each output.
- Normalize and deduplicate URLs before submission.
- Set explicit width, height, format, and full-page behavior.
- Use one batch per viewport or output policy.
- Store the source URL and capture options with the image.
Handle Validation and Capture Failures Differently
The endpoint has two failure layers. URL validation happens before browsers start. Capture failures happen per item.
| Failure | Observed behavior | Recommended action |
|---|---|---|
| Empty list or more than 10 URLs | HTTP 400 with VALIDATION_ERROR | Fix the request; do not retry unchanged. |
| Malformed or private-network URL | The request fails during upfront URL validation | Remove or correct the URL. Use a self-hosted deployment for internal targets. |
| Navigation or rendering failure | The affected result contains error; other items can succeed | Retry only failed URLs with a capped backoff. |
| Quota exhausted for an item | The item contains error: "QUOTA_EXCEEDED" | Stop new groups and review quota before retrying. |
| Rate limit or server error | The SDK can retry 429, 5xx, and network errors | Keep retries bounded and inspect the final response. |
The current batch route claims one quota unit before each uncached render. If rendering fails after that claim, the request path does not refund it. Keep retries capped and stop the queue when repeated failures point to a persistent target problem.
The SSRF guard blocks loopback, private, and link-local targets on the hosted service. For a staging site behind a VPN or firewall, follow the authenticated and internal page guidance and run SnapshotFlow inside the network.
Choose the Endpoint That Matches the Job
| Job | Use | Reason |
|---|---|---|
| 1 to 10 URLs with shared settings | POST /batch | One request and one result array. |
| One URL with cookies, selectors, headers, or scripts | GET /screenshot | The single endpoint exposes the full capture option set. |
| Return immediately and receive a webhook | GET /screenshot?async=true | The batch endpoint is synchronous. |
| Compare two rendered pages | GET /diff | Returns changed pixels, percentage, and an optional diff image. |
Read the batch endpoint reference for the request schema. If you need one full-page capture before building a list workflow, start with the Screenshot API quick start.
Production Checklist
- Keep each request between one and 10 URLs.
- Group URLs by viewport and output settings.
- Use
base64when the response must contain portable image data. - Inspect every result for
errorbefore saving images. - Retry failed URLs, not the entire successful batch.
- Decode and persist each group before loading the next one.
- Record source URL, capture options, cache status, and capture time in your application.
Batch Screenshot API FAQ
How many URLs can SnapshotFlow capture in one batch?
POST /batch accepts between one and 10 URLs. Split a larger input list into groups of 10.
Can each URL use different screenshot settings?
No. One batch shares format, quality, width, height, full_page, and response_type across every URL. Use separate batches when targets need different settings.
Does one failed capture fail the entire batch?
Navigation and rendering failures appear on the affected result while other items can succeed. URL validation runs before capture, so one malformed or blocked URL rejects the request before rendering starts.
Is the batch endpoint asynchronous?
No. POST /batch returns after its items finish. Use asynchronous single captures with GET /screenshot, async=true, and a webhook when a workflow must return immediately.
Sources
Test One Batch Before You Build the Queue
Create an API key, send two or three representative URLs, and measure the response your application will store. Then add chunking and retries around observed behavior.