SCREENSHOT API

Pixel-perfect website screenshots from one API call.

Turn any URL into a crisp PNG or JPEG — full-page, viewport or element-level — with retina scaling, dark mode and cookie-banner blocking built in. No headless browsers to maintain.

POST https://api.ottersnap.com/v1/screenshot

Full-page or viewport

Capture the whole scroll height or just the visible fold — one flag switches between them.

Element-level captures

Pass a CSS selector to screenshot exactly one card, chart or section instead of the page.

Retina 2× scale

Device scale factor two on request, so captures stay crisp on studio displays and phones alike.

Dark mode emulation

Force prefers-color-scheme dark to capture how a page looks at night, automatically.

Cookie banners, blocked

Consent popups and newsletter modals are hidden before the shot, so renders stay clean.

Wait your way

A delay window and networkidle waiting let lazy-loaded pages finish painting before capture.

Call it in seconds

JSON in, rendered file out. Works with anything that can make an HTTP request.

CURL
curl -X POST https://api.ottersnap.com/v1/screenshot \
  -H "Authorization: Bearer otter_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://github.com", "fullPage": true, "scale": 2}' \
  --output shot.png
NODE.JS
const res = await fetch("https://api.ottersnap.com/v1/screenshot", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.OTTERSNAP_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ url: "https://github.com", fullPage: true }),
});

fs.writeFileSync("shot.png", Buffer.from(await res.arrayBuffer()));
PYTHON
import os, requests

res = requests.post(
    "https://api.ottersnap.com/v1/screenshot",
    headers={"Authorization": f"Bearer {os.environ['OTTERSNAP_KEY']}"},
    json={"url": "https://github.com", "fullPage": True},
)

open("shot.png", "wb").write(res.content)

Parameters

NameTypeDescription
urlstring · requiredThe page to render. Must start with https:// or http://.
formatstring · default pngOutput format: png or jpeg.
fullPageboolean · default trueCapture beyond the viewport when true.
widthinteger · default 1280Viewport width in CSS pixels (16–2560).
heightinteger · default 800Viewport height in CSS pixels (16–2560).
scaleinteger · default 1Device scale factor. Set 2 for retina captures.
darkModeboolean · default falseEmulate prefers-color-scheme: dark.
delayinteger · default 0Extra milliseconds (0–10000) to wait after the page loads — useful for late fonts.
cookieBlockboolean · default falseHide common cookie banners and consent modals.
selectorstring · optionalCSS selector for an element capture instead of the whole page.

Questions about the screenshot api

How fast is a screenshot?

Most pages render in a few seconds. The first render of a page pays the full cost; repeat renders of the same URL hit our cache and come back faster and free of charge.

Can I capture pages that require login?

Not with this endpoint today — it renders public pages. For private dashboards, render on your own infrastructure or contact us about authenticated sessions.

What happens if a page fails to load?

You get a clear HTTP error instead of a blank image, and failed renders never count against your monthly quota.

Ready to render?

Free tier, no credit card. Upgrade only when you scale.

Get your API key