TheDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/betterspacx/app/llms.txt
Use this file to discover all available pages before exploring further.
/api/screenshot route launches a headless Chromium browser via Playwright and captures a viewport screenshot of any public http or https URL. The resulting PNG is returned as a Base64-encoded string and optionally cached in Cloudflare R2 for up to 7 days so repeated requests for the same URL and device type are served instantly without re-launching the browser.
This endpoint powers the “Import from URL” feature in the Betterflow editor, allowing users to screenshot any website and immediately use it as a canvas background.
Endpoint
| Property | Value |
|---|---|
| Method | POST |
| Path | /api/screenshot |
| Content-Type | application/json |
maxDuration of 60 seconds (set via export const maxDuration = 60 in the route module itself) to accommodate slow websites and Playwright startup time on cold starts. Memory is set to 1024 MB in vercel.json.
Request Body
The full URL of the website to screenshot. Must use the
http or https protocol. The URL is normalized (trailing slashes and fragments removed) before being used as a cache key.Viewport size for the screenshot. Accepted values:
"desktop"(default) — 1920 × 1080 px"mobile"— 375 × 667 px
When
true, the existing cached screenshot for this URL and device type is invalidated before capturing a new one. Defaults to false.Response Body
The captured screenshot as a Base64-encoded PNG string. Decode and render this directly in an
<img> tag or pass it to the canvas loader.The normalized URL that was screenshotted (trailing slashes and fragments stripped, lowercased).
true if the response was served from the R2 cache. false if a fresh Playwright capture was performed.The capture method used. Will be
"playwright-chromium" for a live capture. Absent when cached is true.The device type used for this capture:
"desktop" or "mobile".Example
Desktop screenshot
Mobile screenshot, force-refreshed
Caching
Screenshots are stored in Cloudflare R2 under thescreenshots/ prefix using a Base64url-encoded URL hash as the filename, keyed by device type (e.g. screenshots/<url-hash>:desktop.png). The cache TTL is 7 days. Cache reads and writes are best-effort — a cache failure never prevents a fresh capture from being attempted or returned.
If R2 is not configured (the MY_BUCKET binding is absent), caching is silently disabled and every request triggers a live Playwright capture.
Rate Limiting
Requests are rate-limited per IP address. If the limit is exceeded, the route returns429 Too Many Requests with a Retry-After header indicating when the limit resets.
Browser Setup
The route tries two strategies to launch Chromium, in order:- Local Playwright — uses a locally installed Chromium binary (installed via
npx playwright install chromium). Preferred for self-hosted deployments. @sparticuz/chromium— a serverless-compatible Chromium binary for Vercel and AWS Lambda environments. Used automatically on Vercel if the local binary is not available.
Error Responses
| Status | Description |
|---|---|
400 Bad Request | url is missing, not a string, uses a non-http/https protocol, or is an invalid URL format. |
400 Bad Request | The target website returned a network error (DNS failure, connection refused, SSL issues). |
400 Bad Request | deviceType is provided but is not "desktop" or "mobile". |
408 Request Timeout | The target website took longer than 55 seconds to reach a networkidle state. |
429 Too Many Requests | IP-based rate limit exceeded. Includes Retry-After, X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers. |
503 Service Unavailable | Playwright/Chromium binaries are not installed. |
500 Internal Server Error | An unexpected error occurred during capture. |