{
  "openapi": "3.0.1",
  "info": {
    "title": "Website Screenshot & Change Monitor (PDF, Markdown)",
    "description": "Screenshot hundreds of URLs or a whole sitemap as PNG, JPEG or PDF, on desktop and mobile, and get alerted when a page changes: diff image in red, text added and removed, price and stock changes, Slack or Discord alerts. Markdown and JSON-LD for AI. Failed pages are free.",
    "version": "0.1",
    "x-build-id": "YQnC87QpXZF0lQDec"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/dgn-lab~website-screenshot-batch/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-dgn-lab-website-screenshot-batch",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/acts/dgn-lab~website-screenshot-batch/runs": {
      "post": {
        "operationId": "runs-sync-dgn-lab-website-screenshot-batch",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor and returns information about the initiated run in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/runsResponseSchema"
                }
              }
            }
          }
        }
      }
    },
    "/acts/dgn-lab~website-screenshot-batch/run-sync": {
      "post": {
        "operationId": "run-sync-dgn-lab-website-screenshot-batch",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "inputSchema": {
        "type": "object",
        "required": [
          "startUrls"
        ],
        "properties": {
          "startUrls": {
            "title": "URLs",
            "type": "array",
            "description": "Web pages to capture. Each distinct URL produces one screenshot and one result item. A sitemap URL (path like /sitemap.xml, /sitemap_index.xml or any .xml.gz file) is expanded into the pages it lists.",
            "items": {
              "type": "object",
              "properties": {
                "url": {
                  "type": "string",
                  "title": "URL",
                  "description": "HTTP(S) address to load."
                }
              },
              "required": [
                "url"
              ],
              "additionalProperties": true
            }
          },
          "urlIncludePattern": {
            "title": "Sitemap: include URLs matching",
            "type": "string",
            "description": "Regular expression (case-insensitive). Only sitemap pages whose URL matches are captured, e.g. \"/blog/\" or \"/products/[^/]+$\". Empty = all pages. Start URLs are not filtered.",
            "default": ""
          },
          "urlExcludePattern": {
            "title": "Sitemap: exclude URLs matching",
            "type": "string",
            "description": "Regular expression (case-insensitive). Sitemap pages whose URL matches are skipped, e.g. \"/tag/|/page/\\\\d+\". Empty = skip nothing.",
            "default": ""
          },
          "maxSitemapUrls": {
            "title": "Sitemap: max pages",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "Most pages taken from the sitemaps after filtering, in sitemap order; start URLs come on top. Reading sitemaps is free, each page checked is charged as usual.",
            "default": 100
          },
          "device": {
            "title": "Device",
            "enum": [
              "custom",
              "Desktop Chrome",
              "Desktop Chrome HiDPI",
              "iPhone 15",
              "iPhone 15 Pro Max",
              "Pixel 7",
              "iPad Pro 11"
            ],
            "type": "string",
            "description": "Emulate a real device (screen size, pixel density, mobile user agent and touch) or use a custom viewport.",
            "default": "custom"
          },
          "devices": {
            "title": "Several devices",
            "type": "array",
            "description": "Capture every URL on each of these devices in one run (e.g. desktop + iPhone). Overrides Device when set.",
            "items": {
              "type": "string",
              "enum": [
                "custom",
                "Desktop Chrome",
                "Desktop Chrome HiDPI",
                "iPhone 15",
                "iPhone 15 Pro Max",
                "Pixel 7",
                "iPad Pro 11"
              ],
              "enumTitles": [
                "Custom viewport (width and height below)",
                "Desktop 1280×720",
                "Desktop Retina 1280×720 @2x",
                "iPhone 15",
                "iPhone 15 Pro Max",
                "Google Pixel 7",
                "iPad Pro 11"
              ]
            },
            "default": []
          },
          "viewportWidth": {
            "title": "Viewport width",
            "minimum": 320,
            "maximum": 3840,
            "type": "integer",
            "description": "Browser window width in pixels (320-3840). Used when Device is Custom viewport.",
            "default": 1280
          },
          "viewportHeight": {
            "title": "Viewport height",
            "minimum": 240,
            "maximum": 2160,
            "type": "integer",
            "description": "Browser window height in pixels (240-2160). Used when Device is Custom viewport; also the screenshot height unless Full page is on.",
            "default": 800
          },
          "fullPage": {
            "title": "Full page",
            "type": "boolean",
            "description": "Capture the whole scrollable page instead of the visible viewport only.",
            "default": false
          },
          "longPages": {
            "title": "Very long pages",
            "enum": [
              "split",
              "cut"
            ],
            "type": "string",
            "description": "Full-page captures taller than the image size limit (about 60,000 pixels) are split into several images, or cut at the limit.",
            "default": "split"
          },
          "format": {
            "title": "Image format",
            "enum": [
              "png",
              "jpeg",
              "pdf"
            ],
            "type": "string",
            "description": "PNG is lossless, JPEG files are smaller, PDF keeps text selectable (always the whole page).",
            "default": "png"
          },
          "jpegQuality": {
            "title": "JPEG quality",
            "minimum": 1,
            "maximum": 100,
            "type": "integer",
            "description": "JPEG quality from 1 to 100 (ignored for PNG).",
            "default": 80
          },
          "pdfFormat": {
            "title": "PDF paper size",
            "enum": [
              "A4",
              "Letter",
              "Legal",
              "A3"
            ],
            "type": "string",
            "description": "Paper size of PDF files.",
            "default": "A4"
          },
          "pdfLandscape": {
            "title": "PDF landscape",
            "type": "boolean",
            "description": "Landscape orientation for PDF files.",
            "default": false
          },
          "pdfMargin": {
            "title": "PDF margins",
            "enum": [
              "none",
              "small",
              "normal"
            ],
            "type": "string",
            "description": "Margins of PDF pages.",
            "default": "none"
          },
          "darkMode": {
            "title": "Dark mode",
            "type": "boolean",
            "description": "Ask the page to use its dark color scheme (prefers-color-scheme: dark), when the site supports it.",
            "default": false
          },
          "dismissCookieBanners": {
            "title": "Close cookie banners",
            "type": "boolean",
            "description": "Try to accept common visible cookie-consent banners before capturing. Best effort: some banners, closed shadow roots and custom flows are unsupported. Disable to preserve the first-visit consent screen.",
            "default": true
          },
          "hideSelectors": {
            "title": "Hide elements",
            "type": "array",
            "description": "CSS selectors of elements to hide before capturing, e.g. cookie banners, chat widgets or popups: \"#cookie-banner\", \".intercom-launcher\".",
            "items": {
              "type": "string"
            },
            "default": []
          },
          "hideDistractions": {
            "title": "Hide distractions",
            "type": "boolean",
            "description": "Hide live-chat widgets (Intercom, Drift, Crisp, HubSpot, Zendesk, Tawk.to, LiveChat, Tidio, Freshchat, Olark and more) and ad slots (Google ads, Taboola, Outbrain; their space is kept), finish CSS animations and transitions, hide the text caret and pause videos on their first frame before capturing. Gives cleaner screenshots and fewer false changes when monitoring. Turn off to capture the page exactly as a visitor sees it, e.g. to check ads.",
            "default": true
          },
          "cookies": {
            "title": "Cookies",
            "type": "array",
            "description": "Cookies set before loading the pages, e.g. a session cookie to capture pages behind a login: [{\"name\": \"session\", \"value\": \"...\"}]. Without \"domain\" a cookie applies to the host of each captured URL only; with \"domain\": \".example.com\" (and optional \"path\") to that domain and its subdomains. Sitemap downloads get the cookies that match their host the same way (without \"domain\": the host of the sitemap URL you entered). Stored encrypted and never logged."
          },
          "headers": {
            "title": "HTTP headers",
            "type": "object",
            "description": "Extra HTTP headers, e.g. {\"Authorization\": \"Bearer ...\"} or {\"X-Api-Key\": \"...\"}. Sent only to the host of each captured URL unless \"Send headers to every domain\" is on. Stored encrypted and never logged."
          },
          "headersForAllDomains": {
            "title": "Send headers to every domain",
            "type": "boolean",
            "description": "Off (recommended): HTTP headers are sent only to the host of each URL being captured, so an Authorization header or API key never reaches third-party scripts, images, fonts or redirects to other domains. Sitemap files follow the same rule: headers go to the host of the sitemap URL you entered, not to nested sitemaps or redirects on other hosts. On: headers go with every request the page makes and with every sitemap download.",
            "default": false
          },
          "locale": {
            "title": "Language",
            "type": "string",
            "description": "Browser language, e.g. fr-FR or de-DE (Accept-Language and navigator.language). Leave empty for the device default.",
            "default": ""
          },
          "timezoneId": {
            "title": "Time zone",
            "type": "string",
            "description": "Browser time zone, e.g. Europe/Paris or America/New_York. Leave empty for UTC.",
            "default": ""
          },
          "scrollToBottom": {
            "title": "Scroll to load lazy content",
            "type": "boolean",
            "description": "Scroll through the page before capturing so lazy-loaded images and sections appear. Useful with Full page.",
            "default": false
          },
          "waitUntil": {
            "title": "Wait until",
            "enum": [
              "load",
              "domcontentloaded",
              "networkidle"
            ],
            "type": "string",
            "description": "When navigation is considered finished before capturing. With Page loaded, a load event held back by a slow third-party resource is awaited for at most 15 seconds, then the page is captured once its fonts and visible images are ready.",
            "default": "load"
          },
          "waitForSelector": {
            "title": "Wait for element",
            "type": "string",
            "description": "Optional CSS selector to wait for before capturing, e.g. #pricing or main. Useful when the page renders content after navigation. The first matching element must be visible.",
            "default": ""
          },
          "captureSelector": {
            "title": "Capture element",
            "type": "string",
            "description": "Optional CSS selector to capture only the first matching element, e.g. #pricing or article. PNG/JPEG only; overrides Full page. Leave empty for the whole page or viewport.",
            "default": ""
          },
          "selectorTimeoutSecs": {
            "title": "Element wait timeout",
            "minimum": 1,
            "maximum": 120,
            "type": "integer",
            "description": "Maximum wait for Wait for element or Capture element. A missing element produces a failed item with a reason.",
            "default": 30
          },
          "delayMs": {
            "title": "Extra delay",
            "minimum": 0,
            "maximum": 60000,
            "type": "integer",
            "description": "Additional wait after loading, for animations or late content.",
            "default": 0
          },
          "pageTimeoutSecs": {
            "title": "Page timeout",
            "minimum": 5,
            "maximum": 300,
            "type": "integer",
            "description": "Maximum time to load a page.",
            "default": 60
          },
          "monitorChanges": {
            "title": "Monitor changes",
            "type": "boolean",
            "description": "Compare each page with its capture from the previous run (same URL, device and capture settings) and report changed, changePercent and textChanged. Run on a schedule to watch competitor or own pages. The first run saves the baseline (changed = null).",
            "default": false
          },
          "onlyChanges": {
            "title": "Only changed pages",
            "type": "boolean",
            "description": "With Monitor changes, skip unchanged pages: they get no dataset item and no saved screenshot. First-run baselines, changed pages (including a structured price or stock change) and failures are always reported.",
            "default": false
          },
          "changeThresholdPercent": {
            "title": "Change threshold",
            "minimum": 0,
            "maximum": 100,
            "type": "number",
            "description": "With Monitor changes, a page counts as changed only when more than this share of its pixels differs. Raise it (e.g. 0.5) to ignore tiny changes such as a clock or a rotating ad. 0 reports any visual change.",
            "default": 0
          },
          "ignoreSelectors": {
            "title": "Ignore regions",
            "type": "array",
            "description": "With Monitor changes, CSS selectors of dynamic areas left out of the comparison, e.g. a clock, a rotating carousel or a visitor counter: \"#clock\", \".hero-carousel\". They are masked in a separate comparison image and their text is left out of textChanged; the delivered screenshot still shows them. PNG/JPEG only.",
            "items": {
              "type": "string"
            },
            "default": []
          },
          "stateStoreName": {
            "title": "Monitoring store name",
            "pattern": "^[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$",
            "type": "string",
            "description": "Named key-value store keeping the previous capture of each page. Use a different name per independent watch list. Letters, digits and hyphens only.",
            "default": "website-screenshot-monitor"
          },
          "notificationWebhookUrl": {
            "title": "Notification webhook URL",
            "type": "string",
            "description": "Optional URL that receives a POST summary when at least one monitored page changed. Slack incoming webhooks and Discord webhooks get a chat message; for Telegram use https://api.telegram.org/bot<token>/sendMessage?chat_id=<id>; any other URL receives JSON. Stored encrypted; a failing webhook never fails the run."
          },
          "extractText": {
            "title": "Extract page text",
            "type": "boolean",
            "description": "Also return the visible text of the page, or of Capture element when set, in the text field. Useful for AI agents, search indexes and archives.",
            "default": false
          },
          "textFormat": {
            "title": "Text format",
            "enum": [
              "text",
              "markdown"
            ],
            "type": "string",
            "description": "Plain text, or Markdown that keeps headings, lists, links and tables.",
            "default": "text"
          },
          "maxTextLength": {
            "title": "Max text length",
            "minimum": 0,
            "maximum": 1000000,
            "type": "integer",
            "description": "Longer text is cut at this number of characters and marked textTruncated. 0 = no limit.",
            "default": 20000
          },
          "extractMetadata": {
            "title": "Extract metadata",
            "type": "boolean",
            "description": "Return the meta description, canonical URL, language, first heading and Open Graph tags in the metadata field.",
            "default": false
          },
          "extractStructuredData": {
            "title": "Extract structured data",
            "type": "boolean",
            "description": "Return the page's JSON-LD structured data in the structuredData field, with a flat summary: for a schema.org Product its price, priceCurrency and availability; for an Article its headline and publication date. Invalid blocks are skipped and counted; the raw blocks are capped at 50,000 characters. With Monitor changes, it also turns on price monitoring: the product's price, currency and availability are stored between runs and reported as priceChanged, previousPrice, priceChangePercent, availabilityChanged and previousAvailability; a price or stock change counts as a change for Only changed pages and notifications.",
            "default": false
          },
          "maxRetries": {
            "title": "Max retries",
            "minimum": 0,
            "maximum": 10,
            "type": "integer",
            "description": "How many times a failed page is retried before it is reported as failed. Definitive answers (HTTP 401, 403, 404, 410, 451) are reported as failed at once, without retries.",
            "default": 2
          },
          "maxConcurrency": {
            "title": "Max concurrency",
            "minimum": 1,
            "maximum": 10,
            "type": "integer",
            "description": "Maximum number of pages captured in parallel.",
            "default": 3
          },
          "proxyConfiguration": {
            "title": "Proxy configuration",
            "type": "object",
            "description": "Optional proxies, e.g. to capture a site from a given country or one that blocks data centers. With Apify residential proxies, the page and its data requests go through the proxy and its static files (scripts, styles, images, fonts, videos) are downloaded directly, which keeps residential traffic about 10 times lower; a file refused that way is fetched through the proxy.",
            "properties": {
              "useApifyProxy": {
                "type": "boolean",
                "title": "Use Apify Proxy",
                "description": "Whether to use Apify Proxy."
              },
              "apifyProxyGroups": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "title": "Apify Proxy groups",
                "description": "Proxy groups requested from Apify Proxy."
              },
              "apifyProxyCountry": {
                "type": "string",
                "title": "Proxy country",
                "description": "Country code for the requested proxy exit."
              },
              "proxyUrls": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "title": "Custom proxy URLs",
                "description": "URLs of custom proxy servers."
              }
            },
            "default": {
              "useApifyProxy": false
            },
            "additionalProperties": true
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}