{
  "openapi": "3.0.1",
  "info": {
    "title": "Bilibili Scraper — Videos, Comments, Danmaku & Stats",
    "description": "Extract Bilibili (B站) data by keyword, video URL or uploader: plays, likes, coins, favorites, tags and dates. Add danmaku (弹幕) with exact timestamps and colour - no login. Comments beyond 3 per video need a one-time QR login.",
    "version": "1.3",
    "x-build-id": "q6MHZZFK5rhe55ZGU"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/yu_ovo~bilibili-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-yu_ovo-bilibili-scraper",
        "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/yu_ovo~bilibili-scraper/runs": {
      "post": {
        "operationId": "runs-sync-yu_ovo-bilibili-scraper",
        "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/yu_ovo~bilibili-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-yu_ovo-bilibili-scraper",
        "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": {
          "keywords": {
            "title": "Search keywords",
            "minItems": 1,
            "type": "array",
            "description": "Terms to search on Bilibili. Each keyword is scraped separately; duplicates across keywords are dropped.",
            "items": {
              "type": "string"
            }
          },
          "videoUrls": {
            "title": "Video URLs or IDs",
            "type": "array",
            "description": "Scrape these exact videos instead of searching. Accepts full URLs (https://www.bilibili.com/video/BV...) or bare BVIDs. Combine with keywords or use alone.",
            "items": {
              "type": "string"
            }
          },
          "userUrls": {
            "title": "Uploader URLs or IDs",
            "type": "array",
            "description": "Scrape every video from these Bilibili uploaders (UP主). Accepts space URLs (https://space.bilibili.com/123456) or bare numeric IDs. Requires a login - Bilibili answers -799/-352 to anonymous requests for this endpoint, so set loginTimeoutSeconds above 0 and scan the QR.",
            "items": {
              "type": "string"
            }
          },
          "searchType": {
            "title": "Search type",
            "enum": [
              "video",
              "all"
            ],
            "type": "string",
            "description": "Which Bilibili search tab to use. 'video' is fastest and returns one row per video.",
            "default": "video"
          },
          "sortBy": {
            "title": "Sort order",
            "enum": [
              "relevance",
              "most_played",
              "newest",
              "most_danmaku",
              "most_favorited"
            ],
            "type": "string",
            "description": "How Bilibili should order the results before you scrape them.",
            "default": "relevance"
          },
          "maxItemsPerKeyword": {
            "title": "Max videos per keyword or uploader",
            "minimum": 1,
            "maximum": 5000,
            "type": "integer",
            "description": "Stop after this many new videos per keyword - or per uploader when you use userUrls. This is the main lever on run cost.",
            "default": 100
          },
          "maxPagesPerKeyword": {
            "title": "Max result pages per keyword",
            "minimum": 1,
            "maximum": 50,
            "type": "integer",
            "description": "Hard cap on how many result pages to open per keyword or per uploader (each search page holds roughly 40 videos, each uploader page 50). Raising it costs nothing when maxItemsPerKeyword is reached first.",
            "default": 10
          },
          "includeStats": {
            "title": "Fetch full video stats",
            "type": "boolean",
            "description": "Also read each video's own page data to attach exact likes, coins, favorites, shares, comment count, full description, tags and category. One extra request per video.",
            "default": true
          },
          "includeComments": {
            "title": "Fetch comments",
            "type": "boolean",
            "description": "Also collect top comments for each video. Adds one row per comment and increases run time and cost. Anonymous Bilibili returns 3 comments per video; log in for more.",
            "default": false
          },
          "maxCommentsPerVideo": {
            "title": "Max comments per video",
            "minimum": 0,
            "maximum": 200,
            "type": "integer",
            "description": "How many top-level comments to collect for each video when comments are enabled. Important: Bilibili only serves 3 comments per video to anonymous requests. To go beyond 3 you must be logged in - set 'QR login wait' above 0 and scan the code.",
            "default": 20
          },
          "commentSort": {
            "title": "Comment order",
            "enum": [
              "hot",
              "new"
            ],
            "type": "string",
            "description": "Order comments by popularity or by time.",
            "default": "hot"
          },
          "includeDanmaku": {
            "title": "Fetch danmaku (弹幕)",
            "type": "boolean",
            "description": "Also collect the danmaku (bullet comments) of each video: the text, the exact second it appears, its colour and mode. Unlike normal comments, danmaku need NO login. Each danmaku is one dataset row, so it is charged like any other result.",
            "default": false
          },
          "maxDanmakuPerVideo": {
            "title": "Max danmaku per video",
            "minimum": 0,
            "maximum": 5000,
            "type": "integer",
            "description": "How many danmaku to keep per video. Popular videos have thousands; Bilibili serves the current pool in one XML document. Each danmaku is billed as a normal result row, so raise this deliberately.",
            "default": 200
          },
          "bilibiliCookie": {
            "title": "Bilibili cookie (optional)",
            "type": "string",
            "description": "Optional. Your own logged-in Bilibili cookie, e.g. SESSDATA=xxx. You usually do not need this - leave it empty and the Actor will show a QR code to scan instead."
          },
          "loginTimeoutSeconds": {
            "title": "QR login wait (seconds)",
            "minimum": 0,
            "maximum": 1800,
            "type": "integer",
            "description": "How long to keep a login QR available. The code refreshes itself every ~3 minutes, so a long wait is safe. Uploader (UP主) scraping needs a login and always shows a QR. Comments also need a login to return more than 3 per video: set this above 0 to be shown a QR. 0 = stay anonymous and never block. If the scan never happens the run continues anonymously and says so, unless failWithoutLogin is on.",
            "default": 0
          },
          "resetStoredSession": {
            "title": "Forget the saved Bilibili login",
            "type": "boolean",
            "description": "Tick to delete the session saved by a previous run, so the next uploader run asks for a fresh QR scan. Use this if you switched accounts or the saved login stopped working.",
            "default": false
          },
          "failWithoutLogin": {
            "title": "Stop the run if login is skipped",
            "type": "boolean",
            "description": "ON: if a QR login is requested but not completed, the run fails with a clear message instead of returning partial data. Use it when the promise is 'all comments'. OFF (default): the run continues anonymously and returns whatever Bilibili allows (3 comments per video), and says so in SUMMARY.commentNote.",
            "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}