{
  "openapi": "3.0.1",
  "info": {
    "title": "YouTube Scraper AIO | Videos, Shorts, Comments, Views/Hour",
    "description": "YouTube scraper AIO: channel videos, YouTube Shorts, live, playlists & search with YouTube filters, plus comments. One call per video URL from n8n, Make, Zapier, API or AI agents (MCP). Views, views/hour, outlier score, likes, Most Replayed. Transcripts from Dec. No API key. $1 per 1,000 videos.",
    "version": "0.0",
    "x-build-id": "74qLGthatqpUbbWcX"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/tactful_anvil~youtube-channel-shorts-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-tactful_anvil-youtube-channel-shorts-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/tactful_anvil~youtube-channel-shorts-scraper/runs": {
      "post": {
        "operationId": "runs-sync-tactful_anvil-youtube-channel-shorts-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/tactful_anvil~youtube-channel-shorts-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-tactful_anvil-youtube-channel-shorts-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": {
          "channels": {
            "title": "Channels",
            "type": "array",
            "description": "Channel URLs, @handles or UC… ids, one per line. Videos and/or Shorts tabs are scraped.",
            "items": {
              "type": "string"
            }
          },
          "searchQueries": {
            "title": "Search queries",
            "type": "array",
            "description": "YouTube searches, one per line. Combine with Uploaded within + Sort by to find what is going viral right now.",
            "items": {
              "type": "string"
            }
          },
          "searchType": {
            "title": "Search: find videos or channels",
            "enum": [
              "videos",
              "channels"
            ],
            "type": "string",
            "description": "What your <b>Search queries</b> look for. <code>videos</code> (default) = video / Shorts rows, exactly as before. <code>channels</code> = YouTube's Channel filter: one row per unique channel (name, @handle, channel ID, URL, subscribers, verified, description) plus free details — video count, median views of the latest videos and Shorts, uploads per week, days since the last upload, country, joined date, total views and links. Repeats and channels outside your subscriber range are skipped free. Channels, video URLs and playlists you add still return videos.",
            "default": "videos"
          },
          "maxChannels": {
            "title": "Channel search: max channels per query",
            "minimum": 1,
            "maximum": 500,
            "type": "integer",
            "description": "With Search type <code>channels</code>: unique channels per search query (1–500). Each delivered channel is one paid <code>channel</code> event ($0.002).",
            "default": 20
          },
          "minSubscribers": {
            "title": "Channel search: min subscribers",
            "minimum": 0,
            "type": "integer",
            "description": "With Search type <code>channels</code>: keep only channels with at least this many subscribers. Free filter, applied before charging. Channels that hide their count are skipped when a limit is set."
          },
          "maxSubscribers": {
            "title": "Channel search: max subscribers",
            "minimum": 0,
            "type": "integer",
            "description": "With Search type <code>channels</code>: keep only channels with at most this many subscribers (e.g. <code>100000</code> for micro-influencers). Free filter, applied before charging."
          },
          "channelDetails": {
            "title": "Channel search: free details",
            "type": "boolean",
            "description": "With Search type <code>channels</code>: read each found channel's first Videos page (and Shorts page when Content type includes Shorts) and its About panel — 2–3 free requests per channel, up to 250 channels per run — for video count, median views, uploads/week, last upload, country, joined date, total views and links. Off = search cards only (faster), same price.",
            "default": true
          },
          "videoUrls": {
            "title": "Video URLs / IDs (details only)",
            "type": "array",
            "description": "watch?v=…, /shorts/…, youtu.be/… or 11-char ids → exact details (and comments if enabled).",
            "items": {
              "type": "string"
            }
          },
          "playlistUrls": {
            "title": "Playlist URLs / IDs",
            "type": "array",
            "description": "playlist?list=PL… URLs or PL… ids (e.g. a campaign's list of approved videos). Each video is one Video row with its own channel. YouTube shows our client the first page of a playlist (up to 100 videos).",
            "items": {
              "type": "string"
            }
          },
          "contentType": {
            "title": "Content type",
            "enum": [
              "both",
              "videos",
              "shorts",
              "live",
              "all"
            ],
            "type": "string",
            "description": "Which tabs (channels) / result types (search) to collect. Live = the channel's Live tab (past streams with views, live-now with viewers, upcoming) or, for searches, streams that are live right now.",
            "default": "both"
          },
          "maxVideos": {
            "title": "Max videos per channel tab / search",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "Per channel tab and per search type (30 per page).",
            "default": 50
          },
          "channelSort": {
            "title": "Channel videos order",
            "enum": [
              "latest",
              "popular",
              "oldest"
            ],
            "type": "string",
            "description": "Order of the channel tabs as YouTube shows them (Videos, Shorts and Live each use their own Latest/Popular/Oldest chips).",
            "default": "latest"
          },
          "uploadedWithin": {
            "title": "Search: uploaded within",
            "enum": [
              "any",
              "hour",
              "today",
              "week",
              "month",
              "year"
            ],
            "type": "string",
            "description": "YouTube upload-date filter for search queries.",
            "default": "any"
          },
          "sortBy": {
            "title": "Search: sort by",
            "enum": [
              "relevance",
              "upload_date",
              "view_count",
              "rating"
            ],
            "type": "string",
            "description": "YouTube sort order for search queries. Note: YouTube now treats Upload date and Rating only loosely (results are roughly, not strictly, newest first) — use Sort results by → Newest for an exact order.",
            "default": "relevance"
          },
          "videoLength": {
            "title": "Video length",
            "enum": [
              "any",
              "short",
              "medium",
              "long"
            ],
            "type": "string",
            "description": "Searches use YouTube's own length filter; channel tabs and playlists are filtered here, for free, before anything is charged (cards carry the length). Shorts are at most 3 minutes, so Medium/Long skip Shorts entirely. Live-now streams have no length yet and are kept.",
            "default": "any"
          },
          "searchFeatures": {
            "title": "Search: features",
            "type": "array",
            "description": "YouTube's search feature filters (Filters → Features). Pick several and every result must have all of them. Searches only.",
            "items": {
              "type": "string",
              "enum": [
                "live",
                "4k",
                "hd",
                "subtitles",
                "creative_commons",
                "360",
                "vr180",
                "3d",
                "hdr",
                "location",
                "purchased"
              ],
              "enumTitles": [
                "Live",
                "4K",
                "HD",
                "Subtitles/CC",
                "Creative Commons",
                "360°",
                "VR180",
                "3D",
                "HDR",
                "Location",
                "Purchased"
              ]
            }
          },
          "searchCountry": {
            "title": "Search: country",
            "type": "string",
            "description": "Two-letter country code YouTube searches from, like its Location setting (e.g. <code>GB</code>, <code>DE</code>, <code>IN</code>). Changes which videos rank, not what is available. Empty = US."
          },
          "minViews": {
            "title": "Min views",
            "minimum": 0,
            "type": "integer",
            "description": "Drop cards below this view count (free filter, applied before charging). Paging continues until <code>maxVideos</code> matching videos are found (bounded by <code>maxScan</code>).",
            "default": 0
          },
          "minDurationSec": {
            "title": "Min length (seconds)",
            "minimum": 0,
            "type": "integer",
            "description": "Only videos at least this long (e.g. <code>1800</code> = 30-minute podcasts and streams to clip from). Free filter before charging, every source; combines with Video length."
          },
          "maxDurationSec": {
            "title": "Max length (seconds)",
            "minimum": 0,
            "type": "integer",
            "description": "Only videos at most this long. Free filter before charging, every source. Shorts listings show no length, so Shorts are kept only when Min/Max cover the whole 0–180 s Shorts range."
          },
          "oldestPostDate": {
            "title": "Oldest post date",
            "type": "string",
            "description": "Only videos published on or after this day (UTC, inclusive). A date like <code>2026-09-01</code> or a relative window like <code>30 days</code>, <code>2 weeks</code>, <code>3 months</code> (relative is best for scheduled runs). Free filter applied before charging; latest-first channel tabs stop paging at the date. Leave empty for no limit."
          },
          "maxScan": {
            "title": "Max cards to scan (filters / ranking)",
            "minimum": 50,
            "maximum": 2000,
            "type": "integer",
            "description": "How many cards may be scanned per channel tab / search to find <code>maxVideos</code> matches when <code>minViews</code>, <code>oldestPostDate</code> or a length filter is set (default 10 × maxVideos, 50–2000). With <code>sortResultsBy</code>, setting it ranks the best <code>maxVideos</code> out of this many. Scanned-but-dropped cards are free."
          },
          "sortResultsBy": {
            "title": "Sort results by",
            "enum": [
              "none",
              "viewsPerHour",
              "views",
              "newest",
              "outlierScore"
            ],
            "type": "string",
            "description": "Rank the results here, for free, before <code>maxVideos</code> is applied and before anything is charged — e.g. a channel's last 30 days by views/hour = what to clip first. One ranking across the whole run; each row gets <code>rank</code>. Outlier score works for channels, searches and playlists (searches and playlists read each result's channel — see Outlier score for search results).",
            "default": "none"
          },
          "searchOutliers": {
            "title": "Outlier score for search & playlist results",
            "type": "boolean",
            "description": "Score every search / playlist video against its OWN channel: views ÷ the median views of that channel's latest videos (same format). 10 = ten times what the channel usually gets — a small channel breaking out. Adds <code>outlierScore</code>, <code>channelMedianViews</code> and <code>channelSubscribers</code>; 1 free request per channel (up to 100 per run), no extra charge. On automatically with Sort results by → Outlier score.",
            "default": false
          },
          "includeDetails": {
            "title": "Fetch exact details per video",
            "type": "boolean",
            "description": "Adds exact views, likes, comment count, exact publish date, description, hashtags, channel subscribers, like rate. Charged as Video (detailed) instead of Video. Always on for video URLs and with transcripts.",
            "default": false
          },
          "includeHeatmap": {
            "title": "Full Most-replayed heatmap",
            "type": "boolean",
            "description": "With details: add <code>heatmap</code> — YouTube's whole \"Most replayed\" graph (about 100 points, <code>startSec</code>/<code>endSec</code>/<code>intensity</code> 0–1). Detailed rows always carry the top 3 segments in <code>mostReplayed</code>. Same price.",
            "default": false
          },
          "includeTranscript": {
            "title": "Transcripts (coming early December 2026)",
            "type": "boolean",
            "description": "One <code>transcript</code> row per video, right after its video row: the full text, timestamped segments, language and whether YouTube generated it automatically. <b>$0.006 per transcript</b>, charged only when the video has captions — videos without captions get a free row with <code>status: \"no-captions\"</code>. Turns on details (the video itself is charged as Video (detailed)). Coming early December 2026: until its price is live this option is off and nothing is charged for it.",
            "default": false
          },
          "transcriptLanguages": {
            "title": "Transcript languages",
            "type": "array",
            "description": "Preferred caption languages in order, as codes (<code>en</code>, <code>es</code>, <code>pt-BR</code>, <code>id</code>…). Human captions beat auto-generated ones in the same language. Empty = English; a video without any of them returns its own language.",
            "items": {
              "type": "string"
            }
          },
          "shortsDateLookups": {
            "title": "Free date lookups",
            "minimum": 0,
            "maximum": 2000,
            "type": "integer",
            "description": "YouTube's Shorts shelf has no publish date, and other cards only say \"1 month ago\". The Actor reads the exact date from the video page for up to this many videos per run at no extra charge: Shorts dates (publishedAt / viewsPerHour), and videos close to your <code>oldestPostDate</code>. Still billed as plain Video. 0 = off.",
            "default": 400
          },
          "maxCommentsPerVideo": {
            "title": "Max comments per video",
            "minimum": 0,
            "maximum": 500,
            "type": "integer",
            "description": "0 = no comments. Requires details. 20 per page; order set by <code>commentsSort</code>.",
            "default": 0
          },
          "commentsSort": {
            "title": "Comments order",
            "enum": [
              "top",
              "newest"
            ],
            "type": "string",
            "description": "Top = YouTube's featured comments. Newest = most recent first (for daily brand/product monitoring).",
            "default": "top"
          },
          "includeChannelSummary": {
            "title": "Free channel-summary row",
            "type": "boolean",
            "description": "Per channel: subscribers, median/avg views (also per format), top outliers, upload frequency, days since last upload, and the About panel (joined date / channel age, total views, country, links, whether a business email is listed). Never charged.",
            "default": true
          },
          "onlyNew": {
            "title": "Only new since last run (monitor mode)",
            "type": "boolean",
            "description": "Skip videos already delivered by a previous run of this Actor in your account (remembered by <code>videoId</code> in the key-value store <code>youtube-channel-shorts-scraper-seen</code>). First run returns everything and seeds the memory; schedule the Actor (hourly/daily) and every later run returns only what is new — skipped rows are free.",
            "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}