> ## Documentation Index
> Fetch the complete documentation index at: https://scrinly.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Capture a page snapshot



## OpenAPI

````yaml /api-reference/openapi.json post /render/snapshot
openapi: 3.1.0
info:
  title: Scrinly Browser API
  version: '2026-08-14'
  description: >-
    Public API for browser rendering, screenshots, structured extraction,
    grounded page-reconstruction blueprints, batches, jobs, crawls, schedules,
    and usage.
servers:
  - url: https://api.scrinly.com
    description: Production
security:
  - BearerAuth: []
tags:
  - name: Rendering
    description: Synchronous and asynchronous browser renders.
  - name: Batches
    description: Create multiple asynchronous render jobs.
  - name: Jobs
    description: Inspect and retry account-owned jobs.
  - name: Crawls
    description: Traverse a site and collect page results.
  - name: Schedules
    description: Create and manage account-owned render schedules.
  - name: Usage
    description: Read account credit usage.
paths:
  /render/snapshot:
    post:
      tags:
        - Rendering
      summary: Capture a page snapshot
      operationId: createSnapshot
      parameters:
        - $ref: '#/components/parameters/ProviderApiKey'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SnapshotRequest'
      responses:
        '200':
          $ref: '#/components/responses/SnapshotResult'
        '202':
          $ref: '#/components/responses/JobAccepted'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '403':
          $ref: '#/components/responses/Forbidden'
        '503':
          $ref: '#/components/responses/ProviderUnavailable'
components:
  parameters:
    ProviderApiKey:
      name: X-Scrinly-Provider-API-Key
      in: header
      required: false
      schema:
        type: string
        writeOnly: true
      description: >-
        Ephemeral server-to-server key for the selected AI provider. Never put
        it in a URL or JSON body.
  schemas:
    SnapshotRequest:
      allOf:
        - $ref: '#/components/schemas/RenderOptions'
        - type: object
          required:
            - url
          properties:
            url:
              $ref: '#/components/schemas/HttpUrl'
            markdown:
              type: boolean
              default: false
            html:
              type: boolean
              default: false
            links:
              type: boolean
              default: false
            images:
              type: boolean
              default: false
            videos:
              type: boolean
              default: false
            fonts:
              type: boolean
              default: false
            colors:
              type: boolean
              default: false
            structure:
              type: boolean
              default: false
            design:
              type: boolean
              default: false
            blueprint:
              type: boolean
              default: false
              description: Implies design and requires synchronous mode. Adds 6 credits.
            viewports:
              type: array
              items:
                type: string
                enum:
                  - desktop
                  - mobile
              default:
                - desktop
                - mobile
              description: Widest first. Only valid with blueprint=true.
            screenshots:
              type: boolean
              default: true
              description: >-
                One stored screenshot per viewport. Only valid with
                blueprint=true.
            interpret:
              type: boolean
              default: false
              description: >-
                Generate a grounded prose reading of the blueprint. Only valid
                with blueprint=true. Adds 3 credits, or 1 with your own provider
                key.
            provider:
              $ref: '#/components/schemas/Provider'
            refresh:
              type: boolean
              default: false
            async:
              type: boolean
              default: false
    RenderOptions:
      type: object
      properties:
        url:
          $ref: '#/components/schemas/HttpUrl'
        timeout:
          type: integer
          minimum: 10
          maximum: 60
          default: 30
        waitUntil:
          type: string
          enum:
            - load
            - domcontentloaded
            - networkidle0
            - networkidle2
          default: networkidle2
        width:
          type: integer
          minimum: 100
          maximum: 3840
        height:
          type: integer
          minimum: 100
          maximum: 2160
        device:
          type: string
          description: Supported device preset; overrides width and height.
        theme:
          type: string
          enum:
            - light
            - dark
          default: light
        blockCookieBanners:
          type: boolean
          default: true
        blockAds:
          type: boolean
          default: true
        blockChatWidgets:
          type: boolean
          default: true
        blockPopups:
          type: boolean
          default: true
        blockAccessibilityWidgets:
          type: boolean
          default: true
        hideSelectors:
          type: array
          items:
            type: string
            minLength: 1
        clickSelectors:
          type: array
          items:
            type: string
            minLength: 1
        scrollToElement:
          type: string
          minLength: 1
        headers:
          type: object
          additionalProperties:
            type: string
          writeOnly: true
        cookies:
          type: array
          items:
            $ref: '#/components/schemas/Cookie'
          writeOnly: true
        priority:
          type: string
          enum:
            - low
            - normal
            - high
          default: normal
        cache:
          type: boolean
          default: false
        webhookUrl:
          $ref: '#/components/schemas/HttpUrl'
        webhookSecret:
          type: string
          writeOnly: true
        store:
          type: boolean
          default: false
        storage_provider:
          type: string
          enum:
            - b2
            - s3
            - r2
        storage_path:
          type: string
        storage_bucket:
          type: string
        storage_endpoint:
          type: string
          format: uri
        storage_region:
          type: string
          default: auto
        storage_access_key_id:
          type: string
          writeOnly: true
        storage_secret_access_key:
          type: string
          writeOnly: true
        storage_public_domain:
          type: string
          format: uri
        storage_return_location:
          type: boolean
    HttpUrl:
      type: string
      format: uri
      maxLength: 2048
      pattern: ^https?://
    Provider:
      type: string
      enum:
        - deepseek
        - openai
      default: deepseek
    SnapshotResponse:
      type: object
      required:
        - success
        - type
        - url
        - metadata
        - renderTime
      properties:
        success:
          const: true
        status:
          type: string
          enum:
            - completed
            - blueprint_only
          description: >-
            `blueprint_only` means the capture succeeded and the interpretation
            did not — see `blueprint.interpretationError`. The blueprint is
            present and its credits are not refunded.
        type:
          const: snapshot
        url:
          $ref: '#/components/schemas/HttpUrl'
        metadata:
          type: object
          additionalProperties: true
        markdown:
          type: string
        html:
          type: string
        links:
          type: array
          items:
            type: string
            format: uri
        images:
          type: array
          items:
            type: string
        videos:
          type: array
          items:
            type: string
        fonts:
          type: array
          items:
            type: object
            additionalProperties: true
        colors:
          type: array
          items:
            type: object
            additionalProperties: true
        structure:
          type: object
          additionalProperties: true
        design:
          $ref: '#/components/schemas/Design'
        blueprint:
          $ref: '#/components/schemas/Blueprint'
        credits:
          $ref: '#/components/schemas/Credits'
        renderTime:
          type: integer
          minimum: 0
        startedAt:
          type: string
          format: date-time
        completedAt:
          type: string
          format: date-time
    JobAccepted:
      type: object
      required:
        - success
        - id
        - status
        - statusUrl
      properties:
        success:
          const: true
        id:
          type: string
          format: uuid
        status:
          const: queued
        statusUrl:
          type: string
          examples:
            - /status/6a8bc66a-0000-4000-8000-000000000000
    Error:
      type: object
      properties:
        success:
          type: boolean
          const: false
        error:
          type: string
        type:
          type: string
        message:
          type: string
        fields:
          type: array
          items:
            $ref: '#/components/schemas/FieldError'
    InterpretationError:
      type: object
      required:
        - type
        - message
        - retryable
      properties:
        type:
          type: string
          examples:
            - llm_grounding_failed
        message:
          type: string
        retryable:
          type: boolean
        reason:
          type: string
        missingHeadings:
          type: array
          items:
            type: string
        unknownLiteralCount:
          type: integer
          minimum: 0
    Cookie:
      type: object
      additionalProperties: false
      required:
        - name
        - value
      properties:
        name:
          type: string
          minLength: 1
        value:
          type: string
        domain:
          type: string
        path:
          type: string
        expires:
          type: number
        httpOnly:
          type: boolean
        secure:
          type: boolean
        sameSite:
          type: string
          enum:
            - Strict
            - Lax
            - None
    Design:
      type: object
      description: Deterministic extraction of authored tokens and observed design signals.
      properties:
        tokens:
          type: object
          additionalProperties: true
        color:
          type: object
          additionalProperties: true
        typography:
          type: object
          additionalProperties: true
        breakpoints:
          type: array
          items:
            type: object
            additionalProperties: true
        motion:
          type: object
          additionalProperties: true
        libraries:
          type: array
          items:
            type: object
            additionalProperties: true
        coverage:
          type: object
          additionalProperties: true
      additionalProperties: true
    Blueprint:
      type: object
      description: >-
        Everything needed to rebuild the page, attributed to the parts of the
        page it belongs to. Motion and responsive layout are filed under regions
        rather than listed flat, so "what does the hero do" is answerable.
        `url`, `metadata`, `markdown`, `links`, `images` and `design` are not
        restated here — they are already top-level fields of the same response.
      required:
        - version
        - viewports
        - regions
        - limitations
        - stats
      properties:
        version:
          type: integer
          const: 1
        viewports:
          type: array
          items:
            type: object
            properties:
              name:
                type: string
                enum:
                  - desktop
                  - mobile
              width:
                type: integer
              height:
                type: integer
              documentHeight:
                type:
                  - number
                  - 'null'
              screenshot:
                type:
                  - string
                  - 'null'
                format: uri
                description: Stored image URL, or null when `screenshots=false`.
        regions:
          type: array
          items:
            $ref: '#/components/schemas/BlueprintRegion'
        repeaters:
          type: array
          items:
            type: object
            additionalProperties: true
          description: >-
            Structures repeated across the page — N siblings sharing a shape,
            which is a component in a loop.
        tech:
          type: array
          items:
            $ref: '#/components/schemas/BlueprintTech'
        stylesheets:
          type: object
          additionalProperties:
            type: string
          description: >-
            Generated CSS, returned inline rather than stored so a blueprint
            stays one call: `tokens.css`, `keyframes.css`, `states.css`,
            `responsive.css`. Empty files are omitted.
        motionOrphans:
          type: array
          items:
            $ref: '#/components/schemas/BlueprintMotion'
          description: >-
            Animations that could not be filed under a region. Present only when
            non-empty — an orphan means element identity and the motion readout
            disagreed, which is surfaced rather than dropped.
        instrumentation:
          type:
            - object
            - 'null'
          additionalProperties: true
          description: >-
            Health of the motion capture, including which recovery tiers
            degraded.
        limitations:
          type: array
          description: >-
            What was found but could not be explained. Read this before treating
            a rebuild as complete.
          items:
            type: object
            properties:
              kind:
                type: string
                enum:
                  - webgl
                  - instrumentation
                  - screenshots
                  - application-logic
              note:
                type: string
              count:
                type: integer
              detail:
                type: array
                items:
                  type: string
        truncated:
          type: array
          items:
            type: string
          description: Caps that were hit, e.g. `region-skeleton`.
        stats:
          type: object
          additionalProperties: true
          description: >-
            regions, labelled, nodesCaptured, nodesInSkeleton, motion,
            orphanedMotion, components.
        capturedAt:
          type: string
          format: date-time
        interpretation:
          $ref: '#/components/schemas/Interpretation'
        interpretationError:
          $ref: '#/components/schemas/InterpretationError'
    Credits:
      type: object
      required:
        - charged
        - refunded
        - net
      properties:
        charged:
          type: integer
          minimum: 0
        refunded:
          type: integer
          minimum: 0
        net:
          type: integer
          minimum: 0
    FieldError:
      type: object
      properties:
        field:
          type: string
        message:
          type: string
      required:
        - field
        - message
    BlueprintRegion:
      type: object
      description: >-
        One observed section of the page. Segmentation is measurement; the label
        is inference, carries its evidence, and is null rather than a guess when
        the evidence does not support one.
      properties:
        id:
          type: string
          description: >-
            Matches the `data-scrinly-id` stamped on the captured element, and
            joins motion to layout.
        order:
          type: integer
          description: Document order, top to bottom.
        label:
          type:
            - string
            - 'null'
          enum:
            - nav
            - hero
            - features
            - logos
            - pricing
            - testimonials
            - faq
            - cta
            - footer
            - null
        confidence:
          type:
            - string
            - 'null'
          enum:
            - high
            - medium
            - null
          description: >-
            Null whenever `label` is null, including when two regions competed
            for the same label and neither won outright.
        evidence:
          type: array
          items:
            type: string
          description: Why this label, e.g. `tag:header`, `text:pricing`.
        selector:
          type: string
        tag:
          type: string
        box:
          type:
            - array
            - 'null'
          items:
            type: number
          minItems: 4
          maxItems: 4
          description: '[top, left, width, height] in CSS pixels at the primary viewport.'
        nodeCount:
          type: integer
          description: Elements captured in this region, before the skeleton cap.
        skeleton:
          type: array
          items:
            type: object
            additionalProperties: true
          description: >-
            Depth-limited element tree, capped per region. Boxes are [top, left,
            width, height] and properties equal to the CSS default are omitted.
        components:
          type: array
          items:
            type: object
            additionalProperties: true
          description: Repeating structures inside this region — a card rendered in a loop.
        motion:
          type: array
          items:
            $ref: '#/components/schemas/BlueprintMotion'
        responsive:
          type: array
          items:
            type: object
            additionalProperties: true
          description: >-
            Per-viewport layout deltas, carrying only the value each property
            changes *to* — the from side is already in this region's skeleton.
    BlueprintTech:
      type: object
      description: >-
        A technology detected from observed evidence — a global, a selector, a
        request host or a generator tag.
      properties:
        name:
          type: string
        category:
          type: string
          enum:
            - cms
            - ecommerce
            - payments
            - analytics
            - consent
            - testing
            - chat
            - email
            - framework
            - hosting
        categoryLabel:
          type: string
          description: The category rendered for display.
        confidence:
          type: string
          enum:
            - high
            - medium
          description: >-
            High for a JavaScript global or a generator tag, or for two
            independent kinds of evidence agreeing.
        version:
          type: string
          description: Present only when the page exposes one.
        evidence:
          type: array
          items:
            type: object
            properties:
              kind:
                type: string
                enum:
                  - global
                  - generator
                  - selector
                  - url
                  - host
              value:
                type: string
    BlueprintMotion:
      type: object
      description: >-
        One animation, classified. Recovered primarily from
        `document.getAnimations()`, so it is reported the same way whichever
        library produced it.
      properties:
        nodeId:
          type:
            - string
            - 'null'
          description: >-
            The element this animates, joining it to a node in the region
            skeleton.
        type:
          type: string
          description: >-
            The effect, named from what the keyframes do: `fade-up`,
            `fade-zoom-in`, `slide-right`, `class-toggle` when a class carries
            the effect, or `unknown`.
        primitives:
          type: array
          items:
            type: string
            enum:
              - fade
              - slide
              - scale
              - rotate
              - blur
              - clip-reveal
              - color
          description: The independent changes the effect is composed of.
        detail:
          type: object
          additionalProperties: true
          description: >-
            Measured magnitudes behind the primitives, e.g. the translate
            distance and direction.
        tier:
          type:
            - string
            - 'null'
          description: Which recovery tier produced this record. Determines `confidence`.
        source:
          type:
            - string
            - 'null'
          description: What was intercepted or observed, e.g. `gsap`, `hover`, `mutation`.
        confidence:
          type: string
          enum:
            - high
            - medium
            - low
          description: >-
            Derived from the tier: exact keyframes are high, a sampled curve is
            low.
        trigger:
          type: object
          description: >-
            What starts it. `kind` selects which of the other fields are
            present.
          properties:
            kind:
              type: string
              enum:
                - load
                - scroll-into-view
                - scroll-scrub
                - hover
                - click
                - infinite
            delayMs:
              type: integer
              description: kind=load.
            scrollPx:
              type: integer
              description: 'kind=scroll-into-view: scroll offset at which it fired.'
            threshold:
              type:
                - number
                - 'null'
              description: >-
                kind=scroll-into-view: where the element sat in the viewport
                when it fired — the number an IntersectionObserver threshold is
                built from.
            startPx:
              type:
                - integer
                - 'null'
              description: kind=scroll-scrub.
            endPx:
              type:
                - integer
                - 'null'
              description: kind=scroll-scrub.
            pinned:
              type: boolean
              description: kind=scroll-scrub.
        timing:
          type: object
          properties:
            durationMs:
              type: integer
            delayMs:
              type: integer
            easing:
              type:
                - string
                - 'null'
            easingAlias:
              type:
                - string
                - 'null'
              description: The cubic-bezier resolved back to a name where one matches.
            iterations:
              oneOf:
                - type: number
                - type: string
                  const: infinite
            direction:
              type: string
            fill:
              type: string
          description: Fields equal to the CSS default are omitted.
        animationName:
          type:
            - string
            - 'null'
        keyframes:
          type: array
          items:
            type: object
            additionalProperties: true
          description: >-
            Present only when the animation has no named rule in `keyframes.css`
            — for a WAAPI or inline animation this is the only copy.
        keyframesRef:
          type: string
          description: >-
            Name of a rule in `stylesheets["keyframes.css"]`, used instead of
            repeating frames already carried there.
        addedClasses:
          type: array
          items:
            type: string
          description: >-
            type=class-toggle: the classes added. The effect itself lives in the
            stylesheet under them.
        selector:
          type:
            - string
            - 'null'
        modifiers:
          type: object
          properties:
            stagger:
              type: object
              description: >-
                Present when siblings sharing an effect and duration fire at an
                evenly spaced delay.
              properties:
                stepMs:
                  type: integer
                count:
                  type: integer
    Interpretation:
      type: object
      description: >-
        A grounded Markdown reading of the blueprint, present only with
        `interpret=true`. Generated from a sanitised projection — page copy,
        selectors and URLs are removed before anything reaches the provider —
        and refused rather than returned if it cites a value the projection does
        not contain.
      required:
        - document
        - promptVersion
        - sections
        - grounding
        - coverage
        - provider
        - usage
        - cache
      properties:
        document:
          type: string
          description: Grounded Markdown document.
        promptVersion:
          type: string
        sections:
          type: object
          additionalProperties:
            type: string
        grounding:
          $ref: '#/components/schemas/Grounding'
        coverage:
          type: object
          additionalProperties: true
        provider:
          $ref: '#/components/schemas/ProviderMetadata'
        usage:
          $ref: '#/components/schemas/TokenUsage'
        cache:
          type: object
          required:
            - hit
          properties:
            hit:
              type: boolean
              description: True when this document came from the interpretation cache.
    Grounding:
      type: object
      description: >-
        Whether every CSS literal in the document traced back to the projection.
        More than five untraceable literals, a missing heading, or truncation
        refuses the generation rather than returning it.
      required:
        - status
        - unknownLiterals
      properties:
        status:
          type: string
          enum:
            - clean
            - flagged
        unknownLiterals:
          type: array
          maxItems: 5
          items:
            type: string
          description: Literals absent from the projection. Empty when status is clean.
    ProviderMetadata:
      type: object
      required:
        - label
        - model
        - credentialMode
      properties:
        label:
          $ref: '#/components/schemas/Provider'
        model:
          type: string
          readOnly: true
          description: Server-selected model.
        host:
          type: string
        credentialMode:
          type: string
          enum:
            - platform
            - byok
        dataPolicy:
          type: object
          additionalProperties: true
          description: Training, retention and residency terms for the selected provider.
        dataResidency:
          type:
            - string
            - 'null'
        settings:
          type: object
          additionalProperties: true
        latencyMs:
          type: integer
          minimum: 0
        finishReason:
          type:
            - string
            - 'null'
    TokenUsage:
      type: object
      properties:
        inputTokens:
          type: integer
          minimum: 0
        outputTokens:
          type: integer
          minimum: 0
        totalTokens:
          type: integer
          minimum: 0
        cacheHitTokens:
          type: integer
          minimum: 0
        cacheMissTokens:
          type: integer
          minimum: 0
        reasoningTokens:
          type: integer
          minimum: 0
        providerDetails:
          type: object
          additionalProperties: true
  responses:
    SnapshotResult:
      description: >-
        Snapshot, optionally carrying a blueprint and its interpretation.
        `blueprint_only` reports a capture that succeeded with a failed
        interpretation.
      headers:
        X-Credits-Charged:
          $ref: '#/components/headers/CreditsCharged'
        X-Credits-Refunded:
          $ref: '#/components/headers/CreditsRefunded'
        X-Credits-Remaining:
          $ref: '#/components/headers/CreditsRemaining'
        X-Scrinly-LLM-Provider:
          $ref: '#/components/headers/LlmProvider'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/SnapshotResponse'
    JobAccepted:
      description: Job accepted for asynchronous processing.
      headers:
        X-Credits-Charged:
          $ref: '#/components/headers/CreditsCharged'
        X-Credits-Remaining:
          $ref: '#/components/headers/CreditsRemaining'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/JobAccepted'
    BadRequest:
      description: Invalid request
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: Missing, unknown, or revoked API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    PaymentRequired:
      description: Credit limit reached
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Forbidden:
      description: Account is deactivated
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    ProviderUnavailable:
      description: Selected platform-funded AI provider is not configured
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/InterpretationError'
  headers:
    CreditsCharged:
      description: Credits charged before refunds.
      schema:
        type: integer
        minimum: 0
    CreditsRefunded:
      description: Credits refunded by this request.
      schema:
        type: integer
        minimum: 0
    CreditsRemaining:
      description: Credits left in the current account period.
      schema:
        type: integer
        minimum: 0
    LlmProvider:
      description: Selected AI provider for the interpretation.
      schema:
        type: string
        enum:
          - deepseek
          - openai
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: Scrinly API key
      description: Customer API key from the Scrinly dashboard.

````