POST /v1/render/screenshots loads a URL (or renders HTML you send) in a warm browser, captures it, composes it with a style and encodes it, in one call.

Take a styled screenshot

bash
curl -s https://beta-api.b3os.org/v1/render/screenshots \ -H "Authorization: Bearer $B3OS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"url": "https://example.com", "viewport": {"width": 1600, "height": 900}, "style": {"background": "midnight", "frame": "browser-dark"}, "format": "webp"}'

The JSON response lists the artifacts, primary image first, each with a signed url, its size and expires_at, plus timing with the phases of the call, such as navigate, capture, compose and encode. Preset names such as midnight and browser-dark come from GET /v1/render/presets, which also returns a preview of each.

Get the image bytes instead

Send Accept: image/webp, image/png or image/jpeg and the response body is the image:

bash
curl -s https://beta-api.b3os.org/v1/render/screenshots \ -H "Authorization: Bearer $B3OS_API_KEY" \ -H "Content-Type: application/json" \ -H "Accept: image/png" \ -d '{"url": "https://example.com", "format": "png"}' -o example.png

Capture one element

target captures a single element, found the same way as in browser actions:

json
{ "url": "https://example.com/pricing", "target": { "selector": "#plans" }, "dpr": 2, "format": "png" }

An element that never appears, or stays outside the viewport after scrolling to it, fails with target_not_found. full_page: true captures the whole scrollable page instead of the viewport.

Options

FieldDefaultMeaning
url or htmlThe page to load, or HTML to render with no network access
profilenoneA vision profile to load first, to capture a signed-in page
viewportWidth 320 to 3840 and height 240 to 2160, in CSS pixels
dpr1Device pixel ratio: 1, 2 or 3
wait_untilloadload, domcontentloaded or networkidle
wait_for_ms0Extra settle time after the page is ready, up to 10 seconds
themeautoEmulate a light or dark color scheme; auto leaves the page's default
hidenoneCSS selectors to hide before capture, such as cookie banners and chat widgets
block_adstrueBlock ads and trackers
stylenonebackground, frame and the other preset names, plus overrides
format, qualitywebp, 90webp, png or jpeg; quality applies to WebP and JPEG
variantsnoneUp to 4 extra encodings of the same capture, each with format, an optional width and quality

Each variant is its own artifact and bills one more render.screenshot; the page is captured once.

When the page is ready

By default render captures once the page has loaded and its network has been quiet for a short window, ignoring requests that hang. Pages that animate content in after load can be captured mid-animation. For those, wait for something specific:

json
{ "url": "https://example.com", "wait_until": "networkidle", "wait_for_ms": 1500 }

Keep, fetch and delete

Screenshots are synchronous, so a stored screenshot has always succeeded. They are kept for 7 days. GET /v1/render/screenshots/{screenshot_id} returns one with fresh artifact URLs, GET /v1/render/screenshots lists them, and DELETE removes one and its artifacts; their URLs stop working within a minute.

Ask a question... ⌘I