Connectors
/
YouTube
Live · 35 tools

YouTube Integration for AI Agents

The YouTube Data API is well-documented. Getting your agent to call it correctly — for real users, with Google's OAuth scope tiers, token revocation on password change, and per-user isolation — is the part that takes longer than it should.
YouTube
Live

Video

Content & Media

Status
Live
Tools
35 pre-built
Auth
OAuth 2.0
Credential storage
Sandbox support

OAuth 2.0

Auto token refresh

Revocation detection

Scoped permissions

The real problem

Why this is harder than it looks

The YouTube Data API v3 documentation is thorough. The OAuth flow is standard. Most developers get a working prototype against their own channel in an afternoon. The complexity arrives when you try to do this for real users in a multi-tenant product.

YouTube's OAuth is backed by Google's infrastructure, which means it inherits Google's scope enforcement model. The scopes are split into tiers: youtube.readonly is sensitive and requires Google to review and verify your app before users outside your test group can connect without an "unverified app" warning. Broader scopes like youtube or youtube.force-ssl — required for writes like creating playlists, posting comments, or managing subscriptions — are also sensitive and carry the same verification requirement. Getting the scope selection wrong creates friction at the authorization step, especially for users on Google Workspace accounts where admins can block non-approved third-party apps entirely via admin_policy_enforced.

Then there's the token revocation problem. Google revokes all OAuth refresh tokens containing YouTube scopes when the user changes their Google account password. In enterprise Workspace deployments with mandatory password rotation, this happens routinely and without warning. Refresh tokens also expire after six months of inactivity, and in Google Cloud projects with the OAuth consent screen set to "Testing," tokens expire after seven days. Without per-user revocation detection, your agent silently starts returning invalid_grant errors with no actionable signal for the user.

Finally, the YouTube Analytics API is a separate API surface from the YouTube Data API, with its own quota system. Analytics queries — even simple ones like views or watch time — require the yt-analytics.readonly scope in addition to the data scopes, and the quota costs are tracked independently. An agent that mixes data and analytics calls without accounting for this will hit quota limits on the analytics side while the data quota remains untouched, producing failures that look identical to auth errors.

Scalekit handles scope configuration, token refresh, revocation detection, and per-user isolation. Your agent names a tool and passes parameters. The auth plumbing is not your problem.

Capabilities

What your agent can do with YouTube

Once connected, your agent has 35 pre-built tools covering the full YouTube Data API and YouTube Analytics API:

  • Search and retrieve video metadata: search YouTube by keyword, channel, or date range; fetch video statistics, captions, and category data
  • Manage playlists end-to-end: create, update, and delete playlists; add or remove videos with position control
  • Read and post comments: list comment threads on videos or channels, post top-level comments, and retrieve replies
  • Manage subscriptions: list, add, and remove channel subscriptions for the authenticated user
  • Query YouTube Analytics: pull views, watch time, subscriber counts, and revenue metrics with date range, dimension, and filter support
  • Schedule and retrieve reports: create Reporting API jobs for recurring bulk analytics exports; list and retrieve generated CSV reports
Setup context

What we're building

This guide connects a content operations agent to YouTube — helping creators and teams query video performance, manage playlists, and monitor channel activity without leaving your product.

🤖
Example agent
Content assistant querying video analytics, managing playlists, and tracking channel performance on behalf of each creator
🔐
Auth model
B2B SaaS — each creator connects their own YouTube channel. identifier = your user ID
⚙️
Scalekit account
app.scalekit.com — Client ID, Secret, Env URL
🔑
Google Cloud project
Register an OAuth 2.0 client and enable the YouTube Data API v3 at console.cloud.google.com
Setup

1 Setup: One SDK, One credential

Install the Scalekit SDK. The only credential your application manages is the Scalekit API key — no YouTube secrets, no user tokens, nothing belonging to your users.

pip install scalekit-sdk-python
npm install @scalekit-sdk/node
import scalekit.client import os from dotenv import load_dotenv load_dotenv() scalekit = scalekit.client.ScalekitClient( client_id=os.getenv("SCALEKIT_CLIENT_ID"), client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"), env_url=os.getenv("SCALEKIT_ENV_URL"), ) actions = scalekit.actions
import { ScalekitClient } from '@scalekit-sdk/node'; import 'dotenv/config'; const scalekit = new ScalekitClient( process.env.SCALEKIT_ENV_URL, process.env.SCALEKIT_CLIENT_ID, process.env.SCALEKIT_CLIENT_SECRET ); const actions = scalekit.actions;
Already have credentials?
Connected Accounts

2 Per-User Auth: Creating connected accounts

Each creator gets their own Connected Account, giving them a dedicated auth context. The identifier is any unique string from your system — a UUID, email, whatever you use internally.

response = actions.get_or_create_connected_account( connection_name="youtube", identifier="user_yt_456" # your internal user ID ) connected_account = response.connected_account print(f"Status: {connected_account.status}") # Status: PENDING — user hasn't authorized yet
const response = await actions.getOrCreateConnectedAccount({ connectionName: "youtube", identifier: "user_yt_456" // your internal user ID }); const connectedAccount = response.connectedAccount; console.log(`Status: ${connectedAccount.status}`); // Status: PENDING — user hasn't authorized yet

This call is idempotent — safe to call on every session start. Returns the existing account if one already exists.

Authorization Flow

3 The authorization flow

The user authorizes your agent once. Scalekit generates the OAuth URL with correct scopes, PKCE challenge, and redirect handling pre-configured. After approval, you never see the token.

if connected_account.status != "ACTIVE": link = actions.get_authorization_link( connection_name="youtube", identifier="user_yt_456" ) # Redirect user → Google's native OAuth consent screen # Scalekit captures the token on callback return redirect(link.link)
if (connectedAccount.status !== "ACTIVE") { const { link } = await actions.getAuthorizationLink({ connectionName: "youtube", identifier: "user_yt_456" }); // Redirect user → Google's native OAuth consent screen // Scalekit captures the token on callback return redirect(link); }
Token management is automatic
After the user approves, Scalekit stores encrypted tokens and the connected account moves to ACTIVE. Access tokens refresh before expiry. If a user's token is revoked — by password change, admin policy, or manual revocation — the account moves to REVOKED. No silent invalid_grant failures. Check account.status before critical operations.
Bring Your Own Credentials — required for production
YouTube requires you to register your own Google Cloud OAuth 2.0 client and supply your Client ID and Secret. Scalekit does not provide a managed Google app for YouTube. In the Scalekit dashboard, go to Agent Auth → Connections → your YouTube connection, click "Use your own credentials," and paste your Google credentials. Token management stays fully handled.
Calling YouTube

4 Calling YouTube: What your agent writes

With the connected account active, your agent calls YouTube actions using actions.execute_tool(). Name the tool, pass parameters. Scalekit handles token retrieval and request construction.

Get channel details

Retrieve metadata and statistics for the authenticated user's channel. Pass mine: true to fetch the connected user's own channel — use id for any public channel by ID.

result = actions.execute_tool( identifier="user_yt_456", tool_name="youtube_channels_list", tool_input={ "part": "snippet,statistics,contentDetails", "mine": True } ) # Returns: channel name, description, subscriber count, video count, view count
const result = await actions.executeTool({ identifier: "user_yt_456", toolName: "youtube_channels_list", toolInput: { "part": "snippet,statistics,contentDetails", "mine": true } }); // Returns: channel name, description, subscriber count, video count, view count

Query analytics for a date range

Pull views, watch time, and subscriber changes for a channel. The ids field must be prefixed with channel==. Use dimensions to break results down by day, country, or video.

result = actions.execute_tool( identifier="user_yt_456", tool_name="youtube_analytics_query", tool_input={ "ids": "channel==MINE", "start_date": "2026-01-01", "end_date": "2026-03-31", "metrics": "views,estimatedMinutesWatched,subscribersGained,subscribersLost", "dimensions": "day", "sort": "-views" } ) # Returns: daily rows with view counts, watch time, and subscriber delta
const result = await actions.executeTool({ identifier: "user_yt_456", toolName: "youtube_analytics_query", toolInput: { "ids": "channel==MINE", "start_date": "2026-01-01", "end_date": "2026-03-31", "metrics": "views,estimatedMinutesWatched,subscribersGained,subscribersLost", "dimensions": "day", "sort": "-views" } }); // Returns: daily rows with view counts, watch time, and subscriber delta

Search and list videos

Search across YouTube using any keyword, optionally scoped to a channel. Use type to restrict to videos, channels, or playlists. Returns snippet data including title, description, and publish date.

result = actions.execute_tool( identifier="user_yt_456", tool_name="youtube_search", tool_input={ "q": "product demo 2026", "type": "video", "channel_id": "UCxxxxxxxxxxxxxxxxxxxxxx", "max_results": 10, "order": "date" } ) # Returns: list of video snippets with videoId, title, description, publishedAt
const result = await actions.executeTool({ identifier: "user_yt_456", toolName: "youtube_search", toolInput: { "q": "product demo 2026", "type": "video", "channel_id": "UCxxxxxxxxxxxxxxxxxxxxxx", "max_results": 10, "order": "date" } }); // Returns: list of video snippets with videoId, title, description, publishedAt

Create a playlist and add videos

Create a new playlist, then add videos to it. Both calls require the youtube scope. Use the position parameter in insert to control ordering.

# 1. Create the playlist playlist = actions.execute_tool( identifier="user_yt_456", tool_name="youtube_playlist_insert", tool_input={ "title": "Q2 2026 Product Demos", "description": "All demo videos from Q2", "privacy_status": "public" } ) playlist_id = playlist["id"] # 2. Add a video to the playlist result = actions.execute_tool( identifier="user_yt_456", tool_name="youtube_playlist_items_insert", tool_input={ "playlist_id": playlist_id, "video_id": "dQw4w9WgXcQ", "position": 0 } )
// 1. Create the playlist const playlist = await actions.executeTool({ identifier: "user_yt_456", toolName: "youtube_playlist_insert", toolInput: { "title": "Q2 2026 Product Demos", "description": "All demo videos from Q2", "privacy_status": "public" } }); const playlistId = playlist.id; // 2. Add a video to the playlist const result = await actions.executeTool({ identifier: "user_yt_456", toolName: "youtube_playlist_items_insert", toolInput: { "playlist_id": playlistId, "video_id": "dQw4w9WgXcQ", "position": 0 } });
Framework wiring

5 Wiring into your agent framework

Scalekit integrates directly with LangChain. The agent decides what to call; Scalekit handles auth on every invocation. No token plumbing in your agent logic.

from langchain_anthropic import ChatAnthropic from langchain.agents import AgentExecutor, create_tool_calling_agent from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from scalekit.langchain import get_tools yt_tools = get_tools( connection_name="youtube", identifier="user_yt_456" ) prompt = ChatPromptTemplate.from_messages([ ("system", "You are a YouTube content assistant. Use the available tools to help manage video content, playlists, and channel analytics."), MessagesPlaceholder("chat_history", optional=True), ("human", "{input}"), MessagesPlaceholder("agent_scratchpad"), ]) agent = create_tool_calling_agent(ChatAnthropic(model="claude-sonnet-4-6"), yt_tools, prompt) result = AgentExecutor(agent=agent, tools=yt_tools).invoke({ "input": "Show me the top 5 videos by views from the last 30 days and create a playlist with them" })
import { ChatAnthropic } from "@langchain/anthropic"; import { AgentExecutor, createToolCallingAgent } from "langchain/agents"; import { ChatPromptTemplate, MessagesPlaceholder } from "@langchain/core/prompts"; import { getTools } from "@scalekit-sdk/langchain"; const ytTools = getTools({ connectionName: "youtube", identifier: "user_yt_456" }); const prompt = ChatPromptTemplate.fromMessages([ ["system", "You are a YouTube content assistant. Use the available tools to help manage video content, playlists, and channel analytics."], new MessagesPlaceholder("chat_history", true), ["human", "{input}"], new MessagesPlaceholder("agent_scratchpad"), ]); const agent = await createToolCallingAgent({ llm: new ChatAnthropic({ model: "claude-sonnet-4-6" }), tools: ytTools, prompt }); const result = await AgentExecutor.fromAgentAndTools({ agent, tools: ytTools }).invoke({ input: "Show me the top 5 videos by views from the last 30 days and create a playlist with them" });
Other frameworks supported
Tool reference

All 35 YouTube tools

Grouped by capability. Your agent calls tools by name — no API wrappers to write.

Channels
youtube_channels_list
Retrieve channel metadata and statistics. Filter by mine, id, handle, or username. Requires exactly one filter.
Videos
youtube_videos_list
Retrieve detailed video info including statistics, content details, and status. Filter by id, chart, or my_rating
youtube_videos_update
Update video metadata — title, description, tags, privacy status, and category. title and category_id are required together when updating snippet
youtube_videos_delete
Permanently delete a video by ID. Requires youtube scope. Cannot be undone
youtube_videos_rate
Like, dislike, or remove a rating from a video on behalf of the authenticated user. Requires youtube.force-ssl scope
youtube_videos_get_rating
Retrieve the authenticated user's rating for one or more videos by comma-separated video IDs
Search
youtube_search
Search videos, channels, and playlists by keyword, channel, date range, and type. Supports safe search, ordering, and pagination
Playlists
youtube_playlist_insert
Create a new playlist with title, description, privacy status, and tags. Requires youtube scope
youtube_playlist_update
Update a playlist's title, description, privacy status, or language by playlist ID
youtube_playlist_delete
Permanently delete a playlist by ID. Does not delete the videos within it
youtube_playlists_list
List playlists for the authenticated user or a specific channel. Filter by mine, channel_id, or id
Playlist Items
youtube_playlist_items_insert
Add a video to a playlist at an optional position. Requires youtube scope
youtube_playlist_items_list
List all videos in a playlist with position and metadata. Supports pagination and optional video ID filter
youtube_playlist_items_delete
Remove a video from a playlist using its playlist item ID (not video ID). Requires youtube scope
Comments
youtube_comment_threads_insert
Post a new top-level comment on a video. Requires youtube.force-ssl scope
youtube_comment_threads_list
List top-level comment threads for a video or channel, with optional keyword filtering. Requires exactly one filter: video_id, channel ID, or thread id
youtube_comments_list
Retrieve replies to a specific comment thread. Filter by parent_id or comment id. Requires youtube.readonly scope
Captions
youtube_captions_list
List caption tracks for a video. Requires youtube.force-ssl scope
Subscriptions
youtube_subscriptions_insert
Subscribe the authenticated user to a channel by channel ID. Requires youtube scope
youtube_subscriptions_delete
Unsubscribe the authenticated user from a channel using the subscription ID. Requires youtube scope
youtube_subscriptions_list
List subscriptions for the authenticated user or a channel. Filter by mine, channel_id, id, my_recent_subscribers, or my_subscribers
Video Categories
youtube_video_categories_list
Retrieve available video categories for a region or by ID. Useful for setting category when updating a video
Analytics
youtube_analytics_query
Query views, watch time, subscribers, and revenue metrics with date range, dimension, and filter support. Requires yt-analytics.readonly scope
youtube_analytics_group_create
Create an Analytics group to organize videos, playlists, or channels for collective reporting
youtube_analytics_groups_list
List Analytics groups for a channel or content owner. Filter by mine or specific group IDs
youtube_analytics_groups_update
Update the title of an existing Analytics group by group ID
youtube_analytics_groups_delete
Delete an Analytics group. Does not delete the videos or playlists within it
youtube_analytics_group_item_insert
Add a video, playlist, or channel to an Analytics group by resource ID and type
youtube_analytics_group_items_list
Retrieve all items belonging to an Analytics group by group ID
youtube_analytics_group_items_delete
Remove an item from an Analytics group by group item ID
Reporting
youtube_reporting_create_job
Schedule a recurring daily report job by report type ID (e.g., channel_basic_a2). YouTube generates the report daily once created
youtube_reporting_list_jobs
List all active Reporting API jobs for a channel or content owner, including system-managed jobs
youtube_reporting_jobs_delete
Delete a scheduled reporting job. Stops future report generation; does not delete already-generated reports
youtube_reporting_list_report_types
List all available report type IDs (e.g., channel_basic_a2, channel_demographics_a1) for a channel or content owner
youtube_reporting_list_reports
List generated reports for a job, with optional date filters. Each report is a downloadable CSV file
Connector notes

YouTube-specific behavior

Tokens are revoked on password change — by design
Google revokes all refresh tokens containing YouTube scopes when the user changes their Google account password. In enterprise Workspace deployments with mandatory password rotation, this happens routinely. The account will move to REVOKED in Scalekit. Check account.status before operations and surface a re-authorization prompt rather than returning a generic error.
Analytics and Data API quotas are tracked separately
The YouTube Analytics API and YouTube Data API v3 use independent quota pools. An agent that mixes data and analytics calls can exhaust one quota while the other remains untouched. Monitor both independently in Google Cloud Console under the respective APIs. Analytics queries also require the yt-analytics.readonly scope in addition to any data scopes.
Scope selection determines your Google verification path
YouTube scopes are sensitive. Read-only access (youtube.readonly) and write access (youtube, youtube.force-ssl) both require Google app verification before users outside your test group can connect without an "unverified app" warning. Use the narrowest scope set that covers your agent's actual functionality, and configure the approved scope set in the Scalekit dashboard under your YouTube connection.
Playlist item removal uses the playlist item ID, not the video ID
youtube_playlist_items_delete requires the playlist item ID returned from youtube_playlist_items_list — not the video ID. Passing a video ID to this tool returns a 404. Always retrieve the playlist item ID from a list call before attempting removal.
Infrastructure decision

Why not build this yourself

The YouTube OAuth flow is documented. Token storage isn't technically hard. But here's what you're actually signing up for:

PROBLEM 01
Token revocation on every user password change — a routine event in Workspace deployments — requires per-user detection and re-authorization prompts your backend must handle gracefully
PROBLEM 02
Google's sensitive scope tier requires app verification before real users can connect — getting scope selection wrong either breaks enterprise IT approval or triggers re-verification when you add new capabilities
PROBLEM 03
Per-user token isolation across a multi-tenant system — one creator's YouTube credentials must never be accessible to another, even within the same organization
PROBLEM 04
Separate Analytics and Data API quota pools, 7-day token expiry in testing mode, and Workspace admin_policy_enforced errors are all silent failure modes that only surface with real users in production

That's one connector. Your agent product will eventually need Salesforce, Gmail, Slack, HubSpot, and whatever else your customers ask for. Each has its own OAuth quirks and failure modes.

Scalekit maintains every connector. You maintain none of them.

Ready to ship

Ship YouTube in minutes

Free to start. Token management fully handled. Google OAuth verification lifecycle managed.
YouTube
Live

Video

Content & Media

Status
Live
Tools
35 pre-built
Auth
OAuth 2.0
Credential storage
Sandbox support