Browser SDK · no runtime dependencies

Screenshots, PDFs and exports that look exactly like your app

One button turns any part of your app into a file. Users can draw on it before it goes. You get a URL and your own metadata back, and you never write a line of blob-wrangling code.

The playground is all client-side. Nothing you capture there leaves your machine.

Live in your browser

Invoice INV-2048

Northwind Trading Co.

Issued 27 July · Net 30

Subtotal

$12,480.00

VAT (20%)

$2,496.00

Due

$14,976.00

Billed this quarter

Line items

Consulting retainer$6,000.00
Implementation$4,200.00
Support, 12 months$1,800.00
Training, 2 days$480.00

The file it produced

Press the button. The gradient, the webfont, the live <canvas> and the half-scrolled list all come across — and none of it leaves this machine.

01

The screenshot matches the screen

Most libraries read your stylesheets and lay the page out again from scratch. Dark mode, CSS variables, container queries, whatever your third-party widgets are doing — some of it survives the round trip and some of it does not. We read the computed style of every node instead. That is the browser telling us what it already decided, so there is nothing left to guess at.

02

One element is enough

Give it a selector and you get that element: an invoice, a chart, a single card. If a panel inside it is scrolled halfway down, the capture is scrolled halfway down too. You can also grab just the visible window, or the whole page from top to bottom.

03

Users can mark it up first

Switch the editor on and they get arrows, boxes, a highlighter, freehand, text, crop, and a redaction tool that genuinely destroys the pixels underneath. Plus a caption box, which is usually the part that tells you what they were actually complaining about.

04

No blob handling on your side

The SDK gets a signed URL and uploads straight to storage. Then we POST you the finished file URLs with whatever context you attached at the call site — an invoice id, a ticket number, a user. Nothing to decode, nothing to convert, no multipart parser to maintain.

The client half

Point it at a selector, pick your formats, and attach whatever your backend will need to make sense of the file when it arrives.

import { createClient } from '@screen2api/sdk'

const s2a = createClient({ publishableKey: 'pk_live_…' })

// The whole page
await s2a.capture()

// Or just the invoice, as three files
await s2a.capture({
  target: '#invoice',
  formats: ['png', 'pdf', 'svg'],
  params: { invoiceId: 'inv_1042', userId: 'usr_77' },
})

The server half

Signed, resendable from the dashboard when your endpoint was down, and your params come back word for word — so you know which record the file belongs to.

{
  "event": "capture.completed",
  "capture": {
    "id": "cap_9f3c…",
    "caption": "The VAT line looks wrong",
    "params": { "invoiceId": "inv_1042", "userId": "usr_77" },
    "files": [
      { "format": "png", "url": "https://…/capture.png", "bytes": 481203 },
      { "format": "pdf", "url": "https://…/capture.pdf", "bytes": 262144 }
    ]
  }
}

Ask for as many as you want

The slow part — working out the styles, pulling in the fonts and images, drawing the thing — only happens once. PNG plus PDF plus SVG costs barely more than PNG on its own. And point it at a table with csv to get the data itself, not a picture of it.

PNGJPEGWEBPPDFSVGHTMLCSV