{
  "openapi": "3.0.1",
  "info": {
    "title": "YouTube Metadata Scraper (Hashtag Video Finder)",
    "description": "The YouTube Metadata Scraper actor collects video details like titles, views, likes, upload dates, channels, and tags. It supports keyword or channel-based scraping for large-scale data extraction. Ideal for analytics, SEO tracking, research, and automating YouTube content monitoring.",
    "version": "0.1",
    "x-build-id": "tg4Wusoi4HDA7lLOl"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/scraper-engine~youtube-metadata-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-scraper-engine-youtube-metadata-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/scraper-engine~youtube-metadata-scraper/runs": {
      "post": {
        "operationId": "runs-sync-scraper-engine-youtube-metadata-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/scraper-engine~youtube-metadata-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-scraper-engine-youtube-metadata-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": {
          "hashtags": {
            "title": "#️⃣ Hashtags to open",
            "type": "array",
            "description": "Tags with or without the leading `#`. Full `youtube.com/hashtag/<tag>` links work too. Spaces are removed — YouTube hashtags have none. Example: `minecraft`, `#sourdoughstarter`.",
            "items": {
              "type": "string"
            }
          },
          "hashtagTab": {
            "title": "🗂️ Which hashtag tab",
            "enum": [
              "all",
              "shorts",
              "both"
            ],
            "type": "string",
            "description": "The two tabs are genuinely different corpora — measured overlap between them was **0 videos**. Pick `Both` when you want maximum coverage of a tag.",
            "default": "all"
          },
          "maxVideosPerHashtag": {
            "title": "🔢 Videos per hashtag (per tab)",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "Cap on videos collected from each tag. With `Both tabs` the cap applies to **each tab separately**, so you can get up to 2× this number per tag. Measured real depth: ~235–485 on the All tab, up to ~946 on Shorts — asking for more just stops early.",
            "default": 30
          },
          "skipUnknownHashtags": {
            "title": "🚫 Skip hashtags that don't exist",
            "type": "boolean",
            "description": "A tag with no public videos returns an empty feed and no tag header. On — log a warning and carry on with the other tags. Off — stop the run so a typo cannot pass unnoticed.",
            "default": true
          },
          "includeVideoHashtags": {
            "title": "🏷️ Extract each video's own hashtags",
            "type": "boolean",
            "description": "Fills `videoHashtags` from the #-chips above the title, the #-tokens creators put in the title itself, and the #-tokens in the description. The `#12 on Trending` super-title is recognised as a decoy and rejected.",
            "default": true
          },
          "includeRelatedHashtags": {
            "title": "🔗 Rank co-occurring hashtags",
            "type": "boolean",
            "description": "Fills `relatedHashtags` per row (the video's other tags, minus the one you searched) and writes a run-level ranking of the tags that appear most often alongside yours to the `HASHTAG_INSIGHTS` key-value record.",
            "default": true
          },
          "urls": {
            "title": "🎯 Specific video links or IDs",
            "type": "array",
            "description": "Watch links, `youtu.be` links, `/shorts/`, `/live/` and `/embed/` links, or bare 11-character video IDs. Leave empty for pure hashtag discovery.",
            "items": {
              "type": "string"
            }
          },
          "keywords": {
            "title": "🔤 Keyword search (secondary corpus)",
            "type": "array",
            "description": "Ordinary YouTube search phrases, one per line. Useful as a comparison set: search returns fresher but less tag-faithful videos than a hashtag feed.",
            "items": {
              "type": "string"
            }
          },
          "max_results_per_keyword": {
            "title": "📈 Cap per keyword",
            "minimum": 1,
            "maximum": 100000,
            "type": "integer",
            "description": "How many videos to take per keyword. Deep paging is fixed in this build, but YouTube itself runs out of search results at roughly **130–485 videos per keyword** — values above that simply stop early.",
            "default": 10
          },
          "sort_order": {
            "title": "🥇 Keyword result ordering",
            "enum": [
              "relevance",
              "upload_date",
              "view_count",
              "rating"
            ],
            "type": "string",
            "description": "Applies to the **keyword** search only — hashtag feeds have no sort control. YouTube's live menu now honours only Relevance and View count; the other two values are kept for compatibility and log a warning.",
            "default": "relevance"
          },
          "publishedAfter": {
            "title": "📅 Only videos uploaded on/after",
            "type": "string",
            "description": "Absolute (`2026-01-31`) or relative (`3 months`). Leave empty to keep everything. Remember that hashtag feeds skew old — a tight window can legitimately return very few rows."
          },
          "max_comments": {
            "title": "🗨️ Comments to pull per video",
            "minimum": 0,
            "maximum": 5000,
            "type": "integer",
            "description": "Top-level comments per video (replies are not fetched). `0` skips the comment requests entirely and makes the run much faster. Verified exact: asking for 300 returns 300.",
            "default": 2
          },
          "include_transcripts": {
            "title": "📜 Attach captions / transcript text",
            "type": "boolean",
            "description": "Fetches caption text when YouTube exposes it. Transcripts require a residential exit — on a datacenter IP YouTube returns zero caption tracks even when the page itself loads.",
            "default": true
          },
          "transcript_format": {
            "title": "🧱 Transcript shape",
            "enum": [
              "text",
              "timestamps"
            ],
            "type": "string",
            "description": "`Plain text` puts a single string in `transcripts[].content`; `Timed segments` puts a list of `{start, dur, text}` objects there instead.",
            "default": "text"
          },
          "include_english_auto": {
            "title": "⚙️ Allow auto-generated English captions",
            "type": "boolean",
            "description": "Adds YouTube's machine captions when a creator uploaded none. Many videos — most Shorts especially — have nothing else.",
            "default": false
          },
          "include_non_english": {
            "title": "🗺️ Allow other-language caption tracks",
            "type": "boolean",
            "description": "One video can expose 38 language tracks, each a separate download. This build caps a row at 6 distinct tracks and aborts caption collection after 150 s so a run cannot hang.",
            "default": false
          },
          "proxyConfiguration": {
            "title": "🛰️ Proxy / exit network",
            "type": "object",
            "description": "Your selection is honoured for every request. If YouTube still rejects the exit, the run escalates to Apify RESIDENTIAL (US) and says so in the log rather than silently returning empty rows.",
            "default": {
              "useApifyProxy": true,
              "apifyProxyGroups": [
                "RESIDENTIAL"
              ],
              "apifyProxyCountryCode": "US"
            }
          }
        }
      },
      "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
                  }
                }
              },
              "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}