{
  "openapi": "3.0.1",
  "info": {
    "title": "YouTube Channel Finder: Score, Filter, Monitor",
    "description": "Search YouTube by keyword or results URL and save one row per public channel: profile, metrics, links, description e-mails, posting activity and a 0-100 opportunity score. Filter by subscribers, country, views and recency. Includes an HTML report and a compare-with-previous-run monitor mode.",
    "version": "0.2",
    "x-build-id": "ZJob5lvuzozH8q79i"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/solalab_digital~youtube-channel-search/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-solalab_digital-youtube-channel-search",
        "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/solalab_digital~youtube-channel-search/runs": {
      "post": {
        "operationId": "runs-sync-solalab_digital-youtube-channel-search",
        "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/solalab_digital~youtube-channel-search/run-sync": {
      "post": {
        "operationId": "run-sync-solalab_digital-youtube-channel-search",
        "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": [
          "discoveryMode"
        ],
        "properties": {
          "searchTerms": {
            "title": "Search terms",
            "maxItems": 500,
            "type": "array",
            "description": "Topics, products or kinds of creators to look for, one per line. Terms typed here and terms from uploaded files can total up to 500.",
            "items": {
              "type": "string",
              "minLength": 1
            },
            "default": [
              "coffee roasting"
            ]
          },
          "searchTermsFiles": {
            "title": "Upload search term files",
            "maxItems": 20,
            "type": "array",
            "description": "Up to 20 TXT or CSV files with one search term per line. For CSV only the first column is read. Terms are de-duplicated against the list above, and the combined total is capped at 500.",
            "items": {
              "type": "string",
              "minLength": 1
            }
          },
          "searchUrls": {
            "title": "YouTube search URLs",
            "type": "array",
            "description": "Public youtube.com/results URLs for searches you want to repeat. The surface is read from the URL's own sp filter when it is one this Actor recognises, otherwise the URL is treated as video results.",
            "items": {
              "type": "object",
              "properties": {
                "url": {
                  "type": "string",
                  "title": "URL",
                  "description": "A public YouTube search-result URL.",
                  "pattern": "^https?://(?:www\\.|m\\.)?youtube\\.com/results(?:\\?|$)",
                  "minLength": 1
                }
              },
              "required": [
                "url"
              ],
              "additionalProperties": false
            }
          },
          "discoveryMode": {
            "title": "Where to look",
            "enum": [
              "both",
              "videoResults",
              "channelFilter"
            ],
            "type": "string",
            "description": "Which YouTube search surface to read. 'Channel-only search' uses YouTube's channel filter and returns channels directly. 'Video results' reads the normal search page and takes the channel that owns each video, which surfaces smaller creators the channel filter hides. 'Both' runs the two passes over every source.",
            "default": "both"
          },
          "maxChannelsPerSearchTerm": {
            "title": "Max channels per source",
            "minimum": 1,
            "type": "integer",
            "description": "Stop a source after this many channels have been saved from it. Channels dropped by filters or already seen do not count. Leave empty to read each source until YouTube runs out of results."
          },
          "maxTotalResults": {
            "title": "Max channels in total",
            "minimum": 1,
            "type": "integer",
            "description": "Stop the whole run after this many channels have been saved. Channels dropped by filters do not count. Leave empty to read every source to the end."
          },
          "minSubscribers": {
            "title": "Minimum subscribers",
            "minimum": 0,
            "maximum": 1000000000,
            "type": "integer",
            "description": "Keep only channels at or above this public subscriber count. Channels that hide their count are dropped unless 'Keep channels with a hidden subscriber count' is on."
          },
          "maxSubscribers": {
            "title": "Maximum subscribers",
            "minimum": 0,
            "maximum": 1000000000,
            "type": "integer",
            "description": "Keep only channels at or below this public subscriber count. Works together with the minimum."
          },
          "minVideos": {
            "title": "Minimum videos",
            "minimum": 0,
            "maximum": 10000000,
            "type": "integer",
            "description": "Keep only channels with at least this many public videos. The count comes from the channel's About panel, so a channel whose count YouTube does not publish is dropped."
          },
          "verifiedOnly": {
            "title": "Verified channels only",
            "type": "boolean",
            "description": "Keep only channels YouTube marks with the verification badge in search results.",
            "default": false
          },
          "excludedChannels": {
            "title": "Excluded channels",
            "type": "array",
            "description": "Channel URLs to leave out, as https://www.youtube.com/@Handle or https://www.youtube.com/channel/UC.... Matching is on the channel ID and the handle, not on the URL text.",
            "items": {
              "type": "object",
              "properties": {
                "url": {
                  "type": "string",
                  "title": "Channel URL",
                  "description": "A YouTube handle URL or /channel/UC... URL.",
                  "pattern": "^https?://(?:www\\.|m\\.)?youtube\\.com/(?:@[A-Za-z0-9._-]+|channel/UC[A-Za-z0-9_-]+)(?:[/?#].*)?$",
                  "minLength": 1
                }
              },
              "required": [
                "url"
              ],
              "additionalProperties": false
            }
          },
          "channelCountry": {
            "title": "Channel country",
            "pattern": "^[A-Za-z]{2}$",
            "minLength": 2,
            "maxLength": 2,
            "type": "string",
            "description": "Two-letter country code, such as GB. Kept only when the channel publishes that country on its About panel; channels with no published country are dropped."
          },
          "minTotalViews": {
            "title": "Minimum total views",
            "minimum": 0,
            "type": "integer",
            "description": "Keep only channels with at least this many lifetime views. The figure comes from the About panel, so channels that hide it are dropped."
          },
          "activeWithinDays": {
            "title": "Posted within the last N days",
            "minimum": 1,
            "maximum": 3650,
            "type": "integer",
            "description": "Keep only channels whose newest video is no older than this. YouTube publishes ages as text ('3 weeks ago'), so the date is approximate. Setting this turns on 'Include posting activity' automatically."
          },
          "keepHiddenSubscribers": {
            "title": "Keep channels with a hidden subscriber count",
            "type": "boolean",
            "description": "By default a subscriber filter drops channels whose count YouTube does not publish. Turn this on to keep them; their size score is then 0.",
            "default": false
          },
          "sortBy": {
            "title": "Sort results by",
            "enum": [
              "relevance",
              "subscribers",
              "score",
              "videos",
              "lastVideo",
              "views"
            ],
            "type": "string",
            "description": "Anything other than 'Discovery order' holds the rows until the run ends so they can be sorted, so results appear in the dataset only at the end.",
            "default": "relevance"
          },
          "includeActivity": {
            "title": "Include posting activity",
            "type": "boolean",
            "description": "Read the channel's Videos tab to work out how recently and how often it posts and the average views of its newest uploads. Costs one extra request per channel and is required for the activity part of the score.",
            "default": false
          },
          "recentVideosCount": {
            "title": "Recent videos to sample",
            "minimum": 3,
            "maximum": 30,
            "type": "integer",
            "description": "How many of the newest videos to average when 'Include posting activity' is on.",
            "default": 10
          },
          "includeContacts": {
            "title": "Include contacts",
            "type": "boolean",
            "description": "Collect e-mail addresses written in plain text in the channel description. Addresses YouTube hides behind 'Sign in to see email address' are not reachable and are never guessed. External links are always returned, with or without this option.",
            "default": false
          },
          "compareWithPrevious": {
            "title": "Compare with the previous run",
            "type": "boolean",
            "description": "Turn this run into a monitor: each channel is marked new or existing against the last snapshot, subscriber changes are reported, and channels missing from this run are listed in the report.",
            "default": false
          },
          "monitorKey": {
            "title": "Monitor key",
            "pattern": "^[A-Za-z0-9][A-Za-z0-9-]{0,38}$",
            "maxLength": 39,
            "type": "string",
            "description": "Names the snapshot store, as yt-channel-search-monitor-<key>. Leave empty to derive it from the sources and filters, which keeps identical searches on the same history."
          },
          "languageHint": {
            "title": "Page language",
            "pattern": "^[A-Za-z]{2}$",
            "minLength": 2,
            "maxLength": 2,
            "type": "string",
            "description": "Two-letter YouTube language hint. Leave it at en: relative dates like '3 weeks ago' and counts like '2.56M' are parsed in English, and another language makes those fields unreadable.",
            "default": "en"
          },
          "countryHint": {
            "title": "Page country",
            "pattern": "^[A-Za-z]{2}$",
            "minLength": 2,
            "maxLength": 2,
            "type": "string",
            "description": "Two-letter YouTube country hint, such as US. A country inside the EU can make YouTube answer with a cookie-consent page instead of results, so a non-EU hint is safer.",
            "default": "US"
          },
          "maxConcurrency": {
            "title": "Parallel sources",
            "minimum": 1,
            "maximum": 10,
            "type": "integer",
            "description": "How many sources to read at the same time. Pages inside one source are always read in order.",
            "default": 5
          },
          "proxyConfiguration": {
            "title": "Proxy",
            "type": "object",
            "description": "Datacenter proxies are enough for most runs. If YouTube answers with consent pages or 429 errors, switch to residential.",
            "default": {
              "useApifyProxy": true,
              "apifyProxyGroups": []
            }
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}