> **Building with AI coding agents?** Install the authstack plugin with one command. This equips your agent with accurate Scalekit implementation patterns.
>
> **Recommended** (the `-y` flags skip prompts, so the command runs without an interactive terminal):
> ```bash
> npx -y @scalekit-inc/cli setup -y
> ```
>
> Global:
> ```bash
> npm install -g @scalekit-inc/cli
> scalekit setup -y
> ```
>
> Supports Claude Code, Cursor, GitHub Copilot, Codex + skills for other Agent Skills-compatible agents in `~/.agents/skills`.
> Skills: integrate-agentkit, implement-saaskit, add-mcp-oauth, implement-sso, implement-scim.
> [Full setup guide](https://docs.scalekit.com/dev-kit/build-with-ai/)

---

# Connect AI agents to YouTube

The YouTube connector lets your AI agent act in each user's YouTube account. Each user signs in to YouTube once, and Scalekit stores and refreshes their tokens, so your agent never handles credentials. It comes with 45 tools.

**Authentication:** OAuth 2.0
**Categories:** Media, Marketing
**Tools:** 45: 19 read, 18 write, 8 destructive
**Users sign in with:** OAuth
**OAuth app:** Your own Google app
**Built by:** Scalekit connector
**Try it:** [Playground in the Scalekit dashboard](https://app.scalekit.com/ws/signup?sk_intent=playground&provider=YOUTUBE)

## What you can do

- **Search and read videos**: search videos, channels, and playlists, and fetch video details and statistics
- **Manage your videos**: update video titles and details, like or dislike videos, and delete videos
- **Manage playlists**: create, update, and delete playlists, and add or remove videos
- **Moderate comments**: read comment threads, post and edit replies, and approve, reject, or delete comments
- **Query analytics**: pull views, watch time, subscribers, and revenue, and schedule daily reporting jobs
- **Run live streams**: create live broadcasts and streams, bind them, and move broadcasts through testing and live

## Setup

1. ### Install the SDK

   **Node.js**

   ```bash
   npm install @scalekit-sdk/node dotenv
   ```

   **Python**

   ```bash
   pip install scalekit-sdk-python python-dotenv
   ```

2. ### Set your credentials

   Add your Scalekit credentials to your `.env` file. Find values in **[app.scalekit.com](https://app.scalekit.com)** > **Developers** > **API Credentials**.

   ```sh title=".env"
   SCALEKIT_ENVIRONMENT_URL=<your-environment-url>
   SCALEKIT_CLIENT_ID=<your-client-id>
   SCALEKIT_CLIENT_SECRET=<your-client-secret>
   ```

3. ### Create the YouTube connection

   In **AgentKit > Connections**, create a YouTube connection and copy its redirect URI. The name you give it is the `connection_name` your code passes. See [Configure connections](/agentkit/connections/).

4. ### Register a Google OAuth app

   YouTube connections use your own OAuth app. Register one with Google and add the redirect URI you copied.

   Then enter the app's Client ID and Client Secret on the YouTube connection.

   **Console steps with screenshots:**

   Register your Google OAuth 2.0 credentials with Scalekit so it can manage the OAuth 2.0 authentication flow and token lifecycle for YouTube on your behalf. You'll need a Client ID and Client Secret from the [Google Cloud Console](https://console.cloud.google.com/).

   1. ### Create an OAuth 2.0 client in Google Cloud

      - Go to the [Google Cloud Console](https://console.cloud.google.com/) and select your project (or create a new one).

        <img src={googleCloudConsoleImg.src} alt="Google Cloud Console welcome page" width="540" />

      - Search for **OAuth** in the top search bar. Select **Credentials** under **APIs & Services**.

        <img src={searchOauthImg.src} alt="Searching for OAuth in Google Cloud Console" width="540" />

      - On the **Credentials** page, click **+ Create credentials** and select **OAuth client ID**.

        <img src={credentialsPageImg.src} alt="Google Cloud Credentials page showing OAuth 2.0 Client IDs" width="540" />

        <img src={createCredentialsDropdownImg.src} alt="Create credentials dropdown with OAuth client ID option" width="540" />

      - Set the **Application type** to **Web application** and enter a **Name** (e.g., `Scalekit`).

        <img src={createOauthClientIdImg.src} alt="Create OAuth client ID form with Web application type and Scalekit name" width="540" />

      - Leave the **Authorized redirect URIs** section empty for now — you'll add the Scalekit redirect URI in a later step.

   2. ### Create a connection in Scalekit

      - In [Scalekit dashboard](https://app.scalekit.com), go to **AgentKit** > **Connections** > **Create Connection**.

        <img src={scalekitAgentAuthImg.src} alt="Scalekit Agent Auth connections page" width="540" />

      - Search for **YouTube** and click **Create**.

        <img src={scalekitSearchYoutubeImg.src} alt="Searching for YouTube in Scalekit Create Connection" width="540" />

      - Copy the **Redirect URI** from the connection configuration panel. It looks like `https://<SCALEKIT_ENVIRONMENT_URL>/sso/v1/oauth/<CONNECTION_ID>/callback`.

        <img src={configureYoutubeConnectionImg.src} alt="Configure YouTube Connection panel showing Redirect URI, Client ID, Client Secret, and Scopes fields" width="540" />

   3. ### Configure the redirect URI in Google Cloud

      - Back in the [Google Cloud Console](https://console.cloud.google.com/), open your OAuth 2.0 client (or continue from step 1).

      - Under **Authorized redirect URIs**, click **+ Add URI** and paste the Scalekit Redirect URI.

        <img src={googleRedirectUriImg.src} alt="Google Cloud OAuth client with Scalekit redirect URI added" width="540" />

      - Click **Create** (or **Save** if editing an existing client). A dialog displays your **Client ID** and **Client secret**. Copy both values.

        <img src={oauthClientCreatedImg.src} alt="OAuth client created dialog showing Client ID and Client secret" width="540" />

   4. ### Add credentials in Scalekit

      - In [Scalekit dashboard](https://app.scalekit.com), go to **AgentKit** > **Connections** and open the YouTube connection you created.

      - Enter your credentials:
        - **Client ID** — the Client ID from your Google OAuth 2.0 client
        - **Client Secret** — the Client secret from the dialog in step 3
        - **Scopes** — select the scopes your app needs (e.g., `youtube.readonly`, `youtube`, `youtube.force-ssl`, `yt-analytics.readonly`)

        <img src={scalekitCredentialsFilledImg.src} alt="Configure YouTube Connection panel filled with Client ID and Client Secret" width="540" />

      - Click **Save**.

5. ### Authorize a user and make your first call

   **Node.js** (`quickstart.mts`)

   ```typescript
   import { ScalekitClient } from '@scalekit-sdk/node'
   import 'dotenv/config'
   import { createInterface } from 'node:readline/promises'

   const scalekit = new ScalekitClient(
     process.env.SCALEKIT_ENVIRONMENT_URL,
     process.env.SCALEKIT_CLIENT_ID,
     process.env.SCALEKIT_CLIENT_SECRET,
   )
   const actions = scalekit.actions

   const connector = 'youtube'
   const identifier = 'user_123'

   // Generate an authorization link for the user
   const { link } = await actions.getAuthorizationLink({ connectionName: connector, identifier })
   console.log('Authorize YouTube:', link)
   const rl = createInterface({ input: process.stdin, output: process.stdout })
   await rl.question('Press Enter after authorizing...')
   rl.close()

   // Make your first call
   const result = await actions.executeTool({
     connector,
     identifier,
     toolName: 'youtube_analytics_groups_list',
     toolInput: {},
   })
   console.log(result)
   ```

   ```bash
   npx tsx quickstart.mts
   ```

   **Python** (`quickstart.py`)

   ```python
   import os
   from scalekit import ScalekitClient
   from dotenv import load_dotenv
   load_dotenv()

   scalekit_client = ScalekitClient(
       env_url=os.getenv("SCALEKIT_ENVIRONMENT_URL"),
       client_id=os.getenv("SCALEKIT_CLIENT_ID"),
       client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"),
   )
   actions = scalekit_client.actions

   connection_name = "youtube"
   identifier = "user_123"

   # Generate an authorization link for the user
   link_response = actions.get_authorization_link(
       connection_name=connection_name,
       identifier=identifier,
   )
   print("Authorize YouTube:", link_response.link)
   input("Press Enter after authorizing...")

   # Make your first call
   result = actions.execute_tool(
       tool_input={},
       tool_name="youtube_analytics_groups_list",
       connection_name=connection_name,
       identifier=identifier,
   )
   print(result)
   ```

   ```bash
   python quickstart.py
   ```

   Each user signs in once. See [Authorize a user](/agentkit/tools/authorize/) for the full flow and statuses.

## Tools

Pass the exact name to `execute_tool`, with an input like each tool's example. To ask for a tool that's missing, use the [request form](https://scalekitsupport.portal.usepylon.com/forms/request-a-connector-tool).

**Node.js**

```typescript
const result = await actions.executeTool({
  toolName: 'youtube_analytics_group_items_list',
  toolInput: {
    group_id: '<group_id>',
  },
  connector: 'youtube',
  identifier: 'user_123',
})
```

**Python**

```python
result = actions.execute_tool(
    tool_name="youtube_analytics_group_items_list",
    tool_input={
        "group_id": "<group_id>",
    },
    connection_name="youtube",
    identifier="user_123",
)
```

`result.data` is the app's response as JSON, and `result.execution_id` (`executionId` in Node.js) is the ID of the call.

### `youtube_analytics_group_items_list`

List Analytics Group Items · Read-only

Retrieve a list of items (videos, playlists, channels, or assets) that belong to a YouTube Analytics group.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `group_id` (`string`, required): ID of the group whose items to retrieve
- `on_behalf_of_content_owner` (`string`, optional): Content owner ID on whose behalf the request is being made

Example input: `{"group_id":"<group_id>"}`

### `youtube_analytics_groups_list`

List Analytics Groups · Read-only

Retrieve a list of YouTube Analytics groups for a channel or content owner. Specify either id or mine to filter results.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `id` (`string`, optional): Comma-separated list of group IDs to retrieve
- `mine` (`boolean`, optional): If true, return only groups owned by the authenticated user. Required if id is not set.
- `on_behalf_of_content_owner` (`string`, optional): Content owner ID on whose behalf the request is being made
- `page_token` (`string`, optional): Token for retrieving the next page of results

Example input: `{}`

### `youtube_analytics_query`

Query YouTube Analytics · Read-only

Query YouTube Analytics data to retrieve metrics like views, watch time, subscribers, revenue, etc. for channels or content owners.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `end_date` (`string`, required): End date for the analytics report in YYYY-MM-DD format
- `ids` (`string`, required): Channel or content owner ID. Format: channel==CHANNEL_ID or contentOwner==CONTENT_OWNER_ID
- `metrics` (`string`, required): Comma-separated list of metrics to retrieve (e.g., views,estimatedMinutesWatched,likes,subscribersGained)
- `start_date` (`string`, required): Start date for the analytics report in YYYY-MM-DD format
- `currency` (`string`, optional): Currency for monetary metrics (ISO 4217 code, e.g., USD)
- `dimensions` (`string`, optional): Comma-separated list of dimensions to group results by (e.g., day,country,video)
- `filters` (`string`, optional): Filter expression to narrow results (e.g., country==US, video==VIDEO_ID)
- `include_historical_channel_data` (`boolean`, optional): Include historical channel data recorded before the channel was linked to a content owner
- `max_results` (`integer`, optional): Maximum number of rows to return in the response (maximum value: 200)
- `sort` (`string`, optional): Comma-separated list of columns to sort by. Prefix with - for descending order (e.g., -views)
- `start_index` (`integer`, optional): 1-based index of the first row to return (for pagination)

Example input: `{"end_date":"<end_date>","ids":"<ids>","metrics":"<metrics>","start_date":"<start_date>"}`

### `youtube_captions_list`

List Captions · Read-only

Retrieve a list of caption tracks for a YouTube video. The part parameter is fixed to 'snippet'. Requires youtube.force-ssl scope.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `video_id` (`string`, required): ID of the video to list captions for
- `id` (`string`, optional): Comma-separated list of caption track IDs to filter results

Example input: `{"video_id":"<video_id>"}`

### `youtube_channels_list`

Get Channel Details · Read-only

Retrieve information about one or more YouTube channels including subscriber count, video count, and channel metadata. You must provide exactly one filter: id, mine, for_handle, for_username, or managed_by_me. Requires a valid YouTube OAuth2 connection.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `part` (`string`, required): Comma-separated list of channel resource parts to include in the response
- `for_handle` (`string`, optional): YouTube channel handle to look up (e.g., @MrBeast). Use instead of id, mine, or for_username.
- `for_username` (`string`, optional): YouTube username of the channel to look up (legacy). Use instead of id, mine, or for_handle.
- `id` (`string`, optional): Comma-separated list of YouTube channel IDs. Use instead of mine, for_handle, or for_username.
- `managed_by_me` (`boolean`, optional): Return channels managed by the authenticated user (content partners only). Use instead of id, mine, for_handle, or for_username.
- `max_results` (`integer`, optional): Maximum number of results to return (0-50, default: 5)
- `mine` (`boolean`, optional): Return the authenticated user's channel. Use instead of id, for_handle, or for_username.
- `page_token` (`string`, optional): Token for pagination

Example input: `{"part":"<part>"}`

### `youtube_comment_threads_list`

List Comment Threads · Read-only

Retrieve top-level comment threads for a YouTube video or channel. You must provide exactly one filter: video_id, all_threads_related_to_channel_id, or id. Each thread includes the top-level comment and optionally its replies. Requires a valid YouTube OAuth2 connection.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `part` (`string`, required): Comma-separated list of comment thread resource parts to include
- `all_threads_related_to_channel_id` (`string`, optional): Return all comment threads associated with a specific channel. Use instead of video_id or id.
- `id` (`string`, optional): Comma-separated list of comment thread IDs to retrieve. Use instead of video_id or all_threads_related_to_channel_id.
- `max_results` (`integer`, optional): Maximum number of comment threads to return (1-100, default: 20). Default: `20`.
- `order` (`string`, optional): Sort order for comment threads. One of: `relevance`, `time`. Default: `time`.
- `page_token` (`string`, optional): Token for pagination
- `search_terms` (`string`, optional): Limit results to comments containing these search terms
- `video_id` (`string`, optional): YouTube video ID to fetch comment threads for. Use instead of all_threads_related_to_channel_id or id.

Example input: `{"part":"<part>"}`

### `youtube_comments_list`

List Comment Replies · Read-only

Retrieve a list of replies to a specific YouTube comment thread. You must provide exactly one filter: parent_id or id. The part parameter is fixed to 'snippet'. Requires youtube.readonly scope.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `id` (`string`, optional): Comma-separated list of comment IDs to retrieve. Use instead of parent_id.
- `max_results` (`integer`, optional): Maximum number of replies to return (1-100, default: 20). Cannot be used with id filter. Default: `20`.
- `page_token` (`string`, optional): Token for pagination to retrieve the next page of replies. Cannot be used with id filter.
- `parent_id` (`string`, optional): ID of the comment thread (top-level comment) to list replies for. Use instead of id.
- `text_format` (`string`, optional): Format of the comment text in the response. One of: `html`, `plainText`. Default: `html`.

Example input: `{}`

### `youtube_live_broadcasts_list`

List Live Broadcasts · Read-only

List live broadcasts owned by the authenticated user's YouTube channel. Filter by broadcast status (active, upcoming, completed) or by specific broadcast IDs. Requires youtube or youtube.readonly scope.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `part` (`string`, required): Comma-separated list of liveBroadcast resource parts to include in the response. Valid values: id, snippet, contentDetails, status.
- `broadcast_status` (`string`, optional): Filter broadcasts by their current status. One of: `active`, `all`, `completed`, `upcoming`.
- `id` (`string`, optional): Comma-separated list of specific YouTube live broadcast IDs to retrieve. Use instead of broadcast_status.
- `max_results` (`integer`, optional): Maximum number of results to return (1-50, default 5).
- `page_token` (`string`, optional): Token for pagination.

Example input: `{"part":"<part>"}`

### `youtube_live_streams_list`

List Live Streams · Read-only

List video streams owned by the authenticated user's YouTube channel. A stream carries the actual ingested video/audio and is bound to one or more live broadcasts. Requires youtube or youtube.readonly scope.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `part` (`string`, required): Comma-separated list of liveStream resource parts to include in the response. Valid values: id, snippet, cdn, contentDetails, status.
- `id` (`string`, optional): Comma-separated list of specific YouTube live stream IDs to retrieve. Use instead of mine.
- `max_results` (`integer`, optional): Maximum number of results to return (1-50, default 5).
- `mine` (`boolean`, optional): Restrict results to streams owned by the authenticated user. Use instead of id.
- `page_token` (`string`, optional): Token for pagination.

Example input: `{"part":"<part>"}`

### `youtube_playlist_items_list`

List Playlist Items · Read-only

Retrieve a list of videos in a YouTube playlist. Returns playlist items with video details, positions, and metadata. Requires a valid YouTube OAuth2 connection.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `part` (`string`, required): Comma-separated list of playlist item resource parts to include
- `playlist_id` (`string`, required): YouTube playlist ID to retrieve items from
- `max_results` (`integer`, optional): Maximum number of playlist items to return (0-50, default: 5). Default: `5`.
- `page_token` (`string`, optional): Token for pagination to retrieve the next page
- `video_id` (`string`, optional): Filter results to items containing a specific video

Example input: `{"part":"<part>","playlist_id":"<playlist_id>"}`

### `youtube_playlists_list`

List Playlists · Read-only

Retrieve a list of YouTube playlists for a channel or the authenticated user. You must provide exactly one filter: channel_id, id, or mine. Requires a valid YouTube OAuth2 connection.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `part` (`string`, required): Comma-separated list of playlist resource parts to include
- `channel_id` (`string`, optional): Return playlists for a specific channel. Use instead of id or mine.
- `id` (`string`, optional): Comma-separated list of playlist IDs to retrieve. Use instead of channel_id or mine.
- `max_results` (`integer`, optional): Maximum number of playlists to return (0-50, default: 5). Default: `5`.
- `mine` (`boolean`, optional): Return playlists owned by the authenticated user. Use instead of channel_id or id.
- `page_token` (`string`, optional): Token for pagination

Example input: `{"part":"<part>"}`

### `youtube_reporting_list_jobs`

List Reporting Jobs · Read-only

List all YouTube Reporting API jobs scheduled for a channel or content owner.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `include_system_managed` (`boolean`, optional): If true, include system-managed reporting jobs in the response
- `on_behalf_of_content_owner` (`string`, optional): Content owner ID on whose behalf the request is being made
- `page_size` (`integer`, optional): Maximum number of jobs to return per page
- `page_token` (`string`, optional): Token for retrieving the next page of results

Example input: `{}`

### `youtube_reporting_list_report_types`

List Report Types · Read-only

List all YouTube Reporting API report types available for a channel or content owner (e.g., channel_basic_a2, channel_demographics_a1).

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `include_system_managed` (`boolean`, optional): If true, include system-managed report types in the response
- `on_behalf_of_content_owner` (`string`, optional): Content owner ID on whose behalf the request is being made
- `page_size` (`integer`, optional): Maximum number of report types to return per page
- `page_token` (`string`, optional): Token for retrieving the next page of results

Example input: `{}`

### `youtube_reporting_list_reports`

List Reports for Job · Read-only

List reports that have been generated for a YouTube reporting job. Each report is a downloadable CSV file.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `job_id` (`string`, required): ID of the reporting job whose reports to list
- `created_after` (`string`, optional): Only return reports created after this timestamp (RFC3339 format, e.g., 2024-01-01T00:00:00Z)
- `on_behalf_of_content_owner` (`string`, optional): Content owner ID on whose behalf the request is being made
- `page_size` (`integer`, optional): Maximum number of reports to return per page
- `page_token` (`string`, optional): Token for retrieving the next page of results
- `start_time_at_or_after` (`string`, optional): Only return reports whose data start time is at or after this timestamp (RFC3339 format)
- `start_time_before` (`string`, optional): Only return reports whose data start time is before this timestamp (RFC3339 format)

Example input: `{"job_id":"<job_id>"}`

### `youtube_search`

Search YouTube · Read-only

Search for videos, channels, and playlists on YouTube. Returns a list of resources matching the search query. The part parameter is fixed to 'snippet'. Requires a valid YouTube OAuth2 connection.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `channel_id` (`string`, optional): Restrict search results to a specific channel
- `max_results` (`integer`, optional): Maximum number of results to return (0-50, default: 10). Default: `10`.
- `order` (`string`, optional): Sort order for search results. One of: `date`, `rating`, `relevance`, `title`, `videoCount`, `viewCount`. Default: `relevance`.
- `page_token` (`string`, optional): Token for pagination to retrieve the next page of results
- `published_after` (`string`, optional): Filter results to resources published after this date (RFC 3339 format)
- `published_before` (`string`, optional): Filter results to resources published before this date (RFC 3339 format)
- `q` (`string`, optional): Search query keywords
- `safe_search` (`string`, optional): Safe search filter level. One of: `moderate`, `none`, `strict`. Default: `moderate`.
- `type` (`string`, optional): Restrict results to a specific resource type. One of: `video`, `channel`, `playlist`. Default: `video`.
- `video_duration` (`string`, optional): Filter videos by duration (only applies when type is 'video'). One of: `any`, `long`, `medium`, `short`.

Example input: `{}`

### `youtube_subscriptions_list`

List Subscriptions · Read-only

Retrieve a list of YouTube channel subscriptions for the authenticated user or a specific channel. You must provide exactly one filter: channel_id, id, mine, my_recent_subscribers, or my_subscribers. Requires a valid YouTube OAuth2 connection with youtube.readonly scope.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `part` (`string`, required): Comma-separated list of subscription resource parts to include
- `channel_id` (`string`, optional): Return subscriptions for a specific channel. Use instead of id, mine, my_recent_subscribers, or my_subscribers.
- `for_channel_id` (`string`, optional): Filter subscriptions to specific channels (comma-separated channel IDs)
- `id` (`string`, optional): Comma-separated list of subscription IDs to retrieve. Use instead of channel_id, mine, my_recent_subscribers, or my_subscribers.
- `max_results` (`integer`, optional): Maximum number of subscriptions to return (0-50, default: 5)
- `mine` (`boolean`, optional): Return subscriptions for the authenticated user. Use instead of channel_id, id, my_recent_subscribers, or my_subscribers.
- `my_recent_subscribers` (`boolean`, optional): Return the authenticated user's recent subscribers. Use instead of channel_id, id, mine, or my_subscribers.
- `my_subscribers` (`boolean`, optional): Return the authenticated user's subscribers. Use instead of channel_id, id, mine, or my_recent_subscribers.
- `order` (`string`, optional): Sort order for subscriptions. One of: `alphabetical`, `relevance`, `unread`.
- `page_token` (`string`, optional): Token for pagination

Example input: `{"part":"<part>"}`

### `youtube_video_categories_list`

List Video Categories · Read-only

Retrieve a list of YouTube video categories available in a given region or by ID. You must provide exactly one filter: id or region_code. The part parameter is fixed to 'snippet'. Useful for setting the category when updating a video. Requires youtube.readonly scope.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `hl` (`string`, optional): Language for the category names in the response (BCP-47). Default: `en_US`.
- `id` (`string`, optional): Comma-separated list of category IDs to retrieve. Use instead of region_code.
- `region_code` (`string`, optional): ISO 3166-1 alpha-2 country code to retrieve categories available in that region. Use instead of id.

Example input: `{}`

### `youtube_videos_get_rating`

Get Video Ratings · Read-only

Retrieve the authenticated user's rating (like, dislike, or none) for one or more YouTube videos. The part parameter is fixed to 'id'. Requires youtube.readonly scope.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `id` (`string`, required): Comma-separated list of YouTube video IDs to get ratings for

Example input: `{"id":"<id>"}`

### `youtube_videos_list`

Get Video Details · Read-only

Retrieve detailed information about one or more YouTube videos including statistics, snippet, content details, and status. You must provide exactly one filter: id, chart, or my_rating. Requires a valid YouTube OAuth2 connection.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `part` (`string`, required): Comma-separated list of video resource parts to include in the response
- `chart` (`string`, optional): Retrieve a chart of the most popular videos. Use instead of id or my_rating. One of: `mostPopular`.
- `id` (`string`, optional): Comma-separated list of YouTube video IDs. Use instead of chart or my_rating.
- `max_results` (`integer`, optional): Maximum number of results to return when using chart filter (1-50, default: 5). Default: `5`.
- `my_rating` (`string`, optional): Filter videos by the authenticated user's rating. Use instead of id or chart. One of: `dislike`, `like`.
- `page_token` (`string`, optional): Token for pagination
- `region_code` (`string`, optional): ISO 3166-1 alpha-2 country code to filter trending videos by region
- `video_category_id` (`string`, optional): Filter most popular videos by category ID

Example input: `{"part":"<part>"}`

### `youtube_analytics_group_create`

Create Analytics Group · Write

Create a YouTube Analytics group to organize videos, playlists, channels, or assets for collective analytics reporting.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `item_type` (`string`, required): Type of items the group will contain. One of: `youtube#video`, `youtube#playlist`, `youtube#channel`, `youtube#userActivity`.
- `title` (`string`, required): Title of the analytics group
- `on_behalf_of_content_owner` (`string`, optional): Content owner ID. For content partners only.

Example input: `{"item_type":"youtube#video","title":"<title>"}`

### `youtube_analytics_group_item_insert`

Add Item to Analytics Group · Write

Add a video, playlist, or channel to a YouTube Analytics group.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `group_id` (`string`, required): ID of the Analytics group to add the item to
- `resource_id` (`string`, required): ID of the resource (video ID, channel ID, or playlist ID)
- `resource_kind` (`string`, required): Type of the resource. One of: `youtube#video`, `youtube#channel`, `youtube#playlist`.
- `on_behalf_of_content_owner` (`string`, optional): Content owner ID. For content partners only.

Example input: `{"group_id":"<group_id>","resource_id":"<resource_id>","resource_kind":"youtube#video"}`

### `youtube_analytics_groups_update`

Update Analytics Group · Write

Update the title of an existing YouTube Analytics group.

Read only: no. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `group_id` (`string`, required): ID of the Analytics group to update
- `title` (`string`, required): New title for the Analytics group
- `on_behalf_of_content_owner` (`string`, optional): Content owner ID. For content partners only.

Example input: `{"group_id":"<group_id>","title":"<title>"}`

### `youtube_comment_threads_insert`

Post Comment · Write

Post a new top-level comment on a YouTube video. Requires youtube.force-ssl scope.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `text` (`string`, required): Text of the comment
- `video_id` (`string`, required): ID of the video to comment on

Example input: `{"text":"<text>","video_id":"<video_id>"}`

### `youtube_comments_insert`

Reply to Comment · Write

Post a reply to an existing top-level YouTube comment thread. Requires youtube.force-ssl scope.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `parent_id` (`string`, required): ID of the top-level comment to reply to
- `text` (`string`, required): Text of the reply

Example input: `{"parent_id":"<parent_id>","text":"<text>"}`

### `youtube_comments_set_moderation_status`

Set Comment Moderation Status · Write

Set the moderation status of a comment on a video or channel you own or moderate — approve it, reject it, or hold it for review. Requires youtube.force-ssl scope.

Read only: no. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `comment_id` (`string`, required): Comma-separated list of comment IDs to moderate
- `moderation_status` (`string`, required): The new moderation status to apply. One of: `published`, `heldForReview`, `rejected`.
- `ban_author` (`boolean`, optional): Whether to additionally ban the comment's author from the channel. Only valid when moderation_status is rejected.

Example input: `{"comment_id":"<comment_id>","moderation_status":"published"}`

### `youtube_comments_update`

Edit Comment · Write

Edit the text of an existing YouTube comment or reply that you have permission to modify. Requires youtube.force-ssl scope.

Read only: no. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `comment_id` (`string`, required): ID of the comment to update
- `text` (`string`, required): New text for the comment

Example input: `{"comment_id":"<comment_id>","text":"<text>"}`

### `youtube_live_broadcasts_bind`

Bind Live Broadcast to Stream · Write

Bind a YouTube live broadcast to a video stream so the broadcast will show that stream's video once it goes live, or remove an existing binding by omitting stream_id. A broadcast can be bound to only one stream at a time, though a stream can be bound to multiple broadcasts. Requires youtube scope.

Read only: no. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `id` (`string`, required): The unique ID of the broadcast to bind.
- `part` (`string`, optional): Comma-separated list of liveBroadcast resource parts to include in the response.
- `stream_id` (`string`, optional): The unique ID of the stream to bind the broadcast to. Omit to remove any existing binding.

Example input: `{"id":"<id>"}`

### `youtube_live_broadcasts_insert`

Create Live Broadcast · Write

Create a new YouTube live broadcast (an event with metadata, a schedule, and a monitor stream) on the authenticated user's channel. After creating both a broadcast and a stream (see live_streams_insert), bind them together with live_broadcasts_bind before going live. Requires youtube scope.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `privacy_status` (`string`, required): Privacy setting for the broadcast. One of: `public`, `private`, `unlisted`.
- `scheduled_start_time` (`string`, required): The scheduled start time for the broadcast, in ISO 8601 format.
- `title` (`string`, required): Title of the broadcast (1-100 characters).
- `description` (`string`, optional): Description of the broadcast (up to 5000 characters).
- `enable_auto_start` (`boolean`, optional): Whether the broadcast automatically transitions to live status when YouTube receives stream data.
- `enable_auto_stop` (`boolean`, optional): Whether the broadcast automatically transitions to complete status after a period of inactivity.
- `enable_dvr` (`boolean`, optional): Whether viewers can access DVR controls (pause/rewind) while watching the broadcast.
- `scheduled_end_time` (`string`, optional): The scheduled end time for the broadcast, in ISO 8601 format.

Example input: `{"privacy_status":"public","scheduled_start_time":"<scheduled_start_time>","title":"<title>"}`

### `youtube_live_broadcasts_transition`

Transition Live Broadcast Status · Write

Change the status of a YouTube live broadcast, driving it through its lifecycle. Transitioning to 'testing' starts sending video to the monitor stream, 'live' makes the broadcast visible to the audience, and 'complete' ends the broadcast. Requires youtube scope.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `broadcast_status` (`string`, required): The target status for the broadcast. One of: `testing`, `live`, `complete`.
- `id` (`string`, required): The unique ID of the broadcast to transition.
- `part` (`string`, optional): Comma-separated list of liveBroadcast resource parts to include in the response.

Example input: `{"broadcast_status":"testing","id":"<id>"}`

### `youtube_live_streams_insert`

Create Live Stream · Write

Create a new YouTube live stream, representing the ingestion endpoint that receives encoder video/audio data. Bind the resulting stream to a broadcast with live_broadcasts_bind before going live. Requires youtube or youtube.force-ssl scope.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `frame_rate` (`string`, required): The frame rate of the encoded video stream. One of: `30fps`, `60fps`, `variable`.
- `ingestion_type` (`string`, required): The method used to transmit video to YouTube. One of: `rtmp`, `dash`, `hls`.
- `resolution` (`string`, required): The resolution of the encoded video stream. One of: `240p`, `360p`, `480p`, `720p`, `1080p`, `1440p`, `2160p`, `variable`.
- `title` (`string`, required): Title of the stream (1-128 characters).
- `description` (`string`, optional): Description of the stream (up to 10000 characters).
- `is_reusable` (`boolean`, optional): Whether this stream can be bound to multiple broadcasts, one at a time, and reused across events.

Example input: `{"frame_rate":"30fps","ingestion_type":"rtmp","resolution":"240p","title":"<title>"}`

### `youtube_playlist_insert`

Create Playlist · Write

Create a new YouTube playlist for the authenticated user. Requires youtube scope.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `title` (`string`, required): Playlist title
- `default_language` (`string`, optional): Default language of the playlist
- `description` (`string`, optional): Playlist description
- `privacy_status` (`string`, optional): Privacy setting. One of: `public`, `unlisted`, `private`.
- `tags` (`array`, optional): Tags for the playlist

Example input: `{"title":"<title>"}`

### `youtube_playlist_items_insert`

Add Video to Playlist · Write

Add a video to a YouTube playlist at an optional position. Requires youtube scope.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `playlist_id` (`string`, required): Playlist to add the video to
- `video_id` (`string`, required): YouTube video ID to add
- `note` (`string`, optional): Optional note for this playlist item
- `position` (`integer`, optional): Zero-based position in the playlist. Omit to add at end.

Example input: `{"playlist_id":"<playlist_id>","video_id":"<video_id>"}`

### `youtube_playlist_update`

Update Playlist · Write

Update an existing YouTube playlist's title, description, privacy status, or default language. Requires youtube scope.

Read only: no. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `playlist_id` (`string`, required): ID of the playlist to update
- `default_language` (`string`, optional): Language of the playlist
- `description` (`string`, optional): New playlist description
- `privacy_status` (`string`, optional): New privacy setting. One of: `public`, `unlisted`, `private`.
- `title` (`string`, optional): New playlist title

Example input: `{"playlist_id":"<playlist_id>"}`

### `youtube_reporting_create_job`

Create Reporting Job · Write

Create a YouTube reporting job to schedule daily generation of a specific report type. Once created, YouTube will generate the report daily.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `name` (`string`, required): Human-readable name for the reporting job
- `report_type_id` (`string`, required): ID of the report type to generate (e.g., channel_basic_a2, channel_demographics_a1)
- `on_behalf_of_content_owner` (`string`, optional): Content owner ID on whose behalf the job is being created

Example input: `{"name":"<name>","report_type_id":"<report_type_id>"}`

### `youtube_subscriptions_insert`

Subscribe to Channel · Write

Subscribe the authenticated user to a YouTube channel. Requires youtube scope.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `channel_id` (`string`, required): ID of the YouTube channel to subscribe to

Example input: `{"channel_id":"<channel_id>"}`

### `youtube_videos_rate`

Rate a Video · Write

Like, dislike, or remove a rating from a YouTube video on behalf of the authenticated user. Requires youtube scope with youtube.force-ssl.

Read only: no. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `rating` (`string`, required): Rating to apply to the video. One of: `dislike`, `like`, `none`.
- `video_id` (`string`, required): YouTube video ID to rate

Example input: `{"rating":"dislike","video_id":"<video_id>"}`

### `youtube_videos_update`

Update Video · Write

Update metadata for an existing YouTube video. When updating snippet, both title and category_id are required together. Requires youtube scope.

Read only: no. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `video_id` (`string`, required): ID of the video to update
- `category_id` (`string`, optional): YouTube video category ID. Required together with title when updating snippet.
- `default_language` (`string`, optional): Language of the video
- `description` (`string`, optional): New video description
- `embeddable` (`boolean`, optional): Whether the video can be embedded
- `license` (`string`, optional): Video license. One of: `youtube`, `creativeCommon`.
- `privacy_status` (`string`, optional): New privacy setting. One of: `public`, `unlisted`, `private`.
- `public_stats_viewable` (`boolean`, optional): Whether stats are publicly visible
- `tags` (`array`, optional): Video tags
- `title` (`string`, optional): New video title. Required together with category_id when updating snippet.

Example input: `{"video_id":"<video_id>"}`

### `youtube_analytics_group_items_delete`

Delete Analytics Group Item · Destructive

Remove an item (video, channel, or playlist) from a YouTube Analytics group.

Read only: no. Destructive: yes. Idempotent (safe to retry): yes.

Inputs:

- `id` (`string`, required): ID of the group item to remove
- `on_behalf_of_content_owner` (`string`, optional): Content owner ID on whose behalf the request is being made

Example input: `{"id":"<id>"}`

### `youtube_analytics_groups_delete`

Delete Analytics Group · Destructive

Delete a YouTube Analytics group. This removes the group but does not delete the videos, channels, or playlists within it.

Read only: no. Destructive: yes. Idempotent (safe to retry): yes.

Inputs:

- `group_id` (`string`, required): ID of the Analytics group to delete
- `on_behalf_of_content_owner` (`string`, optional): Content owner ID on whose behalf the request is being made

Example input: `{"group_id":"<group_id>"}`

### `youtube_comments_delete`

Delete Comment · Destructive

Permanently delete a YouTube comment or reply that you have permission to remove. Requires youtube.force-ssl scope.

Read only: no. Destructive: yes. Idempotent (safe to retry): yes.

Inputs:

- `comment_id` (`string`, required): ID of the comment to delete

Example input: `{"comment_id":"<comment_id>"}`

### `youtube_playlist_delete`

Delete Playlist · Destructive

Permanently delete a YouTube playlist. This action cannot be undone. Requires youtube scope.

Read only: no. Destructive: yes. Idempotent (safe to retry): yes.

Inputs:

- `playlist_id` (`string`, required): ID of the playlist to delete

Example input: `{"playlist_id":"<playlist_id>"}`

### `youtube_playlist_items_delete`

Remove Playlist Item · Destructive

Remove a video from a YouTube playlist by its playlist item ID. Requires youtube scope.

Read only: no. Destructive: yes. Idempotent (safe to retry): yes.

Inputs:

- `playlist_item_id` (`string`, required): ID of the playlist item to remove (not the video ID)

Example input: `{"playlist_item_id":"<playlist_item_id>"}`

### `youtube_reporting_jobs_delete`

Delete Reporting Job · Destructive

Delete a scheduled YouTube Reporting API job. Stopping a job means new reports will no longer be generated.

Read only: no. Destructive: yes. Idempotent (safe to retry): yes.

Inputs:

- `job_id` (`string`, required): ID of the reporting job to delete
- `on_behalf_of_content_owner` (`string`, optional): Content owner ID on whose behalf the request is being made

Example input: `{"job_id":"<job_id>"}`

### `youtube_subscriptions_delete`

Unsubscribe from Channel · Destructive

Unsubscribe the authenticated user from a YouTube channel using the subscription ID. Requires youtube scope.

Read only: no. Destructive: yes. Idempotent (safe to retry): yes.

Inputs:

- `subscription_id` (`string`, required): ID of the subscription to delete

Example input: `{"subscription_id":"<subscription_id>"}`

### `youtube_videos_delete`

Delete Video · Destructive

Permanently delete a YouTube video. This action cannot be undone. Requires youtube scope.

Read only: no. Destructive: yes. Idempotent (safe to retry): yes.

Inputs:

- `video_id` (`string`, required): ID of the video to delete

Example input: `{"video_id":"<video_id>"}`

## Workflows

**Google OAuth consent screen verification**

Before you use your own Google OAuth credentials in production, understand what end users see on Google's consent screen when they authorize a connected account.

| Audience type | Consent screen behavior | When to use |
| --- | --- | --- |
| **Internal** | Shows your App Name and logo from Branding settings | Only users in your Google Workspace or Cloud Identity organization can authorize the connector |
| **External** | Shows `{env_name}.scalekit.dev` until Google verifies your app | Any user with a Google account can authorize the connector |

**Why External is required for most AgentKit connectors:**

- **Internal** restricts authorization to users in your Google Workspace or Cloud Identity organization. Users with `@gmail.com` or other Google accounts outside your organization cannot complete OAuth.
- **External** is required when end users outside your organization authorize tool access through connected accounts.
- **Organization-managed OAuth clients follow the same rules** as personal or developer OAuth clients. Switching to an org-owned client does not bypass Google verification.
- Until Google completes verification of your External app, users see `scalekit.dev` on the consent screen. After verification, your App Name and logo appear.

> note: Separate from Scalekit domain verification
>
> This is Google's OAuth consent screen behavior—not Scalekit's. [Custom domain](/agentkit/advanced/custom-domain/) controls your Scalekit environment URL for MCP auth branding. It does not replace Google's app verification for OAuth consent screens.

**During development:**

- Add **Test users** under **APIs & Services → OAuth consent screen** while publishing status is **Testing**.
- On unverified apps, users can click **Advanced → Go to app (unsafe)** to proceed during testing.
- Google Workspace admins may need to allowlist your OAuth client.

For Google's verification requirements and timeline, refer to [Google's OAuth consent screen verification guide](https://support.google.com/cloud/answer/13463073).

## Related

Other Media connectors ([all 22](/agentkit/connectors/?category=media)):

- [Reddit](/agentkit/connectors/reddit/): Scalekit connector, OAuth, 105 tools
- [Diarize](/agentkit/connectors/diarize/): Scalekit connector, Access token, 3 tools
- [Vimeo](/agentkit/connectors/vimeo/): Scalekit connector, OAuth, 59 tools


---

## More Scalekit documentation

| Resource | What it contains | When to use it |
|----------|-----------------|----------------|
| [/llms.txt](/llms.txt) | Structured index with routing hints per product area | Start here — find which documentation set covers your topic before loading full content |
| [/llms-full.txt](/llms-full.txt) | Complete documentation for all Scalekit products in one file | Use when you need exhaustive context across multiple products or when the topic spans several areas |
| [sitemap-0.xml](https://docs.scalekit.com/sitemap-0.xml) | Full URL list of every documentation page | Use to discover specific page URLs you can fetch for targeted, page-level answers |
