Skip to main content
Transformations work on a screenshot you already captured and stored. Capture once with store: true, keep the screenshotId from the response, then turn it into as many sizes as you need — the page is not loaded again. Transformations are deterministic image processing, not AI editing.
That is the whole API: pick a preset or set width / height / format, and optionally say what to cut first — a saved region, one part of it, or bounds. The screenshotId must belong to your account and remain unexpired; regions need a capture with regions=true, everything else does not.

Use the dashboard

In the signed-in Playground, capture a stored screenshot and switch from Capture to Transform. You can also open Transform screenshot from a monitor run. Neither action captures a page or consumes credits. Each output has a Source (complete screenshot, a saved region or part, a saved crop, or custom bounds), a Preset, and optional size, fit, format and quality overrides — the preset’s values show as placeholders. The target overlay and Draw bounds sit in the workspace toolbar next to the Screenshot/Regions switch; click a region box or drag on the screenshot to set an output’s source. Use as source on a region crop selects that saved crop. The Code tab shows the exact request, including a plain URL for a single output. Playground Transform mode with a saved region part selected, resize controls, and the original Tailwind CSS screenshot. Configuration example in an isolated documentation session. The demo reference and expiry are illustrative; no transformation was submitted. Generate outputs shows the maximum reservation before submitting one asynchronous job. Closing the modal stops polling, not server processing; reopening resumes the same job while it remains in the browser session. Successful siblings survive partial failure, and the result shows confirmed credits rather than estimated refunds. Customer storage credentials are one-shot. Output previews use direct provider URLs. The dashboard does not maintain a screenshot library or transformation history, and expired or oversized sources are never automatically recaptured.

Send a transformation

The URL form (GET) takes the same fields as query parameters and describes one output. It defaults to cache=true, so fetching the same link again reuses the stored output instead of charging again. outputs, webhookSecret and storage credentials are POST-only. Use region and part IDs from your own saved manifest; the example ID is a placeholder. Authentication requires the account’s bearer API key. No provider key is needed.

Presets

Any field you set overrides the preset: {"preset":"og-image","format":"png"} is a PNG OG image; {"preset":"thumbnail","width":240} is a 240-wide thumbnail. On a whole full-page screenshot, the fixed-shape presets (og-image, twitter-card, square) use the top of the page at their aspect ratio — the hero, not whatever sits in the middle of a long page. Set region, bounds or fit to choose differently.

Choose what to cut

Use one of region or bounds, not both. Original-pixel sources read the stored screenshot, whose bytes, dimensions, MIME type, size and SHA-256 are verified first. A saved crop reads the part’s own stored file instead — saved JPEG crops have already been encoded once, and result provenance records the parent screenshot hash and original bounds. Arbitrary source URLs, uploaded images, page headers, cookies and capture settings are not accepted.
Source size. Cutting original pixels requires the whole screenshot to fit within 64 MP and 24 MiB, even when you only select a small region. That covers most full-page captures, including 2× ones (a 3024-wide page up to about 21,000 px tall). For longer pages, use savedCrop: true on a region part: the limits then apply to the crop, not the page.

Size and encoding

  • width / height: give one to keep the aspect ratio (rounded to a positive integer), or both to set the box.
  • fit (with both sides): contain (default) fits everything with centered padding; cover fills the box with a centered crop; fill stretches.
  • format: jpeg, png or webp. Omitted, the output keeps the source’s family.
  • quality: 1–100, default 80. PNG is lossless and ignores it.
  • background: six-digit hex such as "#ffffff" for contain padding and JPEG transparency. Without it, PNG and WebP keep transparency and JPEG uses white.
With no size and no preset, the screenshot is only re-encoded. Every output is one select → resize → encode step; only the final image is encoded. JPEG output is re-encoded: lossless cropping or preservation of original JPEG bytes is not promised. Browser/codec upgrades can change encoded bytes; provenance records the actual engine identity.

Multiple outputs and credits

Put several outputs in an outputs array (POST only). Each is a preset name, or an object for anything more specific. Top-level fields are defaults for every output:
An output that says what to cut (region, part, bounds) replaces the default selection rather than combining with it; every other default still applies. All specifications validate before any credit reservation. One credit per output is reserved before source or cache-artifact downloads. Each newly generated successful output costs one credit. Failed outputs and verified cache hits refund that reservation. Read charged, refunded and net rather than inferring settlement from HTTP status. Single-output success returns an assetId, parent screenshotId, resolved source, the executedPlan (the resize/encode steps that ran), provenance, direct-storage media, referenceExpiresAt, cacheHit and credits. Provenance includes source/output hashes, selected bounds and the transform, browser and codec versions. Multiple outputs return ordered results, each with an index, success/error and credits, plus aggregate credits. HTTP 200 means all outputs succeeded; 207 means partial success. All failed outputs produce a typed error response. Successful siblings remain available. If settlement cannot be confirmed, an availability error supplies a job ID for free polling; it does not claim a completed refund. Do not blindly submit a second paid request.

Storage, caching and retention

Outputs are always stored: omit store or set it to true; store:false is rejected. Default storage uses transforms. Existing B2/S3/R2 overrides, custom prefixes and direct-provider URLs remain supported. No image proxy is introduced. Single-output success includes X-Scrinly-Storage-URL; multiple outputs use individual media.url values, without an ambiguous top-level storage header. Caching is opt-in with cache:true on POST and on by default for the URL form. Identity is account-, source-reference-, geometry-, operation-, destination- and engine-specific. Cached artifacts are downloaded and hash-verified, not trusted from their keys or a HEAD response alone. Missing or mismatched artifacts are regenerated; infrastructure failures do not silently trigger paid regeneration. Equivalent outputs within one request can reuse the first output only with caching enabled. Hits reuse the original assetId and metadata expiry. Cache lifetime is at most 24 hours, bounded by both the parent reference and derived metadata expiry; hits do not renew it. Reference retention is operator-controlled, initially 30 days. Expiry removes metadata only, not stored images. Customer objects may become unavailable earlier under customer retention policies. There is no asset lookup or transformation-history endpoint in this release.

Async jobs and webhooks

Set async:true for the existing 202 job envelope and poll /status/{jobId} using the same account’s API key. Polling is free; other accounts receive 404. Add webhookUrl and optionally webhookSecret to request asynchronous signed delivery. Events are transform.completed, transform.partial, and transform.failed, with the settled response inside result. Existing webhook signature verification applies. Delivery retries do not rerun transformations or alter credit settlement.

Limits and failures

Outputs run sequentially. A deadline preserves completed outputs and fails/refunds the remaining outputs. Missing or cross-account references return 404; expired owned references return 410. Typed failures cover invalid bounds, unsupported format, input size, source availability/hash mismatch, processing, storage and persistence. Public errors never include provider payloads or source URLs.