YouTube API Tutorial in C#: Upload, Search & Manage Playlists

YouTube API C# guide

Did you know that over 500 hours of video are uploaded to YouTube every single minute, and you can automate every second of it from your C# application? In this hands‑on guide I’ll walk you through every step—from the very first “Hello, YouTube!” request all the way to publishing videos, building playlists, and squeezing every millisecond of performance out of Google’s Data API v3. Grab a coffee (or three), fire up Visual Studio, and let’s make your app a YouTube power‑studio!

Prerequisites

Before we touch a line of code, make sure you have:

  • Google account with two‑factor enabled (better security = happier subscribers).
  • Visual Studio 2022/2025 (Community is fine) or VS Code with the .NET 8 SDK.
  • NuGet access – we’ll pull in Google.Apis.YouTube.v3 and friends.
  • Basic C# knowledge (async/await, dependency injection, a healthy respect for exceptions).

Setting Up Your YouTube API Project

YouTube API Quick-Start Checklist
  1. Create a project in Google Cloud Console.
  2. Enable YouTube Data API v3 (and only v3—v2 retired in 2015).
  3. Configure OAuth 2.0 Consent Screen → External → Add scopes .../auth/youtube and .../auth/youtube.upload.
  4. Create credentials
    • OAuth Client ID (Desktop) for full user access.
    • API Key for no‑auth read‑only demos.
  5. Download credentials.json and stash it outside version control.

Tip: Add your dev redirect URI as http://localhost:8080/, then use Google’s built‑in local server callback—zero plumbing!

Set Up Your C# Project

# Create solution & console project
 dotnet new sln -n YoutubeApiLab
 dotnet new console -n YoutubeApiLab.App -f net8.0
 dotnet sln YoutubeApiLab.sln add YoutubeApiLab.App

# Add Google client libraries
 dotnet add YoutubeApiLab.App package Google.Apis.YouTube.v3
 dotnet add YoutubeApiLab.App package Google.Apis.Auth
 dotnet add YoutubeApiLab.App package Google.Apis.OAuth2.v2

Now wire up a tiny helper to centralize the service creation:

public static class YoutubeServiceFactory
{
    public static async Task<YouTubeService> CreateAsync(CancellationToken ct)
    {
        using var stream = new FileStream("credentials.json", FileMode.Open, FileAccess.Read);

        var cred = await GoogleWebAuthorizationBroker.AuthorizeAsync(
            GoogleClientSecrets.FromStream(stream).Secrets,
            new[] { YouTubeService.Scope.Youtube, YouTubeService.Scope.YoutubeUpload },
            "my-youtube-app", ct, new FileDataStore("token_cache", true));

        return new YouTubeService(new BaseClientService.Initializer
        {
            HttpClientInitializer = cred,
            ApplicationName = "YouTube API Lab"
        });
    }
}

Authenticating with the YouTube API

OAuth 2.0

OAuth sounds scary; in practice it’s just three objects:

var yt = await YoutubeServiceFactory.CreateAsync(ct);
Console.WriteLine($"Authenticated as: {yt.HttpClientInitializer?.UserId}");

The first run pops a browser window; subsequent runs reuse the token from FileDataStore. Keep those refresh tokens safe—move them to secure storage before production.

Service Accounts?

Service accounts can’t upload public videos (only to channels linked via CMS). Stick to OAuth if you’re controlling a regular channel.

Retrieving Video Data

Need the latest views count on your viral cat video?

var request = yt.Videos.List("snippet,statistics,contentDetails");
request.Id = "dQw4w9WgXcQ"; // never gona give...
var response = await request.ExecuteAsync(ct);
var video = response.Items.First();
Console.WriteLine($"{video.Snippet.Title} has {video.Statistics.ViewCount} views");

Pagination & Partial Responses

Always set MaxResults ≤ 50 and request only the fields you need (fields parameter) to conserve quota.

Uploading Videos

Resumable Upload Timeline

Uploading is where quotas bite. Use resumable uploads and keep chunks smallish (5 MB):

var file = new FileInfo("my_clip.mp4");
var video = new Video
{
    Snippet = new VideoSnippet
    {
        Title = "🎉 API Demo Upload",
        Description = "Uploaded via Google.Apis.YouTube.v3 – sample code",
        Tags = new[] { "csharp", "youtube api", "demo" },
        CategoryId = "28" // Science & Technology
    },
    Status = new VideoStatus { PrivacyStatus = "private" }
};

using var fs = file.OpenRead();
var insert = yt.Videos.Insert(video, "snippet,status", fs, "video/*");
insert.ChunkSize = ResumableUpload.MinimumChunkSize;
insert.ProgressChanged += progress =>
{
    Console.WriteLine($"{progress.BytesSent / 1024 / 1024} MB sent – {progress.Status}");
};
var result = await insert.UploadAsync(ct);
Console.WriteLine($"New video id = {result.Id}");

Heads‑up: uploads can time‑out on spotty networks. Catch GoogleApiException, inspect Errors[0].Reason, and ResumeAsync() the upload.

Managing Playlists

// 1) Create playlist
var playlist = await yt.Playlists.Insert(new Playlist
{
    Snippet = new PlaylistSnippet { Title = "API Best Of" },
    Status  = new PlaylistStatus  { PrivacyStatus = "public" }
}, "snippet,status").ExecuteAsync(ct);

// 2) Add a video
await yt.PlaylistItems.Insert(new PlaylistItem
{
    Snippet = new PlaylistItemSnippet
    {
        PlaylistId = playlist.Id,
        ResourceId = new ResourceId { Kind = "youtube#video", VideoId = "dQw4w9WgXcQ" }
    }
}, "snippet").ExecuteAsync(ct);

Remember to batch operations where possible using BatchRequest—one HTTP call, many mutations.

Implementing Video Search

var search = yt.Search.List("snippet");
search.Q = "dotnet 9 release";
search.Type = "video";
search.PublishedAfter = DateTime.UtcNow.AddMonths(-1);
search.Order = SearchResource.ListRequest.OrderEnum.ViewCount;
search.MaxResults = 10;

var searchResponse = await search.ExecuteAsync(ct);
foreach (var item in searchResponse.Items)
{
    Console.WriteLine($"{item.Snippet.Title} – {item.Id.VideoId}");
}

Combine search results with a second Videos.List call to fetch stats in bulk (pass comma‑joined video IDs). This uses two quota units instead of ten.

Handling Error Responses

  • quotaExceeded – You’ve hit daily 10 000‑unit limit. Reduce fields, cache responses, or request a higher quota in Cloud Console.
  • invalidParameter – Double‑check enum values; “publick” is not a privacy status (I’ve typed that… twice).
  • forbidden / videoAbuseReportRejected – Channel policy or content violation. No code fix—review Community Guidelines.
  • Network hiccups – use exponential back‑off: wait 1 s → 2 s → 4 s, capping at 32 s.

Quick helper:

static async Task<T> Retry<T>(Func<Task<T>> action, int retries = 5)
{
    for (var i = 0; i < retries; i++)
    {
        try { return await action(); }
        catch (GoogleApiException ex) when (ex.HttpStatusCode >= HttpStatusCode.InternalServerError)
        {
            await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, i)));
        }
    }
    throw new Exception("Max retries exceeded");
}

Best Practices for Performance & Security

Quota, Performance, Security, User Experience
GoalDoAvoid
Lower quota usageRequest partial fields (fields=items(id,snippet/title)), batch requestsRepeated Videos.List per ID
Faster UXCache responses in Redis with ETagsPolling every page load
Secure tokensEncrypt token_cache with DPAPI or Azure Key VaultStoring refresh tokens in plain JSON
Scalable uploadsOff‑load to background worker, show progressBlocking UI thread

Finally, document every scope you request in onboarding—privacy‑savvy users will thank you.

FAQ: Rapid‑Fire Answers for Busy Devs

Can I use an API key instead of OAuth for uploads?

No. API keys are read‑only. Uploads require user‑granted OAuth scope.

How do I get more quota?

Fill the “quota extension” form in Cloud Console after you have a working app and analytics showing real demand.

Does the API support live streaming?

Yes—via the YouTube Live Streaming API. Same auth, different service class.

Why is my video still processing after upload?

YouTube transcodes in the background. Poll Videos.List(part="processingDetails") until ProcessingStatus == succeeded.

How can I move my app to production securely?

Switch to a verified OAuth screen, restrict credentials by SHA‑1 fingerprint, encrypt refresh tokens, and monitor usage with Stackdriver.

Conclusion: Your First Million Views Starts Here

You’ve learned how to authenticate, fetch analytics, upload content, manage playlists, search smartly, and guard against the quota monster—all from clean, modern C# code. Now it’s your turn: clone a repo, wire up those credentials, and let your application become the next backstage manager of your YouTube empire. I’d love to hear what you build—drop a comment below and let’s chat!

Leave a Reply

Your email address will not be published. Required fields are marked *