Skip to main content
Context.dev’s Screenshot API finds and opens any page in a browser, captures a PNG screenshot, hosts it on a CDN, and sends back a URL to access it. It can dismiss cookie banners, capture the full scrollable height, and find standard pages (like pricing, login, etc.) for a given domain without you entering the exact path.

Integrate Context.dev's Screenshot API in your app

Open in Cursor

Prerequisites

  • A Context.dev API key. Sign up at context.dev/signup, copy the key from the dashboard (prefix ctxt_secret_), and export it:
    export CONTEXT_DEV_API_KEY="ctxt_secret_..."
    
  • An SDK (optional). Install for your language, or skip the install and call directly with curl:
    npm install context.dev
    

Capture a screenshot

There are two ways to point at the page you want to capture:
  1. Give a specific URL: pass directUrl with the full URL (e.g. https://stripe.com/pricing).
  2. Give a domain and a page type: pass domain (e.g. stripe.com) for the homepage. Add a page type (choose from login, signup, blog, careers, pricing, terms, privacy, or contact) to let Context.dev’s resolver find the right URL on the domain.
# 1. Give a specific URL
curl -G https://api.context.dev/v1/web/screenshot \
  -H "Authorization: Bearer $CONTEXT_DEV_API_KEY" \
  --data-urlencode "directUrl=https://stripe.com/pricing"

# 2. Give a domain and a page type
curl -G https://api.context.dev/v1/web/screenshot \
  -H "Authorization: Bearer $CONTEXT_DEV_API_KEY" \
  --data-urlencode "domain=stripe.com" \
  --data-urlencode "page=pricing"
5 credits per successful call Context.dev finds and opens the page, closes any cookie consent pop-ups (when handleCookiePopup is set to "true"), takes a screenshot, uploads it to a CDN and returns the public URL.
Captures are cached for one day by default; pass maxAgeMs: 0 to force a fresh render, or up to 30 days for longer reuse.

Request Parameters

Pass either domain or directUrl, not both.
ParameterTypeDefaultDescription
domainstringRequired unless directUrl is provided. Domain to screenshot (e.g. stripe.com).
directUrlstring (URI)Required unless domain is provided. Exact URL to screenshot.
fullScreenshotstring enum ("true" / "false")"false""true" captures the full scrollable height; otherwise a single viewport frame.
handleCookiePopupstring enum ("true" / "false")"false"When "true", dismisses the cookie/consent banner before capture.
viewportobject { width, height }{ width: 1920, height: 1080 }Browser viewport in pixels. width 240–7680, height 240–4320.
pageenum (login / signup / blog / careers / pricing / terms / privacy / contact)Resolve the right URL for the page type via link-scraping heuristics. Only valid with domain, not directUrl.
maxAgeMsinteger86400000 (1 day)Return a cached capture younger than this. 0 forces fresh. Max 2592000000 (30 days).
waitForMsinteger3000Browser wait after page load before capture. Min 0, max 30000 (30 seconds).
timeoutMSintegerAbort with 408 if the request exceeds this many milliseconds. Min 1000, max 300000 (5 min).

Response

{
  "status": "ok",
  "code": 200,
  "domain": "stripe.com",
  "screenshot": "https://media.brand.dev/screenshots/cache/f7d1dab4f1fd942032eeb849f1ad9df7.png",
  "screenshotType": "viewport",
  "width": 1920,
  "height": 1080
}
FieldTypeDescription
statusstring"ok" on success.
codeintegerHTTP status code, echoed for convenience.
domainstringNormalized domain that was processed. For directUrl requests, the host parsed out of the URL.
screenshotstringPublic CDN URL of the captured PNG. Content-addressed: the same query against the same target returns the same URL until maxAgeMs expires.
screenshotTypeenum"viewport" or "fullPage". Mirrors what was actually captured.
widthintegerWidth of the captured image in pixels.
heightintegerHeight in pixels. With fullScreenshot: "true", this is the full scrollable height (often 5–20× the viewport).

Handle errors

The endpoint surfaces four failure modes:
StatusMeaningWhat to do
400Validation error: neither domain nor directUrl provided, both provided at once, page combined with directUrl, or a malformed valueSurface as a user-facing error. The response body’s error_code distinguishes INPUT_VALIDATION_ERROR, WEBSITE_ACCESS_ERROR, etc.
401Missing or invalid API keyRe-check the env var and the dashboard.
408REQUEST_TIMEOUT: the page didn’t render before timeoutMS elapsed (typically a cold hit)Retry once with backoff, or prefetch the capture ahead of time.
500Transient renderer or server errorRetry with exponential backoff.
A retry pattern that covers 500:
import ContextDev from "context.dev";

const client = new ContextDev({ apiKey: process.env.CONTEXT_DEV_API_KEY });

async function screenshotWithRetry(domain: string, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await client.web.screenshot({ domain });
    } catch (err: any) {
      if (err.status === 500 && i < maxRetries - 1) {
        await new Promise((r) => setTimeout(r, 2 ** i * 1000));
        continue;
      }
      throw err;
    }
  }
}
For the full error code catalog, see Troubleshooting.

Use cases

  • Auto-generate on-brand campaign and preview images for every page.
  • Give your coding agent screenshotting tools to do QA or classification tasks.
  • Archive dated visual snapshots of pages for compliance or audits.
  • Power server-side link-preview / share-card generation for chat apps, comments, and any paste-a-URL flow.

Next steps

Prefetch for Faster Response

Hide cold-hit latency from your users.

Handle Rate Limits

Backoff strategies, client cache, and prefetch fallbacks.

Best Practices

Caching, error handling, and key hygiene.

Troubleshooting

Status codes, retry patterns, and common errors.