Render

Capture a bundle from one navigation

Loads a page once and returns the outputs you select from that one navigation: a screenshot, the rendered_html (the DOM after the page's scripts, readiness and actions, serialised - not the source the server sent), the page's text as the browser lays it out, deterministic markdown made from the rendered HTML, and the page's metadata (title, description, language, canonical address, robots and Open Graph). Every screenshot option applies: device, full page, readiness, actions, success rules, request shaping.

The capture window. After readiness, actions and success rules, the page is read in one script call - HTML, text and metadata together, so they describe one state of the document - and the screenshot is taken immediately after. A page that changes itself (a timer, an animation, live data) can change between the two; the manifest gives both times. A bundle is the page as the browser had it, not an atomic snapshot of the site's data.

Frames. HTML, text and Markdown come from the main frame. The content of iframes, same origin or not, is not included; child_frames in the manifest counts the frames left out. The screenshot shows what was painted, frames included.

Bounds. Rendered HTML up to 5 MiB, text and Markdown up to 1 MiB each, metadata fields up to 2,000 characters. Text and Markdown over their bound are cut at a character boundary and marked truncated; HTML over its bound is omitted with too_large (cutting HTML would give a different document), and so is the Markdown made from it (source_too_large). A page nested too deeply to parse has its Markdown omitted with unparseable. A bundle with none of its outputs left is a 422 bundle_empty and counts nothing. An output is never left out without the manifest saying so.

The response is multipart/form-data: manifest (JSON) first, then each included output as a file part named by output, in the order screenshot, rendered_html, text, markdown. Metadata is in the manifest. The manifest gives each output's size and SHA-256. Captured HTML and text are the page's own content: treat them as untrusted, and never insert the HTML into a page of your own.

Metering. One bundle counts one render.screenshot when it succeeds, whatever outputs it holds; a failure counts nothing. Bundles are never cached. Also available as a job of kind bundle, whose result is the same multipart body.

This endpoint is available on the product-partitioned URL only.

post/v1/bundle

Request

  • Base URL: https://api.ironfang.com/render
  • URL: https://api.ironfang.com/render/v1/bundle
  • Auth: HTTP bearer

Headers

Idempotency-Keystring

Makes a synchronous render happen, and count, at most once. Any string up to 255 characters, remembered per account. The first request under a key is admitted and rendered as usual; a synchronous result is not kept, so the same request again under the key is a 409 idempotency_key_used and reserves nothing - send a new key to render again. A different request under a used key is a 409 idempotency_conflict. An identical request inside the cache window is still served from cache.

Request body

authorizationstring

Sets the Authorization header - the common case, spelled once. An explicit Authorization in headers wins over this.

block_adsboolean

Drop requests to known ad and tracker networks before they load. Stopped as network requests rather than hidden afterwards, so the page never spends time fetching them.

block_cookie_bannersboolean

Hide common consent banners, and undo the scroll lock they set - without which a full-page capture is one viewport tall.

Hidden, not accepted. Clicking "accept" would be a decision made on the site owner's behalf and recorded as theirs.

cssstring

Custom stylesheet, at most 65536 UTF-8 bytes. Applied after normal load/wait conditions and built-in hiding, before script, actions, settling and capture. Supports screenshots and PDFs, including @media print rules. Malformed stylesheet syntax is a 400 bad_request; Chromium determines supported properties and values.

device_scale_factornumber

Pixel density. 2 is retina: the same CSS size at twice the pixels.

headersobject

Extra HTTP headers sent with every request for the page.

hide_selectorsstring[]

CSS selectors to hide before capturing. Applied after load, so elements injected by script are covered.

no_cacheboolean

Force a fresh render instead of serving a cached one. Always billable. Excluded from the cache key, so repeated fresh requests do not collide.

scriptstring

JavaScript statements executed inside the target page's main-frame context after load/wait conditions and css, before actions and capture. Runs as an async function body: use await or return a promise for asynchronous work. Completion is awaited; return values are discarded. At most 16384 UTF-8 bytes and 5000 ms execution, further bounded by the remaining timeout_ms budget. Syntax errors, execution failures and timeouts return 422 render_failed with a sanitized message. Supports screenshots and PDFs; no browser-session or Playwright/Puppeteer APIs are exposed.

timeout_msinteger

Per-render timeout. Clamped to the service maximum - it can lower the ceiling but not raise it.

user_agentstring

Overrides the user agent, including any set by device.

wait_for_selectorstring

Wait for this element before capturing. Fails the render if it never appears, rather than returning a half-drawn page.

wait_until'load' | 'domcontentloaded' | 'networkidle'

When the page counts as ready. networkidle waits for traffic to stop and is bounded by the render timeout, because a page with polling never truly idles.

dark_modeboolean

Render with prefers-color-scheme: dark.

delay_msinteger

Extra settle time after load. Ironfang Render watches the page and captures when it stops changing, so this is rarely needed - use it for content that arrives on a timer, which quiescence cannot anticipate. Capped at ten seconds.

device'desktop' | 'tablet' | 'mobile'

Capture as a phone or tablet rather than a desktop window that happens to be narrow. Sets the viewport, the device pixel ratio, touch, and a matching mobile user agent together - width alone gets media queries right and everything else wrong.

An explicit width or height still wins, so a preset can be used for the density and user agent while overriding the size.

format'png' | 'jpeg' | 'webp'

PNG is lossless and the default. WebP is typically a fraction of the size for the same picture, which is what matters when the output is served to browsers or social crawlers.

full_pageboolean

Capture the whole scrollable page.

full_page_max_heightinteger

Cap a full_page capture at this many pixels. An infinite-scroll page has no natural end, so 20000 applies when none is given, and is also the most that can be asked for.

full_page_readiness'scroll'

scroll walks a full_page capture down before taking it, a viewport at a time with overlap, so content a page loads only as it comes into view - loading=lazy images, IntersectionObserver loaders - is in the picture without a script of your own. Each step waits up to 750 ms for the images it exposed; the walk then returns to the top and waits up to 2 s for the images inside the capture. The whole pass takes at most 10 s (less when timeout_ms leaves less, keeping 3 s for the capture), at most 60 steps, and never goes below full_page_max_height, so an infinite feed ends where the capture is cut.

The page keeps its authored layout: the capture is taken from the top, so a sticky header appears once, at the top, and a fixed element where it sits in the first viewport. What the pass did is in the X-Ironfang-Warnings header and a job's diagnostics.readiness; a budget that runs out is a warning on a successful capture, not a failure. Omitted, the capture is taken as it always has been. Requires full_page.

heightinteger

Viewport height. Ignored when full_page is set.

htmlstring

Markup to render. Mutually exclusive with url.

omit_backgroundboolean

Transparent background instead of the page's own. Ignored for jpeg, which has no alpha channel.

qualityinteger

Quality for the lossy formats, jpeg and webp. Ignored for PNG.

selectorstring

CSS selector of a single element to capture instead of the viewport.

urlstring uri

Page to capture. Mutually exclusive with html.

widthinteger

Viewport width in pixels.

outputsstring[] required

The outputs to include. Options that only shape an image (selector, clip, format, quality, omit_background, success_rules.fail_on_blank) need screenshot among them.

Example request

{
  "actions": [
    {
      "selector": "#show-more",
      "type": "click"
    },
    {
      "selector": "#details",
      "type": "wait_for_selector"
    }
  ],
  "css": ".chat-widget { display: none !important; }",
  "script": "document.querySelector('#pricing')?.click();",
  "success_rules": {
    "fail_on_status": [
      "4xx",
      "5xx"
    ],
    "forbid_text": [
      "Sign in to continue"
    ],
    "require_selector": "#invoice"
  }
}

Response

The manifest, then each included output as a file part named by output.

Changes

No recorded changes to this operation across all 1 revision of this API.