Screenshots and page data from any URL

One API for screenshots, structured snapshots, whole-site crawls and page-reconstruction blueprints. Runs on Cloudflare's edge — no browsers to operate, no queues to babysit, no infrastructure to keep alive.

100 credits a month, free. No card required.

RequestcURL
curl "https://api.scrinly.com/render/snapshot" \
  --get \
  -H "Authorization: Bearer sk_live_..." \
  --data-urlencode "url=https://linear.app" \
  -d "markdown=true" \
  -d "links=true" \
  -d "design=true"

# Images, fonts and media are blocked unless
# you ask for them, so a snapshot loads about
# twice as fast as a screenshot.
Responseapplication/json
{
  "success": true,
  "type": "snapshot",
  "metadata": {
    "title": "Linear — Plan and build products",
    "description": "Linear streamlines issues...",
    "favicon": "https://linear.app/favicon.ico"
  },
  "markdown": "# Plan and build products\n...",
  "links": [128 /* unique, absolute */],
  "design": {
    "tokens": { "count": 214 },
    "breakpoints": [640, 768, 1024, 1280],
    "libraries": ["framer-motion"]
  },
  "renderTime": 1412
}

Three primitives.
One endpoint each.

Scrinly does not try to be a scraping framework. It does three things a headless browser is uniquely good at, and returns them as plain JSON you can use the same day.

Snapshot

Metadata, markdown, links, images, headings, colours and fonts from a fully rendered page — including everything JavaScript drew.

Screenshot

Full page or viewport, JPEG or PNG, device emulation, dark mode, and one flag each to hide cookie banners, ads, chat widgets and popups.

Crawl

Walk a whole site from one seed URL. Scope rules, robots.txt, per-host politeness and a live page index, all handled.

Read pages the way
a machine should

Point it at a URL and get back what the page actually contains after rendering — not the empty shell an HTTP fetch returns. Markdown for models, structure for pipelines, metadata for everything else.

Markdownfor LLMs
# Plan and build products

  Linear is a purpose-built tool for planning
  and building products.

  ## Made for modern product teams

  - Purpose-built for product development
  - Designed to move fast
  - Crafted to perfection

  [Get started](https://linear.app/signup)
Structureheadings · CTAs · sections
{
    "headings": [
      { "level": 1, "text": "Plan and build..." },
      { "level": 2, "text": "Made for modern..." }
    ],
    "ctas": [
      { "text": "Get started", "y": 412 },
      { "text": "Talk to sales", "y": 412 }
    ],
    "sections": 14,
    "wordCount": 1284
  }

Capture any page,
at any size

Real Chrome, real layout. Emulate a device, force dark mode, hide the cookie banner, click something first, then take the shot — full page or viewport, returned as bytes or stored for you.

Walk an entire site
from one seed URL

Give it a starting point and a scope. Scrinly discovers the frontier, obeys robots.txt, stays polite to the host, and snapshots every page it finds — up to five thousand of them, without you managing a queue.

/depth 042 links
/pricingdepth 128 links
/docs/getting-starteddepth 161 links
/docs/api-reference/renderdepth 2rendering…
/blog/2026-08-changelogdepth 2rendering…
/blog/tag/engineeringdepth 3queued
/customers/acmedepth 3queued

Extract a design system
from a page you did not build

Scrinly walks the real stylesheets — including cross-origin ones and everything inside media queries — and returns the tokens, the palette, the type stack, the breakpoints and the motion vocabulary.

Palettefrequency ranked
#5E6AD2
#08090A
#F7F8F8
#8A8F98
#E8FF5A
#26282D
AaInter Variable · 400 500 590
AaSF Mono · 400
Aaself-hosted · woff2 · swap
Tokens & motionobserved only
"customProperties": [
    { "name": "--brand",
      "resolved": "#5E6AD2", "kind": "color" },
    { "name": "--radius-md",
      "resolved": "8px", "kind": "length" }
  ],
  "breakpoints": [
    { "px": 768, "rules": 142 },
    { "px": 1024, "rules": 96 }
  ],
  "motion": {
    "durationsMs": [150, 250, 400],
    "easings": ["cubic-bezier(.22,.61,.36,1)"],
    "reducedMotionSupport": true
  },
  "libraries": ["framer-motion", "lenis"]

Turn that into a
rebuildable blueprint

Add blueprint=true and the page comes back section by section: each region labelled with the evidence behind it, every animation filed under the region it belongs to, and the CSS generated from observed values. An agent gets what it needs to rebuild the page, not a dump of the DOM.

Regionsdocument order
{
  "label": "hero", "confidence": "high",
  "evidence": ["contains the h1",
    "starts above the fold",
    "contains a call to action"],
  "motion": [{
    "type": "fade-up",
    "trigger": { "kind": "scroll-into-view" },
    "timing": { "durationMs": 600,
      "easing": "cubic-bezier(.4,0,.2,1)" },
    "modifiers": { "stagger":
      { "stepMs": 100, "count": 3 }}
  }],
  "components": [{ "repeatOf": "div|card",
    "count": 3 }]
}

# Repeated siblings are reported with a count,
# so an agent emits a loop instead of twelve
# near-identical cards.
Stylesheetsinline, from observed values
/* stylesheets["keyframes.css"] */
@keyframes fadeInUp {
  0%   { opacity: 0; transform: translateY(24px); }
  100% { opacity: 1; transform: none; }
}

/* stylesheets["responsive.css"] */
@media (max-width: 390px) {
  div.grid { grid-template-columns: 1fr; }
  #headline { font-size: 32px; }
}

Not the site's media queries read back. Two rendered viewports are compared, so what you get is what actually changed. Computed width and height are left out — emitting them would pin the layout to one screen.

Or have a model
read it back to you

Add interpret=true and the blueprint comes back as prose as well — the page described region by region for an engineer who has to rebuild it and cannot see it. The model never sees the page: only a sanitised projection crosses, with the copy, selectors and URLs removed first.

Page structure

observedSix regions in document order. A sticky header landmark, a full-viewport hero carrying the h1, then features, pricing and testimonials, each built from three repeated cards.

Motion and interaction

observedEleven animations. The features cards fade up on scroll at 600ms with a 100ms stagger across three siblings; one element pulses on an infinite loop.

inferredThe single easing curve across every reveal suggests one shared transition token rather than per-component timing.

Reconstruction notes and gaps

Form validation is detected and not recovered. No WebGL was observed. Region skeletons were capped for length; the caps are reported.

Guaranteesverified per response

Every literal is checked. Each hex code, duration, easing curve and token name in the document is matched back against the projection it came from. More than five unsupported values, or a missing section, refuses the generation and refunds it rather than publishing a confident document with invented numbers in it.

Observed and inferred are labelled. Interpretation is allowed but quarantined, so you always know which claims survive if the model is wrong.

The blueprint is yours either way. A provider outage returns the full capture with the document marked as the part that failed, and only the interpretation credits come back.

Bring your own key. Use ours or your own provider credential. Either way the prompt carries no URL, no HTML and no page text.

Know exactly what
you are spending

Credits are charged before the work starts and refunded when it fails, so a request you never got is a request you never paid for. Every response carries your balance in the headers.

Simple credit pricing

A snapshot or screenshot costs one credit. Design extraction costs two, a blueprint eight, and reading it back three more. Every plan includes the whole API — the only thing that changes is how many credits you get each month.

Switch to yearly and save up to $1,200 a year.

Free

Everything, at a small scale.

$0/mo

Free forever

Start free
  • 100 credits a month
  • 30s render timeout
  • Snapshot, screenshot, crawl
  • Design extraction & blueprints

Startup

For a first production workload.

$29/mo

billed monthly

Choose Startup
  • 2,000 credits a month
  • 30s render timeout
  • 5 webhook endpoints
  • No Scrinly branding

Business

Steady, high-volume pipelines.

$199/mo

billed monthly

Choose Business
  • 30,000 credits a month
  • 60s render timeout
  • 20 webhook endpoints
  • Bring your own AI key

Prime

Crawling at the top of the range. Everything in Business, with nine times the allowance and storage on your own bucket.

  • 90,000 credits a month
  • 60s render timeout
  • 20 webhook endpoints
  • Custom storage buckets
$499/mo

billed monthly

Choose Prime

Yearly plans are billed once but the credit allowance still refreshes every month — an annual plan is not twelve months of credits handed over at once. Credits are charged before a render starts and refunded if it fails. See how credits work →

The questions that
come up first

Everything here is how the API behaves today, not a roadmap. Shipping history lives in the changelog.

Do I have to run any browsers?

No. Renders run on Cloudflare Browser Rendering, so there is no Chromium to operate, no container to size and no queue to babysit. You send a URL and get bytes or JSON back.

Do you respect robots.txt?

Crawls do. They obey robots.txt including Crawl-delay, identify themselves as Scrinly/3.0 with a link to a bot page, and are limited to one request a second and two at a time per host by default.

A single render is a page you asked for by URL — the same as opening a tab — so it is fetched directly. Crawls can opt out with robots=ignore, which is your call to make about sites you control.

Synchronous or queued?

Synchronous by default: one request, one response. Pass async=true or a webhookUrl and the job is queued instead — you get a 202 with an id to poll, or the result delivered to your endpoint.

Blueprints are always synchronous. Making an agent poll in the middle of a task is the one thing they exist to avoid.

Where do the images go?

Your bucket. Backblaze B2 by default, with S3 and R2 supported — you pass the credentials per request and they are never persisted. Leave storage off and screenshots come back as raw bytes instead.

What happens when something fails halfway?

You keep whatever succeeded and pay only for that. A blueprint whose interpretation fails returns the full capture with the document marked as the part that did not land, and only the interpretation credits come back.

A crawl reports per-page status rather than collapsing to one verdict, so forty good pages are not lost to one bad one.

Can I use my own AI provider key?

Yes, in one request header. It cuts an interpretation to a single credit and the key is never stored or logged. Either way the prompt carries no URL, no HTML and no page text.

Charged before the work starts. Refunded when it fails. You never pay for a render you did not get.
Credit metering One atomic statement, safe under concurrency
Your keys are hashed, never stored. Every job, crawl and schedule is scoped to the account that made it.
Tenant isolation Other accounts return 404, not 403

Built on the edge.
Available today.

100 credits a month. No card, no sales call.