{
  "openapi": "3.0.1",
  "info": {
    "title": "Website to Markdown for AI - Fast, Cheap, RAG-Ready Crawler",
    "description": "Turn URLs or whole websites into clean Markdown for LLMs and RAG. Main content only, tables, code, links. Title, language, dates, word and token counts, optional chunks. Plain HTTP first, browser only for JavaScript pages. PDFs included. Failed pages are free.",
    "version": "0.1",
    "x-build-id": "f7adnuepz7nxfEj0r"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/dottti~web-to-markdown/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-dottti-web-to-markdown",
        "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/dottti~web-to-markdown/runs": {
      "post": {
        "operationId": "runs-sync-dottti-web-to-markdown",
        "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/dottti~web-to-markdown/run-sync": {
      "post": {
        "operationId": "run-sync-dottti-web-to-markdown",
        "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": {
          "urls": {
            "title": "Page URLs (no crawling)",
            "type": "array",
            "description": "Single pages to convert, one per line. Each URL gives one row. Links on these pages are not followed. PDF links are read too. Example: https://en.wikipedia.org/wiki/Markdown",
            "items": {
              "type": "string"
            }
          },
          "startUrls": {
            "title": "Start URLs (crawl the site)",
            "type": "array",
            "description": "Websites or sections to crawl. The crawler follows links on the same site, stays inside the start URL's folder (see below) and stops at Max pages per start URL. Example: https://crawlee.dev/js/docs/quick-start crawls /js/docs/.",
            "items": {
              "type": "object",
              "required": [
                "url"
              ],
              "properties": {
                "url": {
                  "type": "string",
                  "title": "URL of a web page",
                  "format": "uri"
                }
              }
            }
          },
          "maxPages": {
            "title": "Max pages per start URL",
            "minimum": 1,
            "maximum": 100000,
            "type": "integer",
            "description": "Stop each crawl after this many saved pages. Failed, skipped and duplicate pages do not count. Pages in Page URLs are not limited by this.",
            "default": 50
          },
          "maxCrawlDepth": {
            "title": "Max link depth",
            "minimum": 0,
            "maximum": 20,
            "type": "integer",
            "description": "How many clicks away from the start URL to go. 0 = only the start URL (plus sitemap pages if Use sitemaps is on), 1 = the start URL and the pages it links to.",
            "default": 2
          },
          "useSitemaps": {
            "title": "Use sitemaps",
            "type": "boolean",
            "description": "Also read the site's sitemap.xml (and sitemaps listed in robots.txt) to find pages that are not linked. Sitemap pages are used after the followed links, and only those inside the crawl scope.",
            "default": true
          },
          "stayInsideStartPath": {
            "title": "Stay inside the start URL's folder",
            "type": "boolean",
            "description": "On: a start URL of https://example.com/docs/intro only crawls pages under https://example.com/docs/. Off: the whole site.",
            "default": true
          },
          "includeSubdomains": {
            "title": "Include subdomains",
            "type": "boolean",
            "description": "Also crawl subdomains of the start URL's site (blog.example.com when starting from example.com).",
            "default": false
          },
          "includeUrlGlobs": {
            "title": "Only crawl URLs matching",
            "type": "array",
            "description": "Optional URL patterns. When set, the crawler only saves and follows matching URLs (start URLs are always fetched). * matches inside one path part, ** matches anything. Example: https://example.com/blog/**. A pattern without https:// matches anywhere in the URL, for example /guide/.",
            "items": {
              "type": "object",
              "required": [
                "glob"
              ],
              "properties": {
                "glob": {
                  "type": "string",
                  "title": "Glob of a web page"
                }
              }
            }
          },
          "excludeUrlGlobs": {
            "title": "Skip URLs matching",
            "type": "array",
            "description": "Optional URL patterns to skip, for example **/tag/** or **?page=*. Same syntax as above.",
            "items": {
              "type": "object",
              "required": [
                "glob"
              ],
              "properties": {
                "glob": {
                  "type": "string",
                  "title": "Glob of a web page"
                }
              }
            }
          },
          "renderJs": {
            "title": "Render JavaScript",
            "enum": [
              "auto",
              "never",
              "always"
            ],
            "type": "string",
            "description": "auto (recommended): plain HTTP for every page, and a headless browser only for pages that come back as an empty JavaScript app shell or refuse plain requests. Those pages are charged as browser-rendered pages. never: plain HTTP only (cheapest). always: every page in the browser (slow, charged as browser-rendered).",
            "default": "auto"
          },
          "jsWaitSecs": {
            "title": "Browser wait (seconds)",
            "minimum": 1,
            "maximum": 60,
            "type": "integer",
            "description": "Longest wait for a JavaScript page to finish loading. The wait ends earlier once the page text stops changing.",
            "default": 8
          },
          "chunkSize": {
            "title": "Chunk size for RAG (tokens)",
            "minimum": 0,
            "maximum": 8000,
            "type": "integer",
            "description": "0 = no chunks. Above 0, each row also gets a chunks array: pieces of about this many tokens (o200k tokenizer) that keep paragraphs, lists, tables and code blocks whole where possible. Each chunk has an id, its heading path and its token count. Typical values: 256 to 1024.",
            "default": 0
          },
          "chunkOverlap": {
            "title": "Chunk overlap (tokens)",
            "minimum": 0,
            "maximum": 2000,
            "type": "integer",
            "description": "Tokens from the end of one chunk repeated at the start of the next, so context is not lost at the cut. At most half the chunk size.",
            "default": 64
          },
          "contentSelector": {
            "title": "Main content CSS selector",
            "type": "string",
            "description": "Optional. A CSS selector for the main content, for example article or .docs-content. When it matches, only that part of the page is converted. Leave empty for automatic detection."
          },
          "removeSelectors": {
            "title": "Extra elements to remove (CSS)",
            "type": "string",
            "description": "Optional. CSS selectors of extra parts to drop before conversion, comma separated. Menus, footers, cookie banners and share bars are already removed."
          },
          "includeImages": {
            "title": "Keep images in Markdown",
            "type": "boolean",
            "description": "Keep images as ![alt text](image URL). Off removes them (fewer tokens).",
            "default": true
          },
          "includeLinksInMarkdown": {
            "title": "Keep link URLs in Markdown",
            "type": "boolean",
            "description": "Keep links as [text](URL). Off keeps only the link text (fewer tokens).",
            "default": true
          },
          "includeLinkList": {
            "title": "Add a list of all links",
            "type": "boolean",
            "description": "Adds a links array (URL and anchor text) with every link found on the page, menus included. Up to 1,000 per page.",
            "default": false
          },
          "handlePdfs": {
            "title": "Read PDF links",
            "type": "boolean",
            "description": "Extract the text of PDF files (up to 8 MB, 300 pages) as Markdown. Scanned PDFs without a text layer return a free status row. Off: PDFs are skipped.",
            "default": true
          },
          "respectRobotsTxt": {
            "title": "Respect robots.txt",
            "type": "boolean",
            "description": "Skip pages the site's robots.txt does not allow, and honour its Crawl-delay (up to 10 seconds). Skipped pages return a free status row.",
            "default": true
          },
          "skipDuplicateContent": {
            "title": "Skip duplicate pages",
            "type": "boolean",
            "description": "When two URLs give exactly the same Markdown, save the first and return a free status row for the others.",
            "default": true
          },
          "onlyChanged": {
            "title": "Only new or changed pages (monitor mode)",
            "type": "boolean",
            "description": "Remembers each page's content between runs and saves only pages that are new or whose text changed. Unchanged pages are not saved and not charged. Schedule the actor to keep a knowledge base fresh. The first run saves everything.",
            "default": false
          },
          "stateName": {
            "title": "Monitor name",
            "type": "string",
            "description": "Separate memory for each monitor, so two schedules do not share history. Only used with monitor mode.",
            "default": "default"
          },
          "maxConcurrency": {
            "title": "Max parallel requests",
            "minimum": 1,
            "maximum": 50,
            "type": "integer",
            "description": "Pages fetched at the same time across all sites.",
            "default": 10
          },
          "maxConcurrencyPerSite": {
            "title": "Max parallel requests per site",
            "minimum": 1,
            "maximum": 20,
            "type": "integer",
            "description": "Polite limit for one website. The actor also slows down by itself when a site answers 429 Too Many Requests.",
            "default": 4
          },
          "requestTimeoutSecs": {
            "title": "Request timeout (seconds)",
            "minimum": 5,
            "maximum": 120,
            "type": "integer",
            "description": "Time limit for one plain HTTP request.",
            "default": 30
          },
          "maxRetries": {
            "title": "Retries per page",
            "minimum": 0,
            "maximum": 6,
            "type": "integer",
            "description": "Retries after network errors, 429 and 5xx answers, with growing pauses.",
            "default": 2
          },
          "proxyConfiguration": {
            "title": "Proxy",
            "type": "object",
            "description": "Optional. By default pages load without a proxy and a site that blocks us moves to Apify datacenter proxy. Set a proxy here to use it for every request."
          },
          "autoProxyFallback": {
            "title": "Automatic proxy fallback",
            "type": "boolean",
            "description": "When a site blocks us (403 or 429 with every header set), move that site to Apify datacenter proxy.",
            "default": true
          },
          "allowResidentialFallback": {
            "title": "Allow residential proxy as last step",
            "type": "boolean",
            "description": "Also try residential proxy for sites that block datacenter IPs. Off by default because residential traffic is slow; the price per page does not change.",
            "default": false
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}