{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/rendex-dev/json-schema/rendex-dev-screenshot-request-schema.json",
  "title": "ScreenshotRequest",
  "description": "Provide exactly one of `url`, `html`, or `markdown` (mutually exclusive). If none is\nprovided, the request will fail with a validation error.\n",
  "x-generated": "2026-10-31",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/rendex-dev-openapi.yaml#/components/schemas/ScreenshotRequest",
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "format": "uri",
      "description": "Webpage URL to capture (mutually exclusive with `html` and `markdown`)"
    },
    "html": {
      "type": "string",
      "maxLength": 5242880,
      "description": "Raw HTML to render (up to 5 MB, mutually exclusive with `url` and `markdown`)"
    },
    "markdown": {
      "type": "string",
      "maxLength": 5242880,
      "description": "Markdown to render as styled HTML, then capture (up to 5 MB, mutually exclusive with `url` and `html`)"
    },
    "data": {
      "type": "object",
      "additionalProperties": true,
      "description": "Mustache template data object. When present, the `html` or `markdown` string is\ntreated as a logic-less Mustache template and rendered against `data` before capture.\nValid only with `html` or `markdown` — returns 400 if combined with `url`.\nSerialized size must not exceed 256 KB.\nSyntax: `{{var}}` (HTML-escaped), `{{{var}}}` (raw), `{{#items}}…{{/items}}` (loop),\n`{{^x}}…{{/x}}` (inverted section), `{{a.b}}` (nested access).\n"
    },
    "format": {
      "type": "string",
      "enum": [
        "png",
        "jpeg",
        "webp",
        "pdf"
      ],
      "default": "png",
      "description": "Output format"
    },
    "width": {
      "type": "integer",
      "minimum": 320,
      "maximum": 3840,
      "default": 1280,
      "description": "Viewport width in pixels"
    },
    "height": {
      "type": "integer",
      "minimum": 240,
      "maximum": 2160,
      "default": 800,
      "description": "Viewport height in pixels"
    },
    "fullPage": {
      "type": "boolean",
      "default": false,
      "description": "Capture full scrollable page (capped at 16384px height)"
    },
    "quality": {
      "type": "integer",
      "minimum": 1,
      "maximum": 100,
      "description": "Image quality (JPEG and WebP only)"
    },
    "delay": {
      "type": "integer",
      "minimum": 0,
      "maximum": 10000,
      "default": 0,
      "description": "Wait milliseconds after page load before capture"
    },
    "darkMode": {
      "type": "boolean",
      "default": false,
      "description": "Emulate dark color scheme"
    },
    "deviceScaleFactor": {
      "type": "number",
      "minimum": 1,
      "maximum": 3,
      "default": 2,
      "description": "Device pixel ratio (2 for Retina)"
    },
    "blockAds": {
      "type": "boolean",
      "default": true,
      "description": "Block ads, trackers, and chat widgets"
    },
    "blockResourceTypes": {
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "font",
          "image",
          "media",
          "stylesheet",
          "other"
        ]
      },
      "description": "Resource types to block during page load"
    },
    "css": {
      "type": "string",
      "maxLength": 51200,
      "description": "CSS to inject into the page before capture"
    },
    "js": {
      "type": "string",
      "maxLength": 51200,
      "description": "JavaScript to execute on the page before capture"
    },
    "cookies": {
      "type": "array",
      "description": "Cookies to set before navigating to the page",
      "items": {
        "type": "object",
        "required": [
          "name",
          "value"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "value": {
            "type": "string"
          },
          "domain": {
            "type": "string"
          },
          "path": {
            "type": "string"
          },
          "httpOnly": {
            "type": "boolean"
          },
          "secure": {
            "type": "boolean"
          },
          "sameSite": {
            "type": "string",
            "enum": [
              "Strict",
              "Lax",
              "None"
            ]
          },
          "expires": {
            "type": "number",
            "description": "Unix timestamp (seconds) for cookie expiration"
          }
        }
      }
    },
    "headers": {
      "type": "object",
      "additionalProperties": {
        "type": "string"
      },
      "description": "Custom HTTP headers to send with the page request"
    },
    "userAgent": {
      "type": "string",
      "maxLength": 512,
      "description": "Custom User-Agent string"
    },
    "timeout": {
      "type": "integer",
      "minimum": 5,
      "maximum": 60,
      "default": 30,
      "description": "Navigation timeout in seconds"
    },
    "waitUntil": {
      "type": "string",
      "enum": [
        "load",
        "domcontentloaded",
        "networkidle0",
        "networkidle2"
      ],
      "default": "networkidle2",
      "description": "Page readiness condition before capture"
    },
    "waitForSelector": {
      "type": "string",
      "maxLength": 500,
      "description": "CSS selector to wait for before capture"
    },
    "bestAttempt": {
      "type": "boolean",
      "default": true,
      "description": "Return partial screenshot on timeout instead of failing"
    },
    "selector": {
      "type": "string",
      "maxLength": 500,
      "description": "CSS selector of element to capture instead of full page"
    },
    "pdfFormat": {
      "type": "string",
      "enum": [
        "A4",
        "Letter",
        "Legal",
        "Tabloid",
        "A3"
      ],
      "description": "Paper size for PDF output (only applies when `format` is `pdf`)"
    },
    "pdfLandscape": {
      "type": "boolean",
      "description": "Use landscape orientation for PDF output"
    },
    "pdfPrintBackground": {
      "type": "boolean",
      "description": "Include background colors and images in PDF output"
    },
    "pdfScale": {
      "type": "number",
      "minimum": 0.1,
      "maximum": 2,
      "description": "Scale factor for PDF rendering (0.1 to 2)"
    },
    "pdfMargin": {
      "type": "object",
      "description": "Page margins for PDF output (CSS units, e.g. \"1cm\", \"0.5in\")",
      "properties": {
        "top": {
          "type": "string"
        },
        "right": {
          "type": "string"
        },
        "bottom": {
          "type": "string"
        },
        "left": {
          "type": "string"
        }
      }
    },
    "geo": {
      "type": "string",
      "minLength": 2,
      "maxLength": 2,
      "description": "ISO 3166-1 alpha-2 country code for geo-targeted rendering (Pro/Enterprise)"
    },
    "geoCity": {
      "type": "string",
      "maxLength": 100,
      "description": "City for geo-targeted rendering (Pro/Enterprise)"
    },
    "geoState": {
      "type": "string",
      "maxLength": 100,
      "description": "State or region for geo-targeted rendering (Pro/Enterprise)"
    },
    "async": {
      "type": "boolean",
      "description": "Process the capture asynchronously (returns a `jobId` to poll)"
    },
    "webhookUrl": {
      "type": "string",
      "format": "uri",
      "description": "URL to receive a webhook notification when the capture completes (Starter+ channel; Free/Basic poll GET /v1/jobs/{jobId} instead)."
    },
    "cacheTtl": {
      "type": "integer",
      "minimum": 3600,
      "maximum": 2592000,
      "description": "Cache time-to-live in seconds (1 hour to 30 days)"
    },
    "device": {
      "type": "string",
      "enum": [
        "desktop",
        "iphone_15",
        "iphone_se",
        "pixel_8",
        "ipad",
        "ipad_pro"
      ],
      "description": "Device preset — sets viewport, device scale, and user agent in one parameter. Explicit width/height/userAgent still win."
    },
    "hideSelectors": {
      "type": "array",
      "items": {
        "type": "string",
        "maxLength": 500
      },
      "maxItems": 50,
      "description": "CSS selectors to hide before capture (popups, sticky nav, chat bubbles). Never errors on a miss."
    },
    "blockCookieBanners": {
      "type": "boolean",
      "default": false,
      "description": "Hide common cookie/consent walls (OneTrust, Cookiebot, Quantcast, …) via a curated CSS list."
    },
    "hosted": {
      "type": "boolean",
      "default": false,
      "description": "Store the result in R2 and return `{url, expiresAt}` (a signed CDN-backed URL) instead of the image bytes. Drop the URL into an `<img>`/`og:image`."
    },
    "extract": {
      "type": "boolean",
      "default": false,
      "description": "Also return clean reader-mode content from the same render pass (use on `/v1/screenshot/json`; the binary endpoint rejects it). Shape set by `extractFormat`."
    },
    "extractFormat": {
      "type": "string",
      "enum": [
        "markdown",
        "json",
        "html",
        "text"
      ],
      "default": "markdown",
      "description": "Shape of the extracted content when `extract` is true."
    },
    "resizeWidth": {
      "type": "integer",
      "minimum": 16,
      "maximum": 3840,
      "description": "Downscale the output to this width (image formats only). Aspect ratio preserved when only one dimension is set. Never upscales."
    },
    "resizeHeight": {
      "type": "integer",
      "minimum": 16,
      "maximum": 2160,
      "description": "Downscale the output to this height (image formats only)."
    }
  }
}