{
  "title": "Website Link Health - Broken Links & Recovery",
  "type": "object",
  "schemaVersion": 1,
  "description": "Start with the public crawler-test example. For your own site, paste the exact pages whose outgoing links matter.",
  "properties": {
    "startUrls": {
      "title": "Pages to inspect",
      "type": "array",
      "editor": "stringList",
      "description": "Public HTTP(S) page URLs. The Actor reads links on these exact pages; it does not crawl onward. Up to20URLs.",
      "prefill": [
        "https://crawler-test.com/links/broken_links_internal"
      ],
      "default": [
        "https://crawler-test.com/links/broken_links_internal"
      ]
    },
    "checkExternal": {
      "title": "Check external links",
      "type": "boolean",
      "description": "Check links pointing to other origins as well as links on the source site. External pages are never crawled.",
      "default": true
    },
    "includeImages": {
      "title": "Include image sources",
      "type": "boolean",
      "description": "Also inspect image src URLs from the supplied HTML; srcset, CSS backgrounds, scripts and stylesheets are outside scope.",
      "default": false
    },
    "maxPages": {
      "title": "Maximum source pages",
      "type": "integer",
      "description": "Read at most this many supplied URLs. Unreached input pages make the run incomplete and prevent baseline updates.",
      "default": 5,
      "minimum": 1,
      "maximum": 20
    },
    "maxLinks": {
      "title": "Maximum unique targets",
      "type": "integer",
      "description": "Maximum unique discovered target URLs to check. If more are present, the run reports partial coverage and leaves saved history unchanged.",
      "default": 100,
      "minimum": 1,
      "maximum": 500
    },
    "maxResults": {
      "title": "Maximum saved rows",
      "type": "integer",
      "description": "One charged row per unique checked URL. Lowering this below the discovered target count creates partial coverage.",
      "default": 100,
      "minimum": 1,
      "maximum": 500
    },
    "comparePrevious": {
      "title": "Compare with a saved baseline",
      "type": "boolean",
      "description": "Save a complete determinate result set and compare later matching runs. First run establishes the baseline. Incomplete runs never advance it.",
      "default": false
    },
    "onlyChanges": {
      "title": "Save changed targets only",
      "type": "boolean",
      "description": "Implies comparison. Skip targets whose HTTP classification, status, destination and redirect chain are unchanged. A missing link is never called recovered.",
      "default": false
    },
    "snapshotName": {
      "title": "Baseline label",
      "type": "string",
      "editor": "textfield",
      "description": "Use a stable label of1-80letters, numbers, underscores or hyphens for a watchlist; avoid overlapping writers.",
      "default": "default",
      "pattern": "^[-\\w]{1,80}$"
    },
    "maxRequests": {
      "title": "Maximum HTTP requests",
      "type": "integer",
      "description": "Hard ceiling covering source pages, robots.txt, redirects and target checks. Reaching the ceiling reports partial coverage.",
      "default": 350,
      "minimum": 10,
      "maximum": 1500
    },
    "maxRunSeconds": {
      "title": "Run time budget (seconds)",
      "type": "integer",
      "description": "Stop within this time budget, retaining saved results and explicit incomplete coverage. No automatic proxy or paid fallback.",
      "default": 90,
      "minimum": 30,
      "maximum": 180
    }
  },
  "required": []
}
