Youtube REST API Client

yt - Native Dart Client for YouTube APIs

Native Dart interface to multiple Google REST APIs, including:

Related Packages:

  • yt_cli — CLI tool for YouTube APIs
  • yt_mcp — MCP server for AI integration

pub package License: MIT github build github issues

Quick Start

import 'package:yt/yt.dart';

void main() async {
  // Use an API key for read-only access
  final yt = Yt.withKey('[your youtube api key]');

  // Search for videos
  final results = await yt.search.list(q: 'flutter tutorial', maxResults: 5);
  for (final item in results.items) {
    print('${item.snippet?.title}');
  }
}

For write operations (uploading videos, managing broadcasts), use OAuth — see Configuration below.

Features

  • YouTube Data API — Channels, Playlists, Videos, Search, Comments, Subscriptions, Thumbnails, Captions, and more
  • YouTube Live Streaming API — LiveBroadcasts, LiveStreams, and LiveChat
  • YouTube Analytics API — Reports, Groups, and Group Items for channel analytics
  • Members & Memberships — Channel members, membership levels, and video abuse report reasons
  • Activities — Channel activity feeds including uploads, likes, favorites, subscriptions, and playlist additions
  • Multiple auth methods — API key, OAuth 2.0 with automatic token refresh, or custom token generators
  • Cross-platform — works on all Dart/Flutter platforms including web, mobile, and desktop
  • Dart-first — manually crafted (not auto-generated) for a focused, well-documented API surface

Getting Started

Add to your pubspec.yaml:

dependencies:
  yt: ^2.3.0

Configuration

YouTube API access requires either an API key (read-only) or OAuth 2.0 credentials.

Action Type Authentication Requirement Why
Reading Public Data API Key or OAuth 2.0 Accesses data anyone can see (e.g., public video titles, search results).
Reading Private Data OAuth 2.0 Required Accesses data specific to a user (e.g., a user's private videos or watch history).
Writing/Modifying Data OAuth 2.0 Required Performs actions on behalf of a user (e.g., uploading, deleting, or commenting).

API Key

Create an API key in the Google API Console, then:

final yt = Yt.withKey('[your api key]');

OAuth 2.0

Create OAuth credentials in the Google API Console, then generate a credentials file:

yt authorize

This creates $HOME/.yt/credentials.json. Then:

final yt = Yt.withOAuth();  // Uses default credentials file

For manual credential files, the format is:

identifier: [client id from the API console]
secret: [client secret from the API console]

Usage

Data API

import 'package:yt/yt.dart';

final yt = Yt.withOAuth();

var playlistResponse = await yt.playlists.list(
    channelId: '[youtube channel id]', maxResults: 25);

playlistResponse.items
    .forEach((playlist) => print('${playlist.snippet?.title}'));

Upload a Video

final yt = await Yt.withOAuth();

final body = <String, dynamic>{
  'snippet': {
    'title': 'TEST title',
    'description': 'Test Description',
    'tags': ['tag1', 'tag2'],
    'categoryId': '22'
  },
  'status': {
    'privacyStatus': 'private',
    'embeddable': true,
    'license': 'youtube'
  }
};

final videoItem = await yt.videos.insert(
    body: body,
    videoFile: File('[path to a video to upload]'),
    notifySubscribers: false);

print(videoItem);

Live Streaming API

import 'package:yt/yt.dart';

final yt = await Yt.withOAuth();
final br = yt.broadcast;
final th = yt.thumbnails;

// Create a broadcast
final broadcastItem = await br.insert(body: {
  'snippet': {
    'title': 'TEST Broadcast',
    'description': 'Test',
    'scheduledStartTime':
        DateTime.now().add(Duration(hours: 2)).toUtc().toIso8601String()
  },
  'status': {'privacyStatus': 'private'},
  'contentDetails': {
    'monitorStream': {
      'enableMonitorStream': false,
      'broadcastStreamDelayMs': 10
    },
    'enableDvr': true,
    'enableContentEncryption': true,
    'enableEmbed': true,
    'recordFromStart': true,
    'startWithSlate': false
  }
}, part: 'snippet,status,contentDetails');

// Bind to a stream and upload thumbnail
await br.bind(
    broadcastId: broadcastItem.id,
    streamId: '[one of your valid stream ids]');

await th.set(
    videoId: broadcastItem.id,
    thumbnail: File('[path to an image to upload]'));

Download a LiveChat

final yt = await Yt.withOAuth();

var broadcastResponse = await yt.broadcast.list(broadcastStatus: 'active');

if (broadcastResponse.items.isNotEmpty) {
  await yt.chat.downloadHistory(
      liveBroadcastItem: broadcastResponse.items.first);
}

Analytics

final yt = await Yt.withOAuth();

// Query channel analytics
final report = await yt.analytics.query(
  ids: 'channel==MINE',
  startDate: '2026-01-01',
  endDate: '2026-01-31',
  metrics: 'views,estimatedMinutesWatched',
  dimensions: 'day',
);

for (final header in report.columnHeaders) {
  print('${header.name} (${header.dataType})');
}

// List analytics groups
final groups = await yt.analytics.groupsList(mine: true);
for (final group in groups.items) {
  print('${group.id}: ${group.snippet.title}');
}

Activities

final yt = Yt.withKey('[your api key]');

// List recent channel activities
final activities = await yt.activities.list(
  channelId: 'UC_x5XG1OV2P6uZZ5FSM9Ttw',
  maxResults: 10,
);

for (final activity in activities.items) {
  print('${activity.snippet?.type}: ${activity.snippet?.title}');
}
final yt = await Yt.withOAuth();

// List my recent activities
final myActivities = await yt.activities.list(
  mine: true,
  maxResults: 20,
);

for (final activity in myActivities.items) {
  print('${activity.snippet?.publishedAt}: ${activity.snippet?.title}');
}

Flutter Integration

This package has no Flutter dependencies and works on all platforms. To authenticate with a user's own YouTube account, implement a TokenGenerator:

import 'package:google_sign_in/google_sign_in.dart';
import 'package:yt/yt.dart';

class YtLoginGenerator implements TokenGenerator {
  final GoogleSignIn _googleSignIn = GoogleSignIn(
    scopes: ['https://www.googleapis.com/auth/youtube'],
  );

  @override
  Future<Token> generate() async {
    var _currentUser = await _googleSignIn.signInSilently();
    if (_currentUser == null) _currentUser = await _googleSignIn.signIn();
    final token = (await _currentUser!.authentication).accessToken;
    if (token == null) throw Exception();
    return Token(
        accessToken: token, expiresIn: 3599, scope: null, tokenType: '');
  }
}

Then in your Flutter app:

late final Yt yt;

void _init() async {
  yt = await Yt.withGenerator(YtLoginGenerator());
}

void _getPlaylists() async {
  setState(() {
    items.addAll(await yt.playlists.list(mine: true));
  });
}

See Usage within Flutter for google_sign_in setup requirements.

Documentation

Contributing

Any help from the open-source community is always welcome and needed:

  • Found an issue? Please fill a bug report with details.
  • Need a feature? Open a feature request with use cases.
  • Are you a developer? Fix a bug, implement a new feature, or improve tests — send a pull request.
  • Are you using and liking the project? Promote it, or let me know and I'll cross-link your project.

If you donate 1 hour of your time, you can contribute a lot, because others will do the same — just be part and start with your 1 hour.

License

MIT — see the LICENSE file for details.

Libraries

meta
app metadata
oauth
oauth related classes for io versus browser usage
yt
The YouTube Live Streaming API reference explains how to schedule live broadcasts and video streams on YouTube using the YouTube Live Streaming API.