How to Make Screenshot APIs Fast: 5 Optimizations
Most screenshot API calls take longer than they need to. The bottleneck is rarely the API itself. It is the choices you make when calling it: the output format, the viewport size, which resources the browser loads, and whether you send one request or fifty. Five adjustments cover the majority of avoidable overhead.
1. Use a compressed output format
PNG is lossless and therefore the largest output format by default. For thumbnails, preview cards, and social images where exact pixel accuracy is not required, WebP or JPEG cut file size by 50 to 80 percent with no perceptible quality loss at typical display sizes.
import { Rendex } from "@copperline/rendex"
import { writeFileSync } from "fs"
const rendex = new Rendex(process.env.RENDEX_API_KEY!)
// WebP — ~38 KB vs 210 KB for PNG
const webp = await rendex.screenshot({
url: "https://example.com",
format: "webp",
quality: 82,
})
writeFileSync("capture.webp", webp.image)
2. Right-size the viewport
The default viewport is 1280×800 at 2× device pixel ratio. For thumbnail generation, set width to your target size instead.
const thumb = await rendex.screenshot({
url: "https://example.com",
format: "webp",
width: 400,
height: 300,
deviceScaleFactor: 1,
})
3. Block resources you do not need
Third-party analytics scripts, font files, and video embeds add load time. Use blockResourceTypes to skip them.
const result = await rendex.screenshot({
url: "https://dashboard.example.com",
format: "webp",
blockResourceTypes: ["font", "media", "other"],
})
4. Choose the right wait strategy
waitUntil: "load" fires faster than the default "networkidle2" for server-rendered pages. Use waitForSelector for client-side apps.
// Fast server-rendered page
const result = await rendex.screenshot({
url: "https://internal-dashboard.example.com",
waitUntil: "load",
})
// SPA with async content
const spa = await rendex.screenshot({
url: "https://app.example.com/dashboard",
waitForSelector: "#main-content",
waitUntil: "domcontentloaded",
})
5. Submit multiple captures in one batch call
The batch endpoint accepts 5 to 500 URLs per call and processes them concurrently.
const batchResult = await rendex.batch({
urls: productUrls,
defaults: {
format: "webp",
quality: 82,
width: 640,
waitUntil: "load",
blockResourceTypes: ["font", "media"],
},
webhookUrl: "https://yourapp.com/webhooks/screenshots",
})
console.log(batchResult.data.batchId)
Troubleshooting
Page looks broken after blocking resources. Start with only "font" and "media". Pages that use web fonts for icons will break when fonts are blocked — inject a fallback with css: "* { font-family: sans-serif !important; }".
waitUntil: "load" returns a blank page. The page renders content after the load event. Use waitForSelector with a CSS selector that appears when content is ready.
Batch results have some failed jobs. Poll /v1/jobs/:jobId for each job. Failed jobs return an error code and message.
Next steps
- Free screenshot tool — test format and viewport settings without code
- SPA screenshot waitFor guide — framework-specific selector patterns
- API reference — full batch schema and plan-based limits
Get a free API key (100 calls/month, no credit card) or see pricing for higher-volume plans.
Top comments (0)