Programmatically Uploading Videos to YouTube

YouTube Icon
YouTube recently updated their API with some new features. YouTube is now using the GoogleData API instead of a proprietary API. One of the new features is the ability to upload videos via the API. This means that web sites and client applications now have the ability to upload videos directly to YouTube.

I’ve been playing around with the YouTube API upload feature and have a quick and dirty little C# class library that can upload videos straight to YouTube via the API.

Before you can upload a video you have to get an authorization code using your YouTube username and password. The code is then used in the call that actually uploads the video.

The Authorize method of the YouTube library performs the authentication.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public bool Authorize(string username, string password)
{
    bool result = false;
    this.username = username;
    this.password = password;
 
    using (WebClient client = new WebClient())
    {
        // Send the requeset with username and password
        client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
        string response = client.UploadString(
            "https://www.google.com/youtube/accounts/ClientLogin",
            string.Format("Email={0}&Passwd={1}&service=youtube&source=TrailsintheSand.YouTube.Library",
                username, password));
 
        // The response is plain text containing:
        // Auth=<authorization code>
        string[] split = response.Split('\n');
        foreach (string s in split)
        {
            string[] nvsplit = s.Split('=');
            if (nvsplit.Length == 2)
            {
                if (nvsplit[0] == "Auth")
                {
                    authCode = nvsplit[1];
                    result = true;
                }
            }
        }
    }
 
    return result;
}

This simple method uses the WebClient class. WebClient is the simplest way to perform an HTTP request in .NET. The UploadString method of the WebClient class is used because we need to POST the username and password to the server. The response that comes back contains the string “Auth=“. This method parses the authorization code out of the response and stores it for later use.

The Upload method is passed several parameters including the title of the video, a description of the video, the video’s category, a list of keywords and the path to the video on the local hard drive.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
public bool Upload(string title, string description, Catagory catagory,
              string keywords, string videoFileName, out string error)
{
    bool result = false;
    error = null;
 
    // Build byte arrays for the header file and footer
    byte[] header = Encoding.UTF8.GetBytes(GetHeader(title, description, catagory, keywords, videoFileName));
    byte[] file = File.ReadAllBytes(videoFileName);
    byte[] footer = Encoding.UTF8.GetBytes(lineTerm + boundary + "--");
 
    // Combine the byte arrays into one big byte array
    byte[] data = new byte[header.Length + file.Length + footer.Length];
    Array.Copy(header, 0, data, 0, header.Length);
    Array.Copy(file, 0, data, header.Length, file.Length);
    Array.Copy(footer, 0, data, header.Length + file.Length, footer.Length);
 
    // Using a HttpWebRequest here because it allows us to control the timeout
    HttpWebRequest req = (HttpWebRequest)WebRequest
        .Create(string.Format("http://uploads.gdata.youtube.com/feeds/api/users/{0}/uploads",
                username));
    req.Method = "POST";
    req.ContentType = string.Format("multipart/related; boundary={0};", boundaryheader);
    req.ContentLength = data.Length;
    req.Timeout = timeout;
    req.Headers.Add("Authorization", "GoogleLogin auth=" + authCode);
    req.Headers.Add("X-GData-Client", clientCode); // supposed to be optional
    req.Headers.Add("X-GData-Key", devCode);
    req.Headers.Add("Slug", Path.GetFileName(videoFileName));
 
    using (Stream postStream = req.GetRequestStream())
    {
        // Send the data to the server
        postStream.WriteTimeout = timeout;
        postStream.Write(data, 0, data.Length);
        postStream.Close();
 
        try
        {
            // Get the response back from the server
            WebResponse webResponse = req.GetResponse();
            using (Stream responseStream = webResponse.GetResponseStream())
            {
                using (StreamReader reader = new StreamReader(responseStream))
                {
                    // Should check the response here
                    reader.Close();
                    result = true;
                }
 
                responseStream.Close();
            }
 
            webResponse.Close();
        }
        catch (WebException ex)
        {
            // Got a bad response
            using (StreamReader sr = new StreamReader(ex.Response.GetResponseStream()))
            {
                error = sr.ReadToEnd();
            }
        }
    }
 
    return result;
}

Upload builds the content of the HTTP POST. The content is of type multipart/related meaning there will be more than one part and the parts are related. In the case of a YouTube video upload there are two parts. The first part contains an XML document describing the video. It contains the title, description, category, keywords and file name. The Upload method calls the GetHeader method to get a string that contains both the HTTP headers for the parts of the content and the XML data for the video.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private string GetHeader(string title, string description, Catagory catagory,
                         string keywords, string videoFileName)
{
    StringBuilder xml = new StringBuilder();
    xml.Append(boundary + lineTerm + "Content-Type: application/atom+xml; charset=UTF-8" + lineTerm + lineTerm);
    xml.Append("<?xml version=\"1.0\"?><entry xmlns=\"http://www.w3.org/2005/Atom\" ");
    xml.Append("xmlns:media=\"http://search.yahoo.com/mrss/\" xmlns:yt=\"http://gdata.youtube.com/schemas/2007\">");
    xml.AppendFormat("<media:group><media:title type=\"plain\">{0}</media:title>", title);
    xml.AppendFormat("<media:description type=\"plain\">{0}</media:description>", description);
    xml.AppendFormat("<media:category scheme=\"http://gdata.youtube.com/schemas/2007/categories.cat\">{0}</media:category>", catagory);
    xml.AppendFormat("<media:keywords>{0}</media:keywords>", keywords);
    xml.Append("</media:group></entry>" + lineTerm);
    xml.Append(boundary + lineTerm + "Content-Type: video/*" + lineTerm + "Content-Transfer-Encoding: binary" + lineTerm + lineTerm);
    return xml.ToString();
}

GetHeader simply uses a StringBuilder to build the header data containing the XML. It would probably be better to use an XmlWriter or XmlDocument to build the XML part of this data.

The Upload method then builds a byte array containing the entire content of the POST which includes the raw data for the video to be uploaded. The File.ReadAllBytes method is used to load the video into a byte array.

The HttpWebRequest class is used to POST the video to YouTube. This class is used instead of the simple WebClient because we need to be able to set the timeout for the POST. Since video files can be very large it may take longer than the default timeout for a WebClient request and the WebClient timeout cannot be changed.

Here is an example of using the class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Trails.YouTube youTube = new Trails.YouTube();
Console.WriteLine("Authorizing...");
if(youTube.Authorize("youtube username", "youtube password"))
{
    Console.WriteLine("Authorized");
    Console.WriteLine("Uploading...");
    string error;
    if (youTube.Upload("Test Video", "This is a test", YouTube.Catagory.Howto, "test", @"c:\test.mp4", out error))
    {
        Console.WriteLine("Upload complete");
    }
    else
    {
        Console.WriteLine("Upload failed: {0}", error);
    }
}
else
{
    Console.WriteLine("Authorization failed");
}

Using the GoogleData API requires you to have a developer key. Go to the Google YouTube API web page to request a developer key. The library contains two constants named clientCode and devCode. Set devCode to the developer key you got from Google. You will also get a Client ID with your developer key. Set the clientCode constant to the client ID you received.

As you can see it is very easy to upload a video to YouTube from your application. The class has some room for improvement but serves as an example of how to upload videos directly to YouTube. For instance, the Upload method is not checking the response after an upload. A successful upload will return a list of uploaded videos for the YouTube account being used.

Here is the Visual Studio 2005 project with all of the source code.
Trails in the Sand YouTube Library

Enjoy!

Share and Enjoy:
  • StumbleUpon
  • Digg
  • Reddit
  • del.icio.us
  • Suggest to Techmeme via Twitter
  • Technorati
  • Slashdot
  • HackerNews
  • Twitter
  • Facebook
  • Print
You can leave a response, or trackback from your own site.

35 Responses to “Programmatically Uploading Videos to YouTube”

  1. [...] speaks the GData XML format and querying YouTube with C# is fairly simple from there. You can even upload videos programmatically to YouTube like this [...]

  2. [...] speaks the GData XML format and querying YouTube with C# is fairly simple from there. You can even upload videos programmatically to YouTube like this [...]

  3. Tony says:

    I plan on playing around with this code this weekend.

    There’s one thing I wanted to let you know though. Catagory is misspelled. It should be Category (with an ‘e’). :)

    Cheers.

  4. rajender says:

    i use your helping code but where i can get YouTube.Catagory

  5. rajender says:

    hi i used your code but it threw exceptiom

    403

    help me ASAP i m not sure video is upload or not

  6. Ernes says:

    Video uploads succesfully, but there is any way to know the url of the uploaded video, or the code generated? i.e:

    http://www.youtube.com/watch?v=aOfeI3gmNGw

    aOfeI3gmNGw <—– that thing

    Thank you very much

  7. Ernes says:

    well, finally i can know, in the webresponse header is the generated code
    thanks anyway

  8. Arsen Yeremin says:

    Did you get the auth issue resolved with c# youtube upload?

  9. Arsen Yeremin says:

    Problem solved by

    http://uploads.gdata.youtube.com/feeds/api/users/{0}/uploads",

    with


    http://uploads.gdata.youtube.com/feeds/api/users/default/uploads",

    A this point the original problem may be a non-issue, since google has notified me that they they had authentication problems around the time I was working on this.

  10. Peter says:

    How to i get the url for the vieo to show on ahtml page?

  11. Peter says:

    How to i get the url for the video to show on a html page?

  12. Ernes says:

    try this… the ID of the video is in the WebResponse headers. You need to split the content of the header, and then, you have the code…

    string s1 = objWebResponse.Headers.ToString();

    string[] sep = s1.Split(‘/’);

    string s2 = sep[8].ToString();

    string[] sep2 = s2.Split(‘?’);

    string url = sep2[0].ToString();

    result = “http://www.youtube.com/watch?v=” + url;

  13. Peter says:

    Thank you very much i´ll have a go at it today.

  14. Ohad Kless says:

    Hi,
    Do you have any way to add progress bar to show upload progress?

    Thanks!
    Ohad Kless

  15. Aqil says:

    Hi everyone,
    is there any way of playing the youtube video in C# application by writing youtube url.

  16. shawn says:

    change

    req.Headers.Add(“X-GData-Key”, devCode)

    to

    req.Headers.Add(“X-GData-Key”, “key=” + devCode)

  17. tam dang says:

    thanks you. but I can not see my video i just load.

  18. z0ro says:

    Thanks ,
    I was looking for this Sample more then a week
    You Really helped me.

  19. venkatesh says:

    i can able to upload the video file with the extention .wmv but i cant able to upload the video file with the extention .flv. can any one help me what to do in the upload function or coding..

    Thanks in Advance..
    By.
    s.venkatesh

  20. prabhu says:

    hi,I am getting Token invalid – Invalid AuthSub token.401 .I am calling authorize method first and getting auhorized and then calling uploading method.In the response of uploading method..i am getting Token invalid – Invalid AuthSub token.401 in the catch.
    kindly assisst me.

  21. Asad Siddiqi says:

    I got the developer key and no client code with a note that it is no longer required. So i commented that out.

    I changed the username to my email address and the API authorized me. I changed the developer key in the code. When I m trying to upload I get a “Service Forbidden 403″ Exception. Can you help me out ? This is urgent and I would really appreciate your reply. Thanks

  22. Asad Siddiqi says:

    I resolved the issue using my sign in email for authentication and username with the request. Is there a url or video id in the response where I can see the uploaded video ?

  23. Asad Siddiqi says:

    This does not work with ASP.Net web forms and the error returned is “Service Forbidden 403″

  24. nicola says:

    hello there!
    for 1 months that code in my c# applications worked very very well… now it dosent work… 5 days ago..
    i dont change nothing.. can u help me?
    change something on utube or google process??

    result : authoritazion failed
    but by browser i can access on my utube channel..

    can u try it on your app??
    thank you very much
    nicola

  25. nicola says:

    if i put my google/utube account its works!
    user=email address and pwd=password

    and with email the authentification is ok.
    but the upload file failed. error: service forbidden

    ???
    thanks
    nicola

  26. nicola says:

    hello Asad Siddiqi!
    me too.. the same error..
    authentication ok with email address..
    but i cant upload file.. service forbidden..

    have u got the solution?
    thanks
    nicola

  27. yagnesh says:

    Hello Friends,

    Greetings

    I am new to Youtube API use. I am developing my application in .Net
    (ASP .Net/C#). I am facing issue as below.
    I am trying to post comment for the video that are being uploaded by
    users. My code is working fine and it’s not throwing any error.
    However i am not able to view comment in the youtube.com against the
    video.
    My code is as below.
    =======================================

    YouTubeRequestSettings settings = new
    YouTubeRequestSettings(“ApplicationName”,
    “AI39si53ltlNkiaLm1P1OAJjuIFNk-IUNsrpO6JowqAKxJ1z4NPXa1Dm8X3vwdSBFGV-
    tXUdQa7aQ”);

    YouTubeRequest request = new YouTubeRequest(settings);

    Comment c = new Comment();

    c.Content = “Test Comments”;

    Video newVideo = new Video();

    newVideo.VideoId = “Hnz5avWae70″;

    request.AddComment(newVideo, c);

    =======================================

    Please let me know what i am doing wrong. Do any one have idea what i
    am doing wrong?

    Thanks,
    Yagnesh

  28. Ashish says:

    Program is not working .
    please help me give correct solution file.

  29. Vlad says:

    Hello,
    Very useful code, but there is a problem.
    This does not work with private proxies (ip/port and username password).

    I create a new WebProxy and assign it to request.Proxy . But that does not work correctly :(

    Any ideas ?

  30. Swapna says:

    Thanks a lot…..I have been trying from 10 hrs to upload videos….This sample solved my problem in 15 mins…..

  31. Swapna says:

    This is vry useful….Thnx a lot….

  32. Ron says:

    How can you make it so it shows your upload progress?

  33. Ron says:

    How can I make an update details application

  34. Swapna says:

    It is a vry gud example.

    But when I am trying to upload files of size greater than 150MB , I am getting error message as :

    “An operation on a socket could not be performed because the system lacked sufficient buffer space…..”

    Kindly please someone help me on this….

  35. Amila says:

    Hi All,

    Has anyone tried to access the youtube inbox using YouTube Data API. I can access the inbox, but it only shows the Shared Video messages. Does anyone know how to retrieve my private inbox. I don’t want to send private messages, but I need to retrieve my complete inbox.

    Any help appreciated,

    Cheers,
    Amila

Leave a Reply

*