Install
openclaw skills install youtube-api-skillYouTube Data API integration with managed OAuth. Search videos, manage playlists, access channel data, and interact with comments. Use this skill when users want to interact with YouTube. For other third party apps, use the api-gateway skill (https://clawhub.ai/byungkyu/api-gateway).
openclaw skills install youtube-api-skillAccess the YouTube Data API v3 with managed OAuth authentication. Search videos, manage playlists, access channel information, and interact with comments and subscriptions.
CLI:
maton youtube search videos 'coding tutorial' --limit 10
maton api '/youtube/youtube/v3/search?part=snippet&q=coding+tutorial&type=video&maxResults=10'
Python:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/youtube/youtube/v3/search?part=snippet&q=coding+tutorial&type=video&maxResults=10')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
https://api.maton.ai/youtube/{native-api-path}
Maton proxies requests to www.googleapis.com and automatically injects your OAuth token.
NPM:
npm install -g @maton-ai/cli
Homebrew:
brew install maton-ai/cli/maton
CLI:
maton login # Opens browser for API key
maton login --interactive # Skip browser, paste API key directly
maton whoami # Show current auth state
Manual:
MATON_API_KEY:export MATON_API_KEY="YOUR_API_KEY"
Manage your Google OAuth connections at https://api.maton.ai.
CLI:
maton connection list youtube --status ACTIVE
maton api -X GET /connections -f app=youtube -f status=ACTIVE
Python:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections?app=youtube&status=ACTIVE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
CLI:
maton connection create youtube
maton api /connections -f app=youtube
Python:
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'youtube'}).encode()
req = urllib.request.Request('https://api.maton.ai/connections', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
CLI:
maton connection view {connection_id}
maton api /connections/{connection_id}
Python:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
{
"connection": {
"connection_id": "{connection_id}",
"status": "ACTIVE",
"creation_time": "2025-12-08T07:20:53.488460Z",
"last_updated_time": "2026-01-31T20:03:32.593153Z",
"url": "https://connect.maton.ai/?session_token=...",
"app": "youtube",
"metadata": {}
}
}
Open the returned url in a browser to complete OAuth authorization.
CLI:
maton connection delete {connection_id}
maton api -X DELETE /connections/{connection_id}
Python:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
If you have multiple YouTube connections, specify which one to use:
CLI:
maton youtube channel mine --connection {connection_id}
maton api '/youtube/youtube/v3/channels?part=snippet&mine=true' --connection {connection_id}
Python:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/youtube/youtube/v3/channels?part=snippet&mine=true')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Maton-Connection', '{connection_id}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
If you have multiple connections, always specify the connection to ensure requests go to the intended account.
GET /youtube/youtube/v3/search
Query parameters:
part - Required: snippetq - Search querytype - Filter by type: video, channel, playlistmaxResults - Results per page (1-50, default 5)order - Sort order: date, rating, relevance, title, viewCountpublishedAfter - Filter by publish date (RFC 3339)publishedBefore - Filter by publish date (RFC 3339)channelId - Filter by channelvideoDuration - short (<4min), medium (4-20min), long (>20min)pageToken - Pagination tokenExample:
maton youtube search videos 'machine learning' --limit 10 --order viewCount
maton youtube search channels 'rob pike'
maton youtube search playlists 'study music'
GET /youtube/youtube/v3/videos?part=snippet,statistics,contentDetails&id=dQw4w9WgXcQ
Parts available:
snippet - Title, description, thumbnails, channel infostatistics - View count, likes, commentscontentDetails - Duration, dimension, definitionstatus - Upload status, privacy statusplayer - Embedded player HTMLExample:
maton youtube video view dQw4w9WgXcQ
GET /youtube/youtube/v3/search?part=snippet&forMine=true&type=video&order=viewCount&maxResults=25
Example:
maton youtube search mine --order viewCount --limit 25
POST /youtube/youtube/v3/videos/rate?id=dQw4w9WgXcQ&rating=like
Rating values: like, dislike, none
Example:
maton youtube video rate dQw4w9WgXcQ --rating like
GET /youtube/youtube/v3/videos?part=snippet,statistics&chart=mostPopular®ionCode=US&maxResults=10
Example:
maton youtube video list --region US --limit 10
GET /youtube/youtube/v3/videoCategories?part=snippet®ionCode=US
Example:
maton youtube video-category list --region US
GET /youtube/youtube/v3/channels?part=snippet,statistics,contentDetails&id=UCBJycsmduvYEL83R_U4JriQ
Example:
maton youtube channel view UCBJycsmduvYEL83R_U4JriQ
GET /youtube/youtube/v3/channels?part=snippet,statistics,contentDetails&mine=true
Example:
maton youtube channel mine
Response:
{
"items": [
{
"id": "UCxyz123",
"snippet": {
"title": "My Channel",
"description": "Channel description",
"customUrl": "@mychannel",
"publishedAt": "2020-01-01T00:00:00Z",
"thumbnails": {...}
},
"statistics": {
"viewCount": "1000000",
"subscriberCount": "50000",
"videoCount": "100"
},
"contentDetails": {
"relatedPlaylists": {
"uploads": "UUxyz123"
}
}
}
]
}
GET /youtube/youtube/v3/channels?part=snippet,statistics&forUsername=GoogleDevelopers
Example:
maton youtube channel view --username GoogleDevelopers
To look up by @handle instead, use maton youtube channel view --handle GoogleDevelopers.
GET /youtube/youtube/v3/playlists?part=snippet,contentDetails&mine=true&maxResults=25
Example:
maton youtube playlist list --limit 25
GET /youtube/youtube/v3/playlists?part=snippet,contentDetails&id={playlistId}
Example:
maton youtube playlist view {playlistId}
POST /youtube/youtube/v3/playlists?part=snippet,status
Content-Type: application/json
{
"snippet": {
"title": "My New Playlist",
"description": "A collection of videos",
"defaultLanguage": "en"
},
"status": {
"privacyStatus": "private"
}
}
Privacy values: public, private, unlisted
Example:
maton youtube playlist create --title 'My New Playlist' --description 'A collection of videos' --privacy private
PUT /youtube/youtube/v3/playlists?part=snippet,status
Content-Type: application/json
{
"id": "PLxyz123",
"snippet": {
"title": "Updated Playlist Title",
"description": "Updated description"
},
"status": {
"privacyStatus": "public"
}
}
Example:
maton youtube playlist update PLxyz123 --title 'Updated Playlist Title' --description 'Updated description' --privacy public
DELETE /youtube/youtube/v3/playlists?id=PLxyz123
Example:
maton youtube playlist delete PLxyz123
GET /youtube/youtube/v3/playlistItems?part=snippet,contentDetails&playlistId={playlistId}&maxResults=50
Example:
maton youtube playlist items {playlistId} --limit 50
POST /youtube/youtube/v3/playlistItems?part=snippet
Content-Type: application/json
{
"snippet": {
"playlistId": "PLxyz123",
"resourceId": {
"kind": "youtube#video",
"videoId": "abc123xyz"
},
"position": 0
}
}
Example:
maton youtube playlist add-video --playlist PLxyz123 --video abc123xyz --position 0
DELETE /youtube/youtube/v3/playlistItems?id=UEx5dGVzdAAA
Example:
maton youtube playlist remove-video UEx5dGVzdAAA
The argument is the playlistItem ID (from maton youtube playlist items {playlistId}), not the video ID.
GET /youtube/youtube/v3/subscriptions?part=snippet&mine=true&maxResults=50
Example:
maton youtube subscription list --limit 50
GET /youtube/youtube/v3/subscriptions?part=snippet&mine=true&forChannelId={channelId}
Example:
maton youtube subscription list --for-channel {channelId}
The response is empty when no subscription exists.
POST /youtube/youtube/v3/subscriptions?part=snippet
Content-Type: application/json
{
"snippet": {
"resourceId": {
"kind": "youtube#channel",
"channelId": "UCxyz123"
}
}
}
Example:
maton youtube subscription create --channel UCxyz123
DELETE /youtube/youtube/v3/subscriptions?id={subscriptionId}
Example:
maton youtube subscription delete {subscriptionId}
The argument is the subscription ID (from maton youtube subscription list), not the channel ID.
GET /youtube/youtube/v3/commentThreads?part=snippet,replies&videoId={videoId}&order=time&maxResults=100
Example:
maton youtube comment list --video {videoId} --order time --limit 100
POST /youtube/youtube/v3/commentThreads?part=snippet
Content-Type: application/json
{
"snippet": {
"videoId": "{videoId}",
"topLevelComment": {
"snippet": {
"textOriginal": "Great video!"
}
}
}
}
Example:
maton youtube comment create --video {videoId} --text 'Great video!'
POST /youtube/youtube/v3/comments?part=snippet
Content-Type: application/json
{
"snippet": {
"parentId": "{commentId}",
"textOriginal": "Thanks for your comment!"
}
}
Example:
maton youtube comment create --parent {commentId} --text 'Thanks for your comment!'
DELETE /youtube/youtube/v3/comments?id={commentId}
Example:
maton youtube comment delete {commentId}
YouTube uses cursor-based pagination via pageToken. The CLI automatically paginates with --paginate.
Example:
maton youtube playlist items {playlistId} --paginate
# Search videos as JSON (default format)
maton youtube search videos 'tutorial' --limit 10
# Filter with jq — e.g., extract just video IDs and titles
# Note: --jq requires --json
maton youtube search videos 'tutorial' --limit 10 \
--json --jq '.items[] | {id: .id.videoId, title: .snippet.title}'
# List your playlists and extract titles only
maton youtube playlist list --json --jq '.items[].snippet.title'
const headers = {
'Authorization': `Bearer ${process.env.MATON_API_KEY}`
};
// Search videos
const results = await fetch(
'https://api.maton.ai/youtube/youtube/v3/search?part=snippet&q=tutorial&type=video&maxResults=10',
{ headers }
).then(r => r.json());
// Get video details
const video = await fetch(
'https://api.maton.ai/youtube/youtube/v3/videos?part=snippet,statistics&id=dQw4w9WgXcQ',
{ headers }
).then(r => r.json());
// Create playlist
await fetch(
'https://api.maton.ai/youtube/youtube/v3/playlists?part=snippet,status',
{
method: 'POST',
headers: { ...headers, 'Content-Type': 'application/json' },
body: JSON.stringify({
snippet: { title: 'My Playlist', description: 'Videos I like' },
status: { privacyStatus: 'private' }
})
}
);
import os
import requests
headers = {'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}
# Search videos
results = requests.get(
'https://api.maton.ai/youtube/youtube/v3/search',
headers=headers,
params={'part': 'snippet', 'q': 'tutorial', 'type': 'video', 'maxResults': 10}
).json()
# Get video details
video = requests.get(
'https://api.maton.ai/youtube/youtube/v3/videos',
headers=headers,
params={'part': 'snippet,statistics', 'id': 'dQw4w9WgXcQ'}
).json()
# Create playlist
response = requests.post(
'https://api.maton.ai/youtube/youtube/v3/playlists?part=snippet,status',
headers=headers,
json={
'snippet': {'title': 'My Playlist', 'description': 'Videos I like'},
'status': {'privacyStatus': 'private'}
}
)
dQw4w9WgXcQ)UC (e.g., UCxyz123)PL (user) or UU (uploads)pageToken for pagination through large result setspart parameter is required and determines what data is returnedcurl -g when URLs contain brackets (fields[], sort[], records[]) to disable glob parsingjq or other commands, environment variables like $MATON_API_KEY may not expand correctly in some shell environments. You may get "Invalid API key" errors when piping.| Status | Meaning |
|---|---|
| 400 | Missing YouTube connection or invalid request |
| 401 | Invalid or missing Maton API key |
| 403 | Forbidden - quota exceeded or insufficient permissions |
| 404 | Video, channel, or playlist not found |
| 429 | Rate limited (10 req/sec per account) |
| 4xx/5xx | Passthrough error from YouTube API |
CLI:
maton whoami
maton connection list
Manual:
MATON_API_KEY environment variable is set:echo $MATON_API_KEY
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
youtube. For example:https://api.maton.ai/youtube/youtube/v3/searchhttps://api.maton.ai/v3/search