Multi-language SDK for the YouTube Data API v3 (and Analytics API v2 in
Python). Ships both a Python client (under youtube/) and a Go client (under
go/).
Note: This repository was renamed from
Inoue-AI/YouTube-Python-SDKtoInoue-AI/Inoue-AI-YouTube-SDK. GitHub auto-redirects the old URL, so existingpip install ... @ git+https://github.com/Inoue-AI/YouTube-Python-SDK.gitcommands continue to work. The local clone keeps the legacy directory name.
The Python source remains under youtube/. Install:
pip install "git+https://github.com/Inoue-AI/Inoue-AI-YouTube-SDK.git"The Go SDK lives under go/. It exposes a focused subset matching
the calls the Inoue AI Go backend makes today (channel + uploads playlist +
single video). Phase 3 will expand the surface as needed.
go get github.com/Inoue-AI/Inoue-AI-YouTube-SDK/go@latestclient := youtube.New(youtube.ClientOptions{AccessToken: "..."})
defer client.Close()
ch, err := client.GetChannel(ctx, youtube.GetChannelParams{Mine: true})See go/README.md for the full Go API.
Async Python SDK for the YouTube Data API v3 and YouTube Analytics API v2.
Built with aiohttp and pydantic v2. Follows the same architecture as the TikTok Python SDK.
- 14 API namespaces — Videos, Channels, Playlists, PlaylistItems, Comments, CommentThreads, Subscriptions, Thumbnails, Search, Captions, ChannelSections, ChannelBanners, Watermarks, Analytics
- Pydantic v2 models for every request and response — full type safety, IDE autocomplete, and serialization
- Async-first — powered by
aiohttpwith lazy session creation - Resumable video uploads — handles chunked uploads automatically
- Auto-pagination — async iterators for paging through large result sets
- Dual auth — OAuth 2.0 access tokens (full access) or API keys (public read-only)
- Comprehensive error hierarchy — typed exceptions mapped from YouTube error codes
pip install youtube-python-sdkOr install from source:
git clone https://github.com/inoue-ai/youtube-python-sdk.git
cd youtube-python-sdk
pip install -e ".[dev]"import asyncio
from youtube import YouTubeClient, VideoPart
async def main():
async with YouTubeClient(api_key="YOUR_API_KEY") as yt:
response = await yt.videos.list(
parts=[VideoPart.SNIPPET, VideoPart.STATISTICS],
chart="mostPopular",
max_results=10,
)
for video in response.items:
print(f"{video.snippet.title} — {video.statistics.view_count} views")
asyncio.run(main())import asyncio
from youtube import (
YouTubeClient, ChannelPart, Video, VideoSnippet, VideoStatus,
PrivacyStatus, VideoPart,
)
async def main():
async with YouTubeClient(access_token="OAUTH_ACCESS_TOKEN") as yt:
# Get your channel info
channels = await yt.channels.list(
parts=[ChannelPart.SNIPPET, ChannelPart.STATISTICS],
mine=True,
)
channel = channels.items[0]
print(f"Channel: {channel.snippet.title}")
print(f"Subscribers: {channel.statistics.subscriber_count}")
# Upload a video
video = await yt.videos.insert(
body=Video(
snippet=VideoSnippet(
title="My New Video",
description="Uploaded via the YouTube Python SDK!",
tags=["sdk", "python", "youtube"],
category_id="22",
),
status=VideoStatus(
privacy_status=PrivacyStatus.PRIVATE,
),
),
file_path="/path/to/video.mp4",
)
print(f"Uploaded: {video.id}")
# Set a custom thumbnail
await yt.thumbnails.set_from_file(
video_id=video.id,
file_path="/path/to/thumbnail.jpg",
)
asyncio.run(main())from youtube import YouTubeClient, SearchResultType, SearchOrder
async with YouTubeClient(api_key="KEY") as yt:
results = await yt.search.list(
q="python tutorial",
type=SearchResultType.VIDEO,
order=SearchOrder.VIEW_COUNT,
max_results=25,
)
for item in results.items:
print(f"{item.snippet.title} — {item.id.video_id}")from youtube import (
YouTubeClient, Playlist, PlaylistSnippet, PlaylistStatus,
PlaylistPart, PlaylistItem, PlaylistItemSnippet, PlaylistItemPart,
PrivacyStatus, ResourceId,
)
async with YouTubeClient(access_token="TOKEN") as yt:
# Create a playlist
playlist = await yt.playlists.insert(
body=Playlist(
snippet=PlaylistSnippet(title="My SDK Playlist"),
status=PlaylistStatus(privacy_status=PrivacyStatus.PUBLIC),
),
)
# Add a video to the playlist
await yt.playlist_items.insert(
body=PlaylistItem(
snippet=PlaylistItemSnippet(
playlist_id=playlist.id,
resource_id=ResourceId(
kind="youtube#video",
video_id="dQw4w9WgXcQ",
),
),
),
)from youtube import (
YouTubeClient, CommentThread, CommentThreadSnippet,
CommentThreadPart, Comment, CommentSnippet, CommentPart,
)
async with YouTubeClient(access_token="TOKEN") as yt:
# Post a top-level comment
thread = await yt.comment_threads.insert(
body=CommentThread(
snippet=CommentThreadSnippet(
video_id="VIDEO_ID",
channel_id="CHANNEL_ID",
top_level_comment=Comment(
snippet=CommentSnippet(text_original="Great video!"),
),
),
),
)
# List comments on a video
async for thread in yt.comment_threads.iter_video_threads(
"VIDEO_ID",
parts=[CommentThreadPart.SNIPPET, CommentThreadPart.REPLIES],
):
top = thread.snippet.top_level_comment.snippet
print(f"{top.author_display_name}: {top.text_display}")from youtube import YouTubeClient
async with YouTubeClient(access_token="TOKEN") as yt:
report = await yt.analytics.query(
start_date="2025-01-01",
end_date="2025-12-31",
metrics=["views", "likes", "estimatedMinutesWatched"],
dimensions=["day"],
)
for row in report.rows:
print(row) # [date, views, likes, minutes_watched]from youtube import YouTubeClient, Caption, CaptionSnippet, CaptionPart, CaptionFormat
async with YouTubeClient(access_token="TOKEN") as yt:
# List captions for a video
captions = await yt.captions.list(
parts=[CaptionPart.SNIPPET],
video_id="VIDEO_ID",
)
# Download a caption track as SRT
srt_data = await yt.captions.download(
id=captions.items[0].id,
tfmt=CaptionFormat.SRT,
)
# Upload a new caption track
await yt.captions.insert_from_file(
body=Caption(
snippet=CaptionSnippet(
video_id="VIDEO_ID",
language="en",
name="English",
),
),
file_path="/path/to/captions.srt",
)| Namespace | Methods | Description |
|---|---|---|
yt.videos |
list, insert, update, delete, rate, get_rating, report_abuse | Video management & upload |
yt.channels |
list, update | Channel info & branding |
yt.playlists |
list, insert, update, delete | Playlist CRUD |
yt.playlist_items |
list, insert, update, delete | Manage videos in playlists |
yt.comments |
list, insert, update, delete, set_moderation_status | Comment replies & moderation |
yt.comment_threads |
list, insert | Top-level comments |
yt.subscriptions |
list, insert, delete | Subscription management |
yt.thumbnails |
set, set_from_file | Custom thumbnail upload |
yt.search |
list | Search across YouTube |
yt.captions |
list, insert, insert_from_file, update, download, delete | Caption track management |
yt.channel_sections |
list, insert, update, delete | Channel page layout |
yt.channel_banners |
insert, insert_from_file | Banner image upload |
yt.watermarks |
set, unset | Channel watermark |
yt.analytics |
query | YouTube Analytics reports |
The SDK does not handle OAuth flows. You must provide a pre-obtained token:
access_token— OAuth 2.0 token for full read/write accessapi_key— Google API key for read-only public data
# OAuth (full access)
client = YouTubeClient(access_token="ya29....")
# API key (public read-only)
client = YouTubeClient(api_key="AIzaSy...")
# Both (OAuth takes priority, API key added to all requests)
client = YouTubeClient(access_token="ya29....", api_key="AIzaSy...")# Install dev dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Lint & format
ruff check .
ruff format .
# Type check
mypy youtube/MIT License — see LICENSE for details.