Install and keys
Everything runs in your user’s browser. There’s no headless renderer on our side, which is why the capture matches what they were actually looking at.
Install
Two ways in. Use the package if you have a bundler; use the script tag if you don’t, or if you’d rather not add a dependency to ship one button.
npm i @screen2api/sdkThe script build is 31 KB gzipped (27 KB brotli), has no dependencies, and exposes a single global — window.screen2api — carrying the same API as the package. Pinning an exact version and supplying the integrity hash means a compromised CDN still can’t change what runs on your page; every released version has one.
There is also a floating channel at /sdk/v0/screen2api.min.js that picks up patches on its own. Be aware that while we’re on 0.x, semver permits breaking changes in a minor release — so pin the exact version in production until 1.0.
Create one client and keep it around. It caches your project config and any assets it has already inlined, so the second capture on a page is much faster than the first.
import { createClient } from '@screen2api/sdk'
export const s2a = createClient({
publishableKey: 'pk_live_…',
})The package ships both module formats, so require resolves to the CommonJS build and import to the ESM one. Either is fine — but note this is a browser SDK. Requiring it from a bundler that outputs CommonJS works; calling capture() in Node does not, and throws a Screen2ApiError with code unsupported rather than failing somewhere confusing.
Both of those first two tabs need a build step. Pasted into a plain <script> on an HTML page they fail immediately — require is not defined for the CommonJS one and Cannot use import statement outside a module for the ESM one. Neither message mentions bundlers, so it reads like a broken package. If you are not running a bundler, use the script tag: it needs no build step and exposes one global, screen2api.
The publishable key is meant to be in your client bundle. What protects your project is the origin allowlist in Settings, not the key being secret.
Keys and origins
There are two kinds of key and they are not interchangeable. Getting this wrong is the most common way to end up either broken or exposed.
| Option | Type | Default | Description |
|---|---|---|---|
pk_live_… / pk_test_… | publishable | browser | Ships in your frontend. Used by the SDK to create captures. Anyone can read it out of your bundle, which is fine — a live publishable key only works from an origin you have listed. |
sk_live_… / sk_test_… | secret | server | Full access to your project over the REST API: read any capture, mint fresh URLs, use the file API. Never put one in a browser. Stored here only as a SHA-256 hash and shown once — if you lose it, rotate it. |
The origin allowlist
A pk_live_ key is refused unless the request’s Origin is on the project’s list. Add every origin you serve from, including the scheme and any port:
https://app.example.com
https://example.com
http://localhost:3000pk_test_ keys skip the check entirely, which is what makes them convenient locally and unsuitable for production. Test captures count against a smaller quota and are the ones to use in CI.
If captures work on your machine and fail once deployed, this is almost always why — look for forbidden_origin in the network response.
Environments
Live and test keys address the same project but separate data, so a test run cannot pollute the captures your team is looking at. Webhooks fire for both; the payload carries the project id so you can route them apart if you want to.
Everything else
- CapturingChoose what to capture with a selector, export it as PNG, JPEG, WebP, SVG, PDF, HTML or CSV, and redact anything that should never leave the browser.
- The editorLet people crop, draw on, redact and caption a capture before it is sent — plus the breadcrumbs of what the page was doing and a visual diff between two captures.
- DeliveryReceive finished captures at your own endpoint with a signed payload, verify the signature, and run captures on a schedule without a browser open.
- IntegrationsUse screen2api from React, wire export buttons up with data attributes and no JavaScript, or drive the capture engine directly.
- API referenceEvery option, method and result the screen2api browser SDK exposes, and every error code it can throw.
- REST APIRead captures, list files and manage projects from your own backend with a secret key.
- LimitsWhat counts against your allowance, how long captures are kept, and the size, rate and browser limits that apply.
- TroubleshootingFixes for blank captures, missing fonts, cross-origin images, cut-off content and captures that never arrive at your webhook.