Last updated: February 5, 2025

<span aria-hidden="true" id="export-files-to-youtube-in-net-c-using-open-source-libraries"></span>

# Export files to YouTube in .Net C# using open source libraries

![Tim Koschützki](/assets/images/teammates/avatar-tim-kos-1.jpg?dpl=dpl_B2d4XACVUtA1h8m6kRxZhWsda77Q)

#### Tim Koschützki

Co-founder · Berlin, Germany · Show bio

[](https://x.com/tim%5Fkos)[](https://github.com/tim-kos)

Exporting videos to YouTube programmatically is essential for automating video content management. Although YouTube offers an official .NET client library, leveraging direct REST API integration using open source libraries can give you greater control and flexibility. In this guide, we demonstrate how to export files to YouTube in .NET C# using the Google APIs client library, updated asynchronous authentication, and robust error handling practices.

<span aria-hidden="true" id="prerequisites"></span>

## Prerequisites

* .NET 6.0 or later
* Google Cloud Project with YouTube Data API enabled
* OAuth 2.0 credentials from Google Cloud Console (download your client\_secrets.json file)
* Google.Apis.YouTube.v3 NuGet package

<span aria-hidden="true" id="setting-up-the-youtube-api-client"></span>

## Setting up the YouTube API client

First, install the required NuGet package:

```shell
dotnet add package Google.Apis.YouTube.v3

```

Use the following asynchronous factory method to create a YouTube service instance. This approach leverages the official GoogleCredential class for OAuth 2.0 authentication:

```csharp
using Google.Apis.Auth.OAuth2;
using Google.Apis.Services;
using Google.Apis.Upload;
using Google.Apis.YouTube.v3;
using System.Threading;
using System.Threading.Tasks;

public class YouTubeUploader
{
    private readonly YouTubeService _youtubeService;

    private YouTubeUploader(YouTubeService youtubeService)
    {
        _youtubeService = youtubeService;
    }

    public static async Task<YouTubeUploader> CreateAsync(string credentialsPath)
    {
        var credential = await GoogleCredential.FromFileAsync(credentialsPath, CancellationToken.None)
            .ConfigureAwait(false);
        credential = credential.CreateScoped(YouTubeService.Scope.YoutubeUpload);

        var youtubeService = new YouTubeService(new BaseClientService.Initializer
        {
            HttpClientInitializer = credential,
            ApplicationName = "YOUR_APP_NAME"
        });

        return new YouTubeUploader(youtubeService);
    }
}

```

<span aria-hidden="true" id="uploading-videos"></span>

## Uploading videos

The method below handles video uploads with progress tracking and comprehensive error handling:

```csharp
using System;
using System.IO;
using System.Threading.Tasks;
using Google.Apis.Upload;
using Google.Apis.YouTube.v3;
using Google.Apis.YouTube.v3.Data;

public async Task<string> UploadVideoAsync(
    string filePath,
    string title,
    string description,
    string[] tags,
    IProgress<IUploadProgress> progress = null)
{
    var video = new Video
    {
        Snippet = new VideoSnippet
        {
            Title = title,
            Description = description,
            Tags = tags,
            CategoryId = "22" // People & Blogs category
        },
        Status = new VideoStatus
        {
            PrivacyStatus = "private" // or "public", "unlisted"
        }
    };

    using var fileStream = new FileStream(filePath, FileMode.Open);
    var videosInsertRequest = _youtubeService.Videos.Insert(
        video,
        "snippet,status",
        fileStream,
        "video/*");

    videosInsertRequest.ChunkSize = ResumableUpload.MinimumChunkSize;

    if (progress != null)
    {
        videosInsertRequest.ProgressChanged += progress.Report;
    }

    try
    {
        var uploadResponse = await videosInsertRequest.UploadAsync();
        if (uploadResponse.Status == UploadStatus.Completed)
        {
            return videosInsertRequest.ResponseBody.Id;
        }
        else
        {
            throw new Exception($"Upload failed with status: {uploadResponse.Status}");
        }
    }
    catch (Google.GoogleApiException ex) when (ex.Error != null &&
             (ex.Error.Code == 403 || ex.Error.Code == 429 || ex.Error.Code == 503))
    {
        throw new Exception("Quota exceeded, rate limit reached, or authentication error. Please check your API credentials and quota usage.", ex);
    }
    catch (Exception ex)
    {
        throw new Exception("Upload failed: " + ex.Message, ex);
    }
}

```

<span aria-hidden="true" id="handling-quotas-and-rate-limits"></span>

## Handling quotas and rate limits

YouTube Data API enforces quota limits to ensure fair usage. For example, a free account typically has a daily limit of 10,000 units, and each video upload costs approximately 1,600 units. In production, be sure to implement quota tracking and rate limiting to avoid exceeding your daily quota. If necessary, you can request a quota increase from Google Cloud.

```csharp
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

public class QuotaManager
{
    private readonly SemaphoreSlim _uploadSemaphore;
    private readonly Dictionary<DateTime, int> _quotaUsage;

    public QuotaManager(int maxConcurrentUploads = 3)
    {
        _uploadSemaphore = new SemaphoreSlim(maxConcurrentUploads);
        _quotaUsage = new Dictionary<DateTime, int>();
    }

    public async Task<T> ExecuteWithQuotaAsync<T>(
        Func<Task<T>> operation,
        int quotaCost)
    {
        await _uploadSemaphore.WaitAsync();
        try
        {
            var today = DateTime.UtcNow.Date;
            if (!_quotaUsage.ContainsKey(today))
            {
                _quotaUsage.Clear();
                _quotaUsage[today] = 0;
            }

            if (_quotaUsage[today] + quotaCost > 10000)
            {
                throw new QuotaExceededException("Daily quota would be exceeded");
            }

            var result = await operation();
            _quotaUsage[today] += quotaCost;
            return result;
        }
        finally
        {
            _uploadSemaphore.Release();
        }
    }
}

```

<span aria-hidden="true" id="best-practices-for-production-use"></span>

## Best practices for production use

* Implement retry logic with exponential backoff to handle transient errors such as network issues or temporary rate limits.
* Store your credentials securely to protect your OAuth 2.0 secrets.
* Monitor upload progress to give feedback and troubleshoot issues in real time.
* Ensure robust error handling to cover quota exceedance, authentication failures, and file size or network constraints.

<span aria-hidden="true" id="implement-retry-logic"></span>

### Implement retry logic

```csharp
using System;
using System.Net.Http;
using System.Threading.Tasks;

public async Task<T> RetryWithExponentialBackoff<T>(
    Func<Task<T>> operation,
    int maxAttempts = 3)
{
    for (int attempt = 1; attempt <= maxAttempts; attempt++)
    {
        try
        {
            return await operation();
        }
        catch (Exception ex) when (IsTransientException(ex))
        {
            if (attempt == maxAttempts) throw;
            var delay = TimeSpan.FromSeconds(Math.Pow(2, attempt));
            await Task.Delay(delay);
        }
    }

    throw new Exception("Retry attempts exhausted");
}

private bool IsTransientException(Exception ex)
{
    return ex is HttpRequestException ||
           (ex is GoogleApiException gex && (gex.Error?.Code == 429 || gex.Error?.Code == 503));
}

```

<span aria-hidden="true" id="store-credentials-securely"></span>

### Store credentials securely

```csharp
using System;

public class SecureCredentialManager
{
    private readonly IConfiguration _configuration;

    public SecureCredentialManager(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    public string GetCredentialsPath()
    {
        var path = _configuration.GetValue<string>("YouTube:CredentialsPath");
        if (string.IsNullOrEmpty(path))
        {
            throw new InvalidOperationException("YouTube credentials path not configured");
        }
        return path;
    }
}

```

<span aria-hidden="true" id="monitor-upload-progress"></span>

### Monitor upload progress

```csharp
using Google.Apis.Upload;

public class UploadProgressHandler : IProgress<IUploadProgress>
{
    private readonly ILogger _logger;

    public UploadProgressHandler(ILogger logger)
    {
        _logger = logger;
    }

    public void Report(IUploadProgress progress)
    {
        var status = progress.Status switch
        {
            UploadStatus.Uploading => $"Uploading: {progress.BytesSent}/{progress.TotalBytes} bytes",
            UploadStatus.Failed => $"Upload failed: {progress.Exception?.Message}",
            UploadStatus.Completed => "Upload completed",
            _ => $"Status: {progress.Status}"
        };

        _logger.LogInformation(status);
    }
}

```

<span aria-hidden="true" id="conclusion"></span>

## Conclusion

Exporting files to YouTube in .NET C# requires up-to-date authentication practices, careful quota management, and robust error handling. By integrating the Google APIs client library with asynchronous credential loading and following best practices for production deployments, you can build a resilient video upload solution. For a more streamlined approach to handling file exports and video processing at scale, consider using[Transloadit's file exporting service](/services/file-exporting.md).

\#file-exporting-service#dotnet#csharp#api-integration

### 👩‍💻 Join 20k+ developers

Sign up for our [monthly newsletter](/newsletters.md) to receive direct links to 3 exclusive tech — and 2 product updates. No less, no more.

Your email:

Get access

## File uploading and encoding. Made simple.

Transloadit streamlines file handling for developers, trusted by brands like Coursera and The New York Times. We’re known for a reliable API, top-notch support, and a strong commitment to open source, with projects like [Uppy⁠](https://uppy.io) and [Tus⁠](https://tus.io) setting standards in file processing.

[Sign up](/c/)[Book a Demo](https://survey.typeform.com/to/kRg47Xi5)

No credit card needed · 5 GB included in the free plan

Cancel anytime
