{
  "openapi": "3.0.1",
  "info": {
    "title": "AI Web Scraper — Structured Data from Any Site, No Selectors",
    "description": "Give URLs and a plain-English instruction (optionally a JSON schema) and get clean structured JSON per page: products, prices, contacts, articles, listings. Cheap LLM via Apify's OpenRouter, billed at cost to your own account. $3 per 1,000 pages plus tokens.",
    "version": "0.1",
    "x-build-id": "ON7TLjP8JAo73sEub"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/actor-forge~ai-web-extractor/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-actor-forge-ai-web-extractor",
        "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/actor-forge~ai-web-extractor/runs": {
      "post": {
        "operationId": "runs-sync-actor-forge-ai-web-extractor",
        "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/actor-forge~ai-web-extractor/run-sync": {
      "post": {
        "operationId": "run-sync-actor-forge-ai-web-extractor",
        "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",
          "instruction"
        ],
        "properties": {
          "startUrls": {
            "title": "Page URLs",
            "type": "array",
            "description": "The web pages to extract data from. Each page is fetched as static HTML (no browser), converted to compact Markdown and sent to the AI model with your instruction.",
            "items": {
              "type": "object",
              "required": [
                "url"
              ],
              "properties": {
                "url": {
                  "type": "string",
                  "title": "URL of a web page",
                  "format": "uri"
                }
              }
            }
          },
          "instruction": {
            "title": "What to extract",
            "type": "string",
            "description": "Plain-English instruction, e.g. \"Extract the product name, price, currency and whether it is in stock\" or \"List every job opening with title, location and link\". The model only uses what is on the page and returns null for missing values."
          },
          "outputMode": {
            "title": "Output mode",
            "enum": [
              "object",
              "list"
            ],
            "type": "string",
            "description": "Object: one row per page with one JSON object. List: the model returns every matching item on the page (products, jobs, articles…) and you get one row per item. Either way a page is charged once.",
            "default": "object"
          },
          "schema": {
            "title": "Fields / JSON schema (optional)",
            "type": "object",
            "description": "Optional. Either a simple map of field names to descriptions, e.g. {\"name\": \"product name\", \"price\": \"number, no currency sign\", \"inStock\": \"true/false\"}, or a full JSON Schema ({\"type\": \"object\", \"properties\": {…}}), which is also sent to the model as a structured-output schema. In list mode it describes one item."
          },
          "model": {
            "title": "AI model",
            "type": "string",
            "description": "Any OpenRouter model id (see openrouter.ai/models), e.g. google/gemini-2.5-flash-lite (default: cheap, fast, good at extraction), openai/gpt-4o-mini, openai/gpt-4.1-nano or google/gemini-2.5-flash (smarter, ~6× the output price). Tokens are billed to your Apify account at OpenRouter rates.",
            "default": "google/gemini-2.5-flash-lite"
          },
          "maxLlmCostUsd": {
            "title": "Max AI token cost per run (USD)",
            "minimum": 0,
            "maximum": 100,
            "type": "number",
            "description": "Hard cap on the AI token charges this run may cause on your Apify account (estimated, including the 10× free-plan rate when it applies). Before each page the worst-case cost (its input plus maxOutputTokens) is reserved; the run stops cleanly when the next page would pass the cap. This is separate from the actor's own per-page fee, which the run's maximum total charge limits.",
            "default": 0.1
          },
          "maxPages": {
            "title": "Max pages",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "Stop after this many successfully extracted (charged) pages. Failed pages are free and don't count.",
            "default": 10
          },
          "maxCrawlDepth": {
            "title": "Follow links (crawl depth)",
            "minimum": 0,
            "maximum": 2,
            "type": "integer",
            "description": "0 = only the URLs above. 1 or 2 = also extract pages linked from them on the same site (same host), up to maxPages. Use include/exclude patterns to keep the crawl on the pages you want.",
            "default": 0
          },
          "includeGlobs": {
            "title": "Only follow links matching",
            "type": "array",
            "description": "When crawling, only follow URLs matching one of these glob patterns, e.g. https://example.com/products/** (`**` = anything, `*` = anything except /).",
            "items": {
              "type": "string"
            }
          },
          "excludeGlobs": {
            "title": "Never follow links matching",
            "type": "array",
            "description": "When crawling, skip URLs matching any of these glob patterns, e.g. **/login** or **/cart**.",
            "items": {
              "type": "string"
            }
          },
          "maxInputTokens": {
            "title": "Max input tokens per page",
            "minimum": 500,
            "maximum": 100000,
            "type": "integer",
            "description": "Page Markdown is cut to about this many tokens before it is sent to the model (rows say truncated: true). Lower = cheaper; raise it for long pages.",
            "default": 8000
          },
          "maxOutputTokens": {
            "title": "Max output tokens per page",
            "minimum": 50,
            "maximum": 16000,
            "type": "integer",
            "description": "max_tokens for each model reply. A list of 50 items needs roughly 1,500–3,000. If a reply is cut off, the complete items are kept and the row says truncated: true.",
            "default": 1500
          },
          "includeLinks": {
            "title": "Keep links in the page text",
            "type": "boolean",
            "description": "Keep link URLs in the Markdown sent to the model, so it can return product/article URLs. Switch off to save tokens when you don't need URLs.",
            "default": true
          },
          "onlyMainContent": {
            "title": "Main content only (articles)",
            "type": "boolean",
            "description": "Send only the main article (Mozilla Readability) instead of the whole page body. Good for news and blog posts; leave off for listings and product pages.",
            "default": false
          },
          "includeMarkdown": {
            "title": "Include page Markdown in output",
            "type": "boolean",
            "description": "Add the exact Markdown the model saw to each page's first row (handy for checking results).",
            "default": false
          },
          "allowPersonalData": {
            "title": "Allow personal contact data",
            "type": "boolean",
            "description": "Off (default): the model is told not to return private individuals' personal contact details, and personal-looking email addresses in the output are replaced (role mailboxes like info@ or sales@ are kept). Switch on only if you have a lawful basis to process personal data.",
            "default": false
          },
          "respectRobotsTxt": {
            "title": "Respect robots.txt",
            "type": "boolean",
            "description": "Skip pages the site's robots.txt disallows (free status row). Recommended.",
            "default": 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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}