{
  "openapi": "3.0.1",
  "info": {
    "title": "YouTube Outlier Videos Finder - AI Video Research & Scraper",
    "description": "First 25 videos free. YouTube outlier videos finder + AI video research: each video scored 0-100 against your brief, views vs its channel, grounded takeaways and brand mentions. Pay only for qualified videos. Any Apify plan with your own free YouTube API key.",
    "version": "0.3",
    "x-build-id": "8M5Wft1FNQWiMWdzT"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/rich_minds~youtube-video-research-ai/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-rich_minds-youtube-video-research-ai",
        "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/rich_minds~youtube-video-research-ai/runs": {
      "post": {
        "operationId": "runs-sync-rich_minds-youtube-video-research-ai",
        "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/rich_minds~youtube-video-research-ai/run-sync": {
      "post": {
        "operationId": "run-sync-rich_minds-youtube-video-research-ai",
        "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": [
          "sourceMode"
        ],
        "properties": {
          "sourceMode": {
            "title": "Where do the videos come from?",
            "enum": [
              "actor",
              "youtubeApi",
              "dataset",
              "list"
            ],
            "type": "string",
            "description": "<b>Paste videos (free demo)</b> — the form starts here with sample videos, nothing charged. <b>Search YouTube with YouTube Scraper</b> — runs <code>streamers/youtube-scraper</code> on your account with the terms / URLs below; its usage is billed by that Actor and it <b>needs a paid Apify plan</b> (the free plan cannot run Store Actors). <b>Search YouTube with your free YouTube API key</b> — works on every plan, including the free one: paste a YouTube Data API v3 key below (free, 10,000 quota units a day ≈ 90 searches); no subtitles in this mode. <b>Existing dataset</b> — re-qualify a YouTube Scraper dataset you already have (under <i>Other sources</i>).",
            "default": "actor"
          },
          "researchBrief": {
            "title": "What are you researching?",
            "type": "string",
            "description": "Describe the videos you want in plain words, e.g. <i>beginner Python web scraping tutorials that build a complete project</i>. Every video gets a 0–100 relevance score against this (AI on: the model's judgement with reasons; AI off: keyword overlap). Leave empty to rank by out-performance only."
          },
          "searchQueries": {
            "title": "YouTube search terms",
            "type": "array",
            "description": "What to type into YouTube search, one term per line. Each term returns up to <b>Videos per search term</b> videos from YouTube Scraper on your account ($0.004 each).",
            "items": {
              "type": "string"
            }
          },
          "startUrls": {
            "title": "YouTube URLs (channels, playlists, videos)",
            "type": "array",
            "description": "Competitor channels (<code>https://www.youtube.com/@name</code>), playlists, single videos or search-result URLs to research instead of — or next to — the search terms.",
            "items": {
              "type": "object",
              "required": [
                "url"
              ],
              "properties": {
                "url": {
                  "type": "string",
                  "title": "URL of a web page",
                  "format": "uri"
                }
              }
            }
          },
          "maxResultsPerQuery": {
            "title": "Videos per search term / URL",
            "minimum": 1,
            "maximum": 500,
            "type": "integer",
            "description": "How many videos are loaded per search term or channel/playlist URL (YouTube Scraper or your YouTube API key). More = better coverage, higher source cost (YouTube Scraper: automatically lowered to fit <b>Max source spend</b>; API key: about 100 quota units per 50 videos).",
            "default": 20
          },
          "maxDiscoveryChargeUsd": {
            "title": "Max source spend (USD)",
            "minimum": 0.01,
            "maximum": 1000,
            "type": "number",
            "description": "Hard cap on what the YouTube Scraper run may charge your account in <b>Search YouTube</b> mode — the videos per term are lowered to fit it ($0.004 per video, +$0.0013 with an oldest-post date). The form starts at $0.50; an API or agent call that leaves it out is capped at $2 per run.",
            "default": 2
          },
          "youtubeApiKey": {
            "title": "YouTube Data API key (only for the free-key search)",
            "type": "string",
            "description": "Only for <i>Search YouTube with your free YouTube API key</i>. Create it in Google Cloud → APIs & Services → enable <b>YouTube Data API v3</b> → Credentials → Create API key. Free: 10,000 quota units a day — one search page of 50 videos costs about 100. Stored encrypted, used only for this run's calls to the YouTube API."
          },
          "mustIncludeKeywords": {
            "title": "Must mention (any of)",
            "type": "array",
            "description": "Keep only videos whose title, description or hashtags contain at least one of these words or phrases. Free filter — dropped videos are never charged.",
            "items": {
              "type": "string"
            }
          },
          "excludeKeywords": {
            "title": "Exclude videos mentioning",
            "type": "array",
            "description": "Drop videos whose title, description or hashtags contain any of these words (e.g. <i>music</i>, <i>live stream</i>).",
            "items": {
              "type": "string"
            }
          },
          "watchTerms": {
            "title": "Brands / products to find mentions of",
            "type": "array",
            "description": "Brand, product or competitor names. Every delivered video lists where each one is said (transcript quote with timestamp) or written (description). Turns on free subtitles in the source run.",
            "items": {
              "type": "string"
            }
          },
          "minViews": {
            "title": "Min views",
            "minimum": 0,
            "type": "integer",
            "description": "Drop videos with fewer views.",
            "default": 0
          },
          "maxViews": {
            "title": "Max views",
            "minimum": 0,
            "type": "integer",
            "description": "Drop videos with more views (0 = no limit) — useful to find rising videos before they peak.",
            "default": 0
          },
          "minSubscribers": {
            "title": "Min channel subscribers",
            "minimum": 0,
            "type": "integer",
            "description": "Drop videos from channels smaller than this.",
            "default": 0
          },
          "maxSubscribers": {
            "title": "Max channel subscribers",
            "minimum": 0,
            "type": "integer",
            "description": "Drop videos from channels bigger than this (0 = no limit) — small channels with big videos are the clearest outliers.",
            "default": 0
          },
          "maxAgeDays": {
            "title": "Max age (days)",
            "minimum": 0,
            "type": "integer",
            "description": "Drop videos published longer ago than this (0 = any age). Relative dates like \"10 months ago\" are approximate.",
            "default": 0
          },
          "minDurationSec": {
            "title": "Min duration (seconds)",
            "minimum": 0,
            "type": "integer",
            "description": "Drop videos shorter than this.",
            "default": 0
          },
          "maxDurationSec": {
            "title": "Max duration (seconds)",
            "minimum": 0,
            "type": "integer",
            "description": "Drop videos longer than this (0 = no limit).",
            "default": 0
          },
          "includeShorts": {
            "title": "Include YouTube Shorts",
            "type": "boolean",
            "description": "Off = Shorts (≤ 60 s or a /shorts/ URL) are skipped for free and not requested from the source. On = the source also loads Shorts for each search term.",
            "default": false
          },
          "minOutlierRatio": {
            "title": "Min outlier ratio (views ÷ subscribers)",
            "minimum": 0,
            "maximum": 1000,
            "type": "number",
            "description": "Keep only videos with at least this many views per channel subscriber, e.g. <b>1</b> = the video out-reached the whole channel, <b>3</b> = a strong outlier. 0 = off. Videos without a subscriber count are dropped when this is on.",
            "default": 0
          },
          "channelBaseline": {
            "title": "Compare with the channel's usual views (channel baseline)",
            "type": "boolean",
            "description": "The creators' outlier score: loads the latest videos of the top candidate channels with YouTube Scraper on your account ($0.004 per video, inside <b>Max source spend</b>) and adds <code>outlierVsChannelMedian</code> = views ÷ the channel's median views, plus the <code>channel_outlier</code> flag (≥ 3×). Not run on the free demo.",
            "default": false
          },
          "minChannelOutlier": {
            "title": "Min views ÷ channel median",
            "minimum": 0,
            "maximum": 1000,
            "type": "number",
            "description": "Keep only videos with at least this many times the channel's median views, e.g. <b>3</b> = a clear outlier for that channel. 0 = off. Turns on the channel baseline; videos whose channel was not measured are dropped.",
            "default": 0
          },
          "channelBaselineVideos": {
            "title": "Channel baseline: latest videos per channel",
            "minimum": 5,
            "maximum": 50,
            "type": "integer",
            "description": "How many of each channel's latest videos make its median (lowered to fit <b>Max source spend</b>).",
            "default": 20
          },
          "channelBaselineMaxChannels": {
            "title": "Channel baseline: max channels",
            "minimum": 1,
            "maximum": 50,
            "type": "integer",
            "description": "How many channels to measure — the channels of the most-viewed candidates first. 10 channels × 20 videos ≈ $0.80 on your account.",
            "default": 10
          },
          "minScore": {
            "title": "Minimum score (0–100)",
            "minimum": 0,
            "maximum": 100,
            "type": "integer",
            "description": "Videos scoring below this against your research brief are discarded and <b>not charged</b>.",
            "default": 40
          },
          "targetFlags": {
            "title": "Target flags (any of)",
            "type": "array",
            "description": "Only deliver videos with at least one of these flags, e.g. <code>outlier</code>, <code>fresh</code>, <code>small_channel</code>, <code>watch_term_mentioned</code> (all flags are listed in the README).",
            "items": {
              "type": "string"
            }
          },
          "suppressionList": {
            "title": "Exclude list (videos / channels)",
            "type": "array",
            "description": "Video URLs, video ids, channel names or channel URLs to never output — your own channel, videos you already covered. Skipped before any processing, never charged.",
            "items": {
              "type": "string"
            }
          },
          "enableAi": {
            "title": "AI research assessment",
            "type": "boolean",
            "description": "Scores each video against your brief with reasons, classifies format and hook, writes grounded key takeaways from the transcript, finds watch-term quotes and suggests a content angle. Off = rule-based scores, format and takeaways only (cheaper).",
            "default": true
          },
          "suggestAngles": {
            "title": "Suggest a content angle per video",
            "type": "boolean",
            "description": "The AI adds one video idea that builds on each on-brief video (same model call, no extra cost).",
            "default": true
          },
          "llmProvider": {
            "title": "AI model access",
            "enum": [
              "apify",
              "byok"
            ],
            "type": "string",
            "description": "<b>Apify (no keys)</b> — the AI runs through Apify's built-in model access on plans that can run Store Actors; tokens are billed to your Apify account at OpenRouter rates. <b>My own key</b> — use your OpenAI / Anthropic / Gemini / Groq key instead (any plan).",
            "default": "apify"
          },
          "llmModel": {
            "title": "AI model",
            "type": "string",
            "description": "Leave empty for the default (<code>anthropic/claude-haiku-4.5</code>). Apify mode takes an OpenRouter slug such as <code>openai/gpt-4.1-mini</code>; own-key mode takes <code>provider:model</code>, e.g. <code>anthropic:claude-haiku-4-5-20251001</code>."
          },
          "llmApiKey": {
            "title": "Your API key (own-key mode only)",
            "type": "string",
            "description": "Required when <b>AI model access</b> is <i>My own API key</i>. Stored encrypted by Apify, never logged."
          },
          "aiCandidateMultiplier": {
            "title": "AI candidate pool (× max qualified)",
            "minimum": 1,
            "maximum": 5,
            "type": "integer",
            "description": "How many of the best rule-scored videos get the AI pass, as a multiple of <b>Max qualified videos</b>. Higher = more thorough, slower, more tokens.",
            "default": 2
          },
          "maxQualified": {
            "title": "Max qualified videos to output",
            "minimum": 1,
            "maximum": 10000,
            "type": "integer",
            "description": "Hard cap on results (and therefore on what you pay for). The best-scoring videos are output first.",
            "default": 100
          },
          "maxToProcess": {
            "title": "Max candidates to process",
            "minimum": 1,
            "maximum": 20000,
            "type": "integer",
            "description": "Upper bound on how many videos are scored in one run (controls run time). Default = 3 × max qualified videos."
          },
          "dedupeAcrossRuns": {
            "title": "Never output the same video twice",
            "type": "boolean",
            "description": "Remembers every video you were charged for (in a named key-value store on your account) and skips it in future runs — a weekly schedule delivers only new videos.",
            "default": true
          },
          "dedupeStoreName": {
            "title": "Dedupe store name",
            "type": "string",
            "description": "Key-value store used for cross-run memory. Use different names for different research projects.",
            "default": "youtube-video-research-ai-seen"
          },
          "webhookUrl": {
            "title": "Webhook URL (optional)",
            "type": "string",
            "description": "Qualified videos are POSTed here as JSON (Zapier, Make, n8n, Slack, your CMS). For Google Sheets / Slack you can also use Apify's built-in Integrations tab."
          },
          "webhookHeaders": {
            "title": "Webhook headers (optional)",
            "type": "object",
            "description": "Extra HTTP headers for the webhook, e.g. <code>{\"Authorization\": \"Bearer …\"}</code>."
          },
          "webhookBatchSize": {
            "title": "Webhook batch size",
            "minimum": 1,
            "maximum": 500,
            "type": "integer",
            "description": "1 = one POST per video the moment it is ready. Higher = one POST per N videos.",
            "default": 1
          },
          "sortingOrder": {
            "title": "Search sort order",
            "enum": [
              "relevance",
              "rating",
              "date",
              "views"
            ],
            "type": "string",
            "description": "How YouTube orders the search results the source loads.",
            "default": "relevance"
          },
          "dateFilter": {
            "title": "Upload date (YouTube filter)",
            "enum": [
              "any",
              "hour",
              "today",
              "week",
              "month",
              "year"
            ],
            "type": "string",
            "description": "YouTube's own upload-date search filter (free). For an exact window use <b>Max age (days)</b>.",
            "default": "any"
          },
          "lengthFilter": {
            "title": "Video length (YouTube filter)",
            "enum": [
              "any",
              "under4",
              "between420",
              "plus20"
            ],
            "type": "string",
            "description": "YouTube's own length search filter.",
            "default": "any"
          },
          "videoType": {
            "title": "Video type (YouTube filter)",
            "enum": [
              "any",
              "video",
              "movie"
            ],
            "type": "string",
            "description": "Restrict search results to regular videos or movies.",
            "default": "any"
          },
          "sortVideosBy": {
            "title": "Channel videos order",
            "enum": [
              "NEWEST",
              "POPULAR",
              "OLDEST"
            ],
            "type": "string",
            "description": "For channel URLs: load the newest, the most popular or the oldest videos first.",
            "default": "NEWEST"
          },
          "oldestPostDate": {
            "title": "Oldest post date (channels)",
            "type": "string",
            "description": "For channel URLs: only videos published after this date (<code>YYYY-MM-DD</code> or e.g. <code>30 days</code>). The source charges $0.0013 extra per video when set — <b>Max age (days)</b> does the same for free after loading.",
            "default": ""
          },
          "maxResultStreams": {
            "title": "Live streams per term / URL",
            "minimum": 0,
            "maximum": 500,
            "type": "integer",
            "description": "Also load this many past live streams per search term or channel (0 = none).",
            "default": 0
          },
          "subtitlesLanguage": {
            "title": "Subtitles language",
            "enum": [
              "any",
              "en",
              "de",
              "es",
              "fr",
              "it",
              "ja",
              "ko",
              "nl",
              "pt",
              "ru"
            ],
            "type": "string",
            "description": "Which subtitle track the transcript comes from.",
            "default": "en"
          },
          "transcriptMode": {
            "title": "Transcript source",
            "enum": [
              "auto",
              "NONE",
              "ALWAYS_SUBTITLES",
              "TRANSCRIPTION_AS_FALLBACK",
              "ALWAYS_TRANSCRIBE"
            ],
            "type": "string",
            "description": "<b>Auto</b> — YouTube's existing subtitles (free) whenever the AI or watch terms read them. The two speech-to-text modes are the source's paid transcription ($0.048 per transcribed minute on your account) — pick them only for videos without subtitles.",
            "default": "auto"
          },
          "discoveryActorId": {
            "title": "Source Actor",
            "type": "string",
            "description": "Actor used in <b>Search YouTube</b> mode. Any Actor whose output has YouTube Scraper's fields works.",
            "default": "streamers/youtube-scraper"
          },
          "discoveryInput": {
            "title": "Extra source input (JSON)",
            "type": "object",
            "description": "Merged over the input this Actor builds for YouTube Scraper (e.g. <code>{\"isHD\": true}</code>). The source's paid AI add-ons stay off — this Actor's AI tier replaces them."
          },
          "proxyConfiguration": {
            "title": "Proxy",
            "type": "object",
            "description": "Not needed: YouTube Scraper handles its own proxies. Kept for compatibility."
          },
          "itemsList": {
            "title": "Videos to process",
            "type": "array",
            "description": "Only for <b>Paste videos</b> mode. JSON array of YouTube Scraper rows (<code>title</code>, <code>url</code>, <code>viewCount</code>, <code>numberOfSubscribers</code>, <code>text</code>, <code>subtitles</code> …). The prefilled sample is the free demo."
          },
          "datasetId": {
            "title": "Dataset",
            "type": "string",
            "description": "Only for <b>Existing dataset</b> mode. Pick a YouTube Scraper dataset so the Actor is granted read access to it."
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}