Tag: Download youtube erlang

Download Youtube video

January 11, 2009

How to download Youtube videos has been done by a number of bloggers in a number of languages. I just wanted to try it out myself in Erlang, but I had no idea where to start.

Now that I’ve decided to start, let me grab an Eddie Vedder song from Youtube:


And lets sniff the HTTP traffic using Wireshark to see what actually happens when we watch a Youtube video. The browser made a conection to Youtube and before it started streaming the video, the input URL got redirected to a different Youtube URL (Depending on whether Youtube is caching the video or not, it could in turn probably be redirected to a different Cache server or a different IP):

No.     Time        Source                Destination           Protocol Info
     96 3.295105    xx.xx.xx.xx        HTTP     GET /get_video?video_id=gct6BB6ijcw&t=OEgsToPDskJ6n06uQXzbbyp7xAnxK6pN&el=detailpage&ps= HTTP/1.1

No.     Time        Source                Destination           Protocol Info
    115 3.879454    xx.xx.xx.xx         HTTP     GET /get_video?origin=lax-v113.lax.youtube.com&video_id=gct6BB6ijcw&ip=xx.xx.xx.xx&region=0&signature=587F68CED7B14F380192AAB1D58942F0EAB9AE7B.6379C474E29D2B2348E1A69954D7FACFC461F964&sver=2&expire=1231731436&key=yt4&ipbits=0 HTTP/1.1

Upon playing with the new URL in the browser, I realized that the URL that Youtube gets the video from is


The param “video_id” is the same as the param “v” in the original URL. So we only need to find the value for the param “t”.
Lets look at the HTML source for


and see if it contains the value for the parameter “t”. Luckily, grepping for “&t=”, I found this in the source:


The value of “t” in the HTML source and the value of “t” in the redirect URL is different, but I found that both values of “t” seemed to work when appended to the URL. Oh well, I tried it again just to make sure and realized that the value of the parameter “t” changes for every request, but all values seem to work(Probably it is timestamp dependent!).

So we have a plan now:
1. Get a Youtube video URL and make a HTTP request to it.
2. Get the body of the reponse and find the value of “t” using regex pattern matching.
3. Generate the proper redirect URL using the two parameters “video_id” and “t”.
4. Make a http request to the new URL and stream the bytes and write to a file with “.flv” extension.

Here is the full source code in Erlang: 


download(URL) ->
    {ok, {_Status, _Header, Body}} = http:request(URL),
    Video_URL = get_video_download_url(URL, Body),

stream_video(Video_URL) ->
    io:format("Downloading video from ~p~n", [Video_URL]),
    {ok, {_Status, _Header, Body}} = http:request(Video_URL),
    file:write_file("myvideo.flv", Body),
    io:format("Download complete!").

get_video_download_url(URL, Body) ->
    Matcher = "&t=[A-Za-z0-9-_]*",
    {match, Start, Length} = regexp:first_match(Body, Matcher),
    T = string:substr(Body, Start, Length),
    {ok, New, _No} = regexp:sub(URL, "watch\?v=", "get_video?video_id="),
    New ++ T.

Lets run it from the Erlang shell:

1> c(video_downloader.erl).
2> inets:start().
3> video_downloader:download("http://www.youtube.com/watch?v=gct6BB6ijcw").
Downloading video from "http://www.youtube.com/get_video?video_id=gct6BB6ijcw&t
Download complete!ok

Go to your current directory and use any Flv Viewer to see if the downloaded file is a working video or convert it to format of your choice and watch it offline.

I would love to give an Erlang twist to it by spawning a few concurrent processes to download videos, but this is not quite a good example to do it from by localbox – too much of Disk IO, Network IO and slow Internet connection.