{
  "openapi": "3.0.1",
  "info": {
    "title": "Broken Link Checker & 404 Finder for Websites",
    "description": "Crawls a site's static HTML, checks every link, image, script and stylesheet it finds, and reports broken links, redirect chains, redirect loops and mixed content, with the referring pages needed to fix each one.",
    "version": "0.1",
    "x-build-id": "o3awMSVGb8CIb02dc"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/opendatalabs~broken-link-site-qa-checker/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-opendatalabs-broken-link-site-qa-checker",
        "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/opendatalabs~broken-link-site-qa-checker/runs": {
      "post": {
        "operationId": "runs-sync-opendatalabs-broken-link-site-qa-checker",
        "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/opendatalabs~broken-link-site-qa-checker/run-sync": {
      "post": {
        "operationId": "run-sync-opendatalabs-broken-link-site-qa-checker",
        "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",
        "properties": {
          "startUrls": {
            "title": "Start URLs",
            "maxItems": 1000,
            "type": "array",
            "description": "Pages to start crawling from. Usually just your homepage. Give a bare domain and it is upgraded to https://. Provide these, a sitemap URL, or both. Leave this and the sitemap empty to run a small demo crawl (5 pages, 50 links).",
            "items": {
              "type": "string"
            }
          },
          "sitemapUrl": {
            "title": "Sitemap URL or domain",
            "type": "string",
            "description": "Seeds the crawl from a sitemap instead of (or as well as) discovering pages by following links. Give a sitemap URL directly, or a bare domain to have the sitemap found through robots.txt, falling back to common paths. Sitemap indexes, gzipped sitemaps, plain-text URL lists and RSS feeds are all handled. This is the fastest way to cover a whole site without deep crawling."
          },
          "maxPages": {
            "title": "Max pages to crawl",
            "minimum": 1,
            "maximum": 50000,
            "type": "integer",
            "description": "Hard ceiling on pages fetched and parsed for links. The crawl is breadth-first, so stopping at this limit still covers the site broadly instead of tunnelling into one section.",
            "default": 500
          },
          "maxDepth": {
            "title": "Max crawl depth",
            "minimum": 0,
            "maximum": 20,
            "type": "integer",
            "description": "How many links deep to follow from the start URLs. 0 checks only the links on the start pages themselves. Pages seeded from a sitemap all start at depth 0.",
            "default": 3
          },
          "sameDomainOnly": {
            "title": "Only crawl your own site",
            "type": "boolean",
            "description": "Keeps the crawl on the hosts that count as your site. Off-site links are still checked when 'Check external links' is on, they are just not crawled into. Which hosts count as yours is controlled by 'Treat subdomains as the same site' below.",
            "default": true
          },
          "includeSubdomains": {
            "title": "Treat subdomains as the same site",
            "type": "boolean",
            "description": "Off by default, so only the exact hostnames you started from count as your site. Turn it on when your site genuinely spans several subdomains, such as www, blog and shop. Leaving it off matters on shared hosts like github.io, myshopify.com or substack.com, where a domain-wide match would pull in unrelated people's sites. Either way, if a start URL redirects to another host, for example example.com to www.example.com, that host is added automatically.",
            "default": false
          },
          "checkExternal": {
            "title": "Check external links",
            "type": "boolean",
            "description": "Also check links that point off your site. These are where most rot happens, but they are also where most false alarms come from, because large sites often challenge or rate-limit automated requests. Those come back as 'blocked', never as 'broken'.",
            "default": true
          },
          "respectRobots": {
            "title": "Respect robots.txt",
            "type": "boolean",
            "description": "Leave this on. Pages disallowed by robots.txt are not crawled. Turn it off only for a site you own and are authorised to crawl in full. It is never a way to get around bot protection: challenges and captchas are always reported as 'blocked' rather than bypassed.",
            "default": true
          },
          "concurrencyPerHost": {
            "title": "Concurrent requests per host",
            "minimum": 1,
            "maximum": 20,
            "type": "integer",
            "description": "How many requests may be in flight against any single host at once. Low on purpose: a crawl that hammers one small origin server gets rate-limited and returns misleading results. The overall run still progresses in parallel across different hosts.",
            "default": 2
          },
          "requestsPerSecond": {
            "title": "Requests per second",
            "minimum": 1,
            "maximum": 50,
            "type": "integer",
            "description": "Global rate ceiling across the whole run, enforced by a token bucket.",
            "default": 8
          },
          "maxLinksToCheck": {
            "title": "Max links to check",
            "minimum": 1,
            "maximum": 500000,
            "type": "integer",
            "description": "Safety cap on unique links checked. Each unique URL is checked once no matter how many pages reference it, so this number is usually much smaller than you expect.",
            "default": 10000
          },
          "maxRedirects": {
            "title": "Max redirects to follow",
            "minimum": 0,
            "maximum": 20,
            "type": "integer",
            "description": "Redirects are followed one hop at a time and the whole chain is recorded. Exceeding this limit is reported as a redirect loop.",
            "default": 10
          },
          "redirectChainThreshold": {
            "title": "Redirects before a link counts as a chain",
            "minimum": 1,
            "maximum": 10,
            "type": "integer",
            "description": "A single redirect is normal (http to https, or adding a trailing slash). Raise this if your site legitimately redirects twice and you only want to hear about longer chains.",
            "default": 1
          },
          "requestTimeoutSecs": {
            "title": "Request timeout (seconds)",
            "minimum": 5,
            "maximum": 300,
            "type": "integer",
            "description": "How long to wait for a single page fetch or link check before giving up on that attempt. A link that exceeds this is reported as 'timeout' rather than 'broken', because a slow server is not the same as a dead one. Raise it if you are checking links to known-slow hosts.",
            "default": 30
          },
          "maxRetries": {
            "title": "Attempts per request",
            "minimum": 1,
            "maximum": 6,
            "type": "integer",
            "description": "Total attempts, including the first. Only transient failures are retried; a 404 is answered immediately rather than retried three times.",
            "default": 2
          },
          "onlyNewProblems": {
            "title": "Only report new or changed problems",
            "type": "boolean",
            "description": "Monitor mode. Compares this run against the previous run's baseline and emits only links that are newly broken or whose status changed, including links that recovered. A link that has been broken for a month is real but is not news. The first run has no baseline, so it reports every problem and then stores the baseline.",
            "default": false
          },
          "stateStoreName": {
            "title": "Baseline key-value store name",
            "type": "string",
            "description": "Named key-value store holding the previous run's link statuses. A named store survives between runs, unlike the default store, which is what makes monitor mode work. Use one store per monitoring job.",
            "default": "broken-link-checker-state"
          },
          "stateKey": {
            "title": "Baseline key",
            "type": "string",
            "description": "Key inside that store. Leave empty to derive one from the first start URL, so several sites can share one store safely. Set it explicitly if you change start URLs but want to keep the same history."
          },
          "maxPageFailurePercentForBaselineUpdate": {
            "title": "Max page failure rate for updating the baseline",
            "minimum": 0,
            "maximum": 100,
            "type": "integer",
            "description": "Safety valve for monitor mode. If more than this share of pages fail to load, the baseline is left untouched, so one bad day at your origin server does not make the next run report the whole site as newly broken. A run that checks zero links never overwrites the baseline either.",
            "default": 50
          },
          "includeOkLinks": {
            "title": "Include working links in the output",
            "type": "boolean",
            "description": "Off by default, so the dataset contains only links that need attention. Turn it on to get a full inventory of every link on the site with its status.",
            "default": false
          },
          "seedFromSitemap": {
            "title": "Discover a sitemap from the start URL",
            "type": "boolean",
            "description": "When no sitemap URL is given, still try to find one through the start URL's robots.txt and common paths. Defaults to on only when you supplied a sitemap URL.",
            "default": false
          },
          "userAgentContact": {
            "title": "Contact string for the User-Agent",
            "type": "string",
            "description": "Appended to the User-Agent header, for example a URL or an address, so site owners can see who is checking their links. Optional; the Actor sends a descriptive User-Agent either way."
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}