SCREENSHOT API · REAL CHROMIUM

Capture the web without operating a browser fleet.

Send a public URL and receive a PNG or JPEG rendered by a warm Chromium pool. Capture a viewport or the full page, emulate phones and tablets, switch dark mode on, and cache stable results without counting repeat requests against quota.

~1 secTYPICAL COLD RENDER
~10 msCACHED RESPONSE
100–3840VIEWPORT WIDTH
30 secMAX TIMEOUT

One authenticated GET returns the image

Use the x-api-key header from server code. Query-string keys are supported for controlled environments, but signed URLs are the safer choice when an image URL must be public.

curl -H "x-api-key: $OGSHOT_API_KEY" \ "https://ogshot.dev/v1/screenshot?url=https://example.com&width=1440&height=900" \ -o example.png

The response includes x-cache: MISS for a real browser render and x-cache: HIT when an identical request is served from disk. The cache key includes every option that can change pixels.

Choose the browser state, not just the rectangle

Viewport width and height range from 100×100 through 3840×2160. Device presets such as iPhone 15 and Pixel 7 set the viewport, device scale factor, user agent, and mobile behavior together. Use full_page=true for the document rather than only the initial viewport, and dark_mode=true to emulate prefers-color-scheme: dark.

Navigation can wait for load, DOM content, or network idle. An additional delay allows late animation, chart, or application state to settle. PNG is the lossless default; JPEG supports adjustable quality when file size matters more than exact edges. A fresh flag bypasses the existing cached output when you intentionally need a new capture.

const query = new URLSearchParams({ url: "https://example.com/dashboard", device: "iPhone 15", full_page: "true", dark_mode: "true", wait_until: "networkidle", delay: "500", }); const response = await fetch(`https://ogshot.dev/v1/screenshot?${query}`, { headers: { "x-api-key": process.env.OGSHOT_API_KEY }, }); const image = Buffer.from(await response.arrayBuffer());

Where the API fits

Common uses include visual regression artifacts, documentation thumbnails, customer-site previews, link archives, website galleries, support attachments, scheduled reports, and product screenshots. The service is best for public pages whose output can be rendered deterministically. It does not currently provide authenticated browser sessions, residential proxies, CAPTCHA solving, or stealth guarantees for hostile third-party targets.

When the source is your own HTML rather than an existing URL, use POST /v1/render. That endpoint avoids deploying a temporary webpage and is the natural route for social cards, report graphics, certificates, receipts, and other generated visual assets.

A screenshot request is also a network request

The target hostname must resolve entirely to public unicast addresses. Private networks, loopback, cloud metadata addresses, link-local ranges, and reserved blocks are refused. The same validation runs inside the browser for redirects, images, scripts, iframes, and popups; service workers are blocked. Read the security overview or the deeper SSRF engineering article.

The API is intentionally not a way to screenshot localhost or private dashboards in production. Local development can opt into private networks explicitly, but that setting should never be enabled on an internet-facing deployment.

Caching makes stable captures economical

Only requests that launch Chromium count as renders. An identical request served from cache is free, which means a screenshot referenced repeatedly by a popular page does not consume quota each time it is viewed. The free plan includes 100 renders per calendar month, Studio includes 5,000 for $19, and Agency includes 25,000 for $49.

If the page changes while the URL and capture options stay the same, use fresh=true or add a content version to your own request. The fresh render replaces the cached copy.

Failures are machine-readable

Policy blocks, invalid parameters, missing credentials, quota exhaustion, navigation timeouts, and unexpected renderer failures return distinct status codes and JSON error bodies. This lets an application decide whether to retry, fix input, upgrade, or surface a useful message rather than treating every failure as a generic server error.

Start in the browser playground, then copy the equivalent request into your application. For social-preview generation, see the template catalog and Next.js guide.

URL IN · PIXELS OUT

Capture the first 100 pages free.

Use every screenshot option on the free plan. Cached responses do not count.