youtube video downloader in vbscriptWhen I was a small kid I liked RAD (Rapid Application Development) in Microsoft® Visual Basic® programming language. I mastered the language entirely from MSDN's samples and it was such a joy to create GUI applications in a few hours or days and they just worked! Now it has been a few years years since I have not touched Visual Basic and I have become really rusty in this language.

If you have been reading my blog, you might have noticed that I have been creating these YouTube video downloaders in various programming languages. I have no plans to create a downloader in Visual Basic itself, because I am creating a GUI downloader in C and C++ already but I would like to use a derived language (a subset of Visual Basic language), VBScript, to create the downloader.

That would refresh my knowledge of Visual Basic a little and also let me learn a little more about programming Windows Script Host (WSH).

Here is a quote from a really good introduction to what WSH is:

The first time people encounter Windows Script Host, they often express some confusion. What exactly is WSH? Is it a language, like VBScript or JScript? No; although WSH enables you to run programs written in these languages, it is not a language itself. WSH is a script host. A script host is a program that provides an environment in which users can execute scripts in a variety of languages, languages that use a variety of object models to perform tasks.

You are probably already familiar with other script hosts. Microsoft® Internet Explorer, for example, enables users to execute scripts that use the Dynamic HTML object model. Shell programs (such as C Shell, Bourne Shell and Korn Shell) enable you to write scripts that use an object model capable of manipulating the file system. Even the command prompt can be thought of as a scripting environment because it can run scripts written in the "batch file" language.

WSH is an unusual script host in that it was designed to be general-purpose. Unlike most of the scripting tools mentioned above, WSH imposes restrictions on neither the language used to write scripts nor the object models used by scripts.

WSH is ideal for non-interactive scripting needs such as logon scripting and administrative scripting but we will use it to download YouTube videos as well.

The key advantage of this script is that it will run on any Windows operating system newer than Windows 98. If you have Windows 98 or an older Windows, follow this link and install the latest version of WSH (unfortunately version 5.1 (5.6 is the latest))!

Let's define the interface of the script.

The script can either be run in WScript environment or CScript environment. WScript is the system default on Windows 2000. Characteristics of this environment are that output appears in a pop-up window, and script execution waits until the user clears the pop-up window by pressing OK button. The other environment is the CScript environment. The primary difference between the CScript and WScript environments is that the CScript environment directs display information to the command window, which has a side effect of letting a script run to completion without pausing for each message sent to the UI. I want this script to be usable from both of the environments.

Here is what I am thinking. By default I want this script to be accepting the video URL to download as the first command line argument (followed by more videos as next arguments). If the first argument is not provided and it is run in WScript environment I want the script to pop up an InputBox dialog asking for the URL of the video to download. Otherwise, if it is run in CScript environment, I want it to quit.

How do we find in which environment the script is being run? I had no idea, so I turned to Google Groups and searched for "cscript wscript detect" and found this post which explained how to do it with this snippet of code:

If "CSCRIPT.EXE" = UCase(Right(WScript.Fullname, 11)) Then
    WScript.Echo "The program was run by CScript!"
End If 

The next thing we need to figure out is how to get the command line arguments of a running script.

Turns out that each WSH script has a WScript object available without the script needing to bind to the object. Command-line arguments are stored in the WshArguments collection, which you access through the Arguments property of the WScript object.

Here is a diagram of WScript object's methods, properties and WShArguments expanded:

wsh wscript object's hierarcy

The easiest way to loop over all arguments is shown in this snippet:

Set objArgs = WScript.Arguments
For I = 0 to objArgs.Count - 1
   WScript.Echo objArgs(I)
Next

Now just instead of "WScript.Echo objArgs(I)" we call "DownloadVideo objArgs(I)", where DownloadVideo is our procedure for downloading YouTube videos.

In one of the previous articles, downloading youtube videos with awk programming language, I explained how the embedded YouTube flash video player retrieves the video file itself. Please see that article if you are interested in how I figured it out.

Last two things we have to figure out before we have a running script is how to talk over HTTP with VBScript and how to save the incoming binary data to a file.

Both VBScript and WScript object provide CreateObject function (but there is a difference between them) which allows binding to COM objects.

There is a "Microsoft.XmlHttp" COM Object which is shipped with Internet Explorer 5.0 and later. This object is what actually provides the well known AJAX interface used in Web2.0 applications - the XMLHttpRequest interface. Here at MSDN is the documentation of this interface with all the methods and properties it provides.

When we get the video, we will be dealing with binary data. Microsoft Scripting Runtime provides us with FileSystemObject (FSO) but unfortunately it is not suitable for writing binary files.

There is a way to write binary files with FSO but it is so slow that I dropped this solution. It took more than 10 minutes to write 1MB of data!

' Given a FileName and Data, saves Data to file named FileName
Sub SaveData(FileName, Data)
    Dim Fso: Set Fso = CreateObject("Scripting.FileSystemObject")
    Dim TextStream: Set TextStream = Fso.CreateTextFile(FileName, True)

    WScript.Echo LenB(Data)
    TextStream.Write BinaryToString(Data)
End Sub

' Given Binary data, converts it to a string
Function BinaryToString(Binary)
  Dim I, S
  For I = 1 To LenB(Binary)
    S = S & Chr(AscB(MidB(Binary, I, 1)))
  Next
  BinaryToString = S
End Function

A much better way to write binary data to a file with VBScript is using ADODO.Stream Object which deals with binary data out of the box. Look at SaveVideo function in my final program to see how it is used to write binary data to file.

Script Usage

Before the script can be used, you have to tell your computer to trust youtube.com domain. If you do not do this, executing the script will lead you to the following error:

ytdown.vbs(73, 5) msxml3.dll: Access is denied.

Youtube.com domain can be trusted by adding it to trusted sites security zone in Internet Explorer.
Launch your Internet Explorer browser and head to Tools -> Internet Options, then follow the steps illustrated in this image:

internet explorer trusted sites zone security

Once you have trusted youtube.com domain, you can start downloading the videos.

One of the ways is to double click the ytdown.vbs icon which will launch the script in WScript environment and an input dialog will appear asking for a video to download:

launch ytdown.vbs by double clicking the icon

After you press "OK", the downloader will save the video to a file with the title of the video and .flv extension in the same directory!

The other way to download a video is to call it via command line in CScript environment:

C:\ytdown>cscript ytdown.vbs "http://www.youtube.com/watch?v=h9MN2mKGZoo"
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.

Downloading video '30 fps, 30 frames (1 second)'
Done!

Happy downloading!

The downloaded .flv file can be converted to a better format like DivX or .avi.
Read about converting a video to a better format in this article.

Here is the final script:

'
' Peteris Krumins (peter@catonmat.net)
' http://www.catonmat.net  -  good coders code, great reuse
'
' 2007.08.03 v1.0 - initial release
' 2007.10.21 v1.1 - youtube changed the way it displays vids
' 2008.03.01 v1.2 - youtube changed the way it displays vids
' 2009.12.02 v1.3 - youtube changed the way it displays vids
'
Option Explicit

Dim WscriptMode

' Detect if we are running in WScript or CScript
If UCase(Right(WScript.Fullname, 11)) = "WSCRIPT.EXE" Then
    WScriptMode = True
Else 
    WScriptMode = False
End If 

Dim Args: Set Args = WScript.Arguments

If Args.Count = 0 And WScriptMode Then
    ' If running in WScript and no command line args are provided
    ' ask the user for a URL to the YouTube video
    Dim Url: Url = InputBox("Enter a YouTube video URL to download" & vbCrLf & _
                   "For example, http://youtube.com/watch?v=G1ynTV_E-5s", _
                   "YouTube Downloader, http://www.catonmat.net")
    If Len(Url) = 0 Then: WScript.Quit 1
    DownloadVideo Url
ElseIf Args.Count = 0 And Not WScriptMode Then
    ' If running in CScript and no command line args are provided
    ' show the usage and quit
    WScript.Echo "Usage: " & WScript.ScriptName & " <video url 1> [video url 2] ..."
    WScript.Quit 1
Else 
    ' Download all videos
    Dim I

    For I = 0 to args.Count - 1
        DownloadVideo args(I)
    Next
End If

' Downloads a YouTube video and saves it to a file
Sub DownloadVideo(Url)
    Dim Http, VideoTitle, VideoName, Req

    Set Http = CreateObject("Microsoft.XmlHttp")
    Http.open "GET", Url, False
    Http.send

    If Http.status <> 200 Then
        WScript.Echo "Failed getting video page at: " & Url & vbCrLf & _
                     "Error: " & Http.statusText
        Exit Sub
    End If

    Dim VideoId: VideoId = ExtractMatch(Url, "v=([A-Za-z0-9-_]+)")
    If Len(VideoID) = 0 Then
        WScript.Echo "Could not extract video ID from " & Url
        Exit Sub
    End If

    VideoTitle = GetVideoTitle(Http.responseText)
    If Len(VideoTitle) = 0 Then
        WScript.Echo "Failed extracting video title from video at URL: " & Url & vbCrLf & _
                     "Will use the video ID '" & VideoID & "' for the filename."
        VideoName = VideoID
    Else
        VideoName = VideoTitle
    End If

    Dim FmtMap: FmtMap = GetFmtMap(Http.responseText)
    If Len(FmtMap) = 0 Then
        WScript.Echo "Could not extract fmt_url_map from the video page."
        Exit Sub
    End If

    Dim VideoURL: VideoURL = Find_Video_5(FmtMap)
    If Len(VideoURL) = 0 Then
        WScript.Echo "Could not extract fmt_url_map from the video page."
        Exit Sub
    End If

    If WScriptMode = False Then: WScript.Echo "Downloading video '" & VideoName & "'"
    Http.open "GET", VideoURL, False
    Http.send

    If Http.status <> 200 Then
        WScript.Echo "Failed getting the flv video: " & Url & vbCrLf & _
                     "Error: " & Http.statusText
        Exit Sub
    End If

    Dim SaneFilename
    SaneFilename = MkFileName(VideoName)

    SaveVideo SaneFilename, Http.ResponseBody
    WScript.Echo "Done downloading video. Saved to " & SaneFilename & "."
End Sub

' Given fmt_url_map, url-escapes it, and finds the video url for video
' with id 5, which is the regular quality flv video.
Function Find_Video_5(FmtMap)
    FmtMap = Unescape(FmtMap)
    Find_Video_5 = ExtractMatch(FmtMap, ",?5\|([^,]+)")
End Function

' Given YouTube Html page, extract the fmt_url_map parameter that contains
' the URL to the .flv video
Function GetFmtMap(Html)
    GetFmtMap = ExtractMatch(Html, """fmt_url_map"": ""([^""]+)""")
End Function

' Given YouTube Html page, the function extracts the title from <title> tag
Function GetVideoTitle(Html)
    ' get rid of all tabs
    Html = Replace(Html, Chr(9), "")

    ' get rid of all newlines (vbscript regex engine doesn't like them)
    Html = Replace(Html, vbCrLf, "")
    Html = Replace(Html, vbLf, "")
    Html = Replace(Html, vbCr, "")

    GetVideoTitle = ExtractMatch(Html, "<title>YouTube ?- ?([^<]+)<")
End Function

' Given the Title of a video, function creates a usable filename for a video by
' sanitizing it - stripping parenthesis, changing non alphanumeric characters
' to _ and adding .flv extension
Function MkFileName(Title)
    Title = Replace(Title, "(", "")
    Title = Replace(Title, ")", "")

    Dim Regex
    Set Regex = New RegExp
    With Regex
        .Pattern = "[^A-Za-z0-9-_]"
        .Global = True
    End With

    Title = Regex.Replace(Title, "_")
    MkFileName = Title & ".flv"
End Function

' Given Text and a regular expression Pattern, the function extracts
' the first submatch
Function ExtractMatch(Text, Pattern)
    Dim Regex, Matches

    Set Regex = New RegExp
    Regex.Pattern = Pattern

    Set Matches = Regex.Execute(Text)
    If Matches.Count = 0 Then
        ExtractMatch = ""
        Exit Function
    End If

    ExtractMatch = Matches(0).SubMatches(0)
End Function

' Function saves Data to FileName
Function SaveVideo(FileName, Data)
  Const adTypeBinary = 1
  Const adSaveCreateOverWrite = 2
  
  Dim Stream: Set Stream = CreateObject("ADODB.Stream")
  
  Stream.Type = adTypeBinary
  Stream.Open
  Stream.Write Data
  Stream.SaveToFile FileName, adSaveCreateOverWrite
End Function

'
' ==========================================================================
' The following code saves binary data to file using FileSystemObject
' It is so slow that even on a 3.2Ghz computer saving 1 MB takes 10 minutes!
' Don't use it! I put it here just to illustrate the wrong solution!
' ==========================================================================
'

' Given a Filename and Data, the function saves Data to File
'Sub SaveVideo(File, Data)
'    Dim Fso: Set Fso = CreateObject("Scripting.FileSystemObject")
'    Dim TextStream: Set TextStream = Fso.CreateTextFile(File, True)
'
'    WScript.Echo LenB(Data)
'    TextStream.Write BinaryToString(Data)
'End Sub

' Given Binary data, converts it to a string
'Function BinaryToString(Binary)
'  Dim I, S
'  For I = 1 To LenB(Binary)
'    S = S & Chr(AscB(MidB(Binary, I, 1)))
'  Next
'  BinaryToString = S
'End Function


'
' ==========================================================================
' The following is an implementation of UrlUnescape. It turned out VBScript
' has Unescape() function built in already, that does it!
'
'Function UrlUnescape(Str)
'    Dim Regex, Match, Matches
'
'    Set Regex = New RegExp
'    With Regex
'        .Pattern = "%([0-9a-f][0-9a-f])"
'        .IgnoreCase = True
'        .Global = True
'    End With
'    ' Wanted to do this, but it wasn't quite possible
'    ' UrlUnescape = Regex.Replace(Str, Chr(CInt("&H" & $0)))
'
'    Set Matches = Regex.Execute(Str)
'    For Each Match in Matches
'        Str = Replace(Str, Match, Chr(CInt("&H" & Match.SubMatches(0))))
'    Next
'
'    UrlUnescape = Str
'End Function

Download Visual Basic Script YouTube Video Downloader

Download link: vbscript youtube video downloader
Total downloads: 21091 times

If you notice any bugs in this script, have any recommendations, want to criticize my code, want to thank me, then just post a comment on this article!

ps. remember the ILOVEYOU virus? It was also written in VBScript, that alone indicates that this language is worth knowing.

Comments

Qalid Permalink
November 15, 2007, 06:59

i get this error plz help

after i did all things u said i get this error

Skript C:/downloads/ytdown.vbs

Error ActiveXkomponenten can´t create objekt ADODB stream

Harshal Permalink
December 10, 2007, 20:50

Hi,
I followed the steps above on my Vista box,
YouTube is added to my trusted sites list,
but still I'm failing with the error:
" ytdown.vbs(73, 5) msxml3.dll: Access is denied.
"

Have you tested your script on Windows Vista ??
Anyother setting that I might need to change ??
Please let me know.

Thanks,
Harshal.

Tom Permalink
December 15, 2007, 00:27

EXCELLENT CODE! This works perfectly as documented here, using MSWinXPProSP2 and MSIE6SP2. THANK YOU for the excellent work!

December 21, 2007, 02:31

I am having the same problem as Harshal, but I am not running on Vista.
Could it be that I have another security that I have to go through, or is it something else that is wrong.

Daniel Permalink
January 07, 2008, 12:27

THANK YOU!!!!!!......... WAW!!!!!.... I REALLY FEEL HAPPY LEARNING!!!

umn Permalink
January 19, 2008, 19:11

This information is really usefull.
With this code I am getting same problem as Harshal and Diablo are getting. I am using Windows XP. Please tell me what is the wrong with this code.

January 20, 2008, 05:10

Umn, Harshal and Diablo I tried it on WinXP and I really got that nasty access denied error!

It could be that you have actually not trusted youtube.com!

Try this one more time:
1) Open Internet Explorer
2) Goto Tools -> Internet Options
3) Click the Security tab
4) Click the Local Internet icon (it should make "Sites..." button clickable)
5) Click on Sites... button
6) Click on Advanced button
7) Enter "http://www.youtube.com" into "Add this website to the zone" text field and click Add button.
7) Do the same for "http://youtube.com" (without www)

I did this and it started working!

Axel Vasquez Permalink
January 21, 2008, 06:54

I put www.youtube.com and http://youtube.com as a trusted site but i have this error:
ytdown.vbs(73, 5) msxml3.dll: Access is denied.
can you help me?

Jay Permalink
February 08, 2008, 18:20

Hey, while downloading from youtube using VBScript downloader, i am getting this error:

Failed getting the flv video: http://youtube.com/watch?............
Error:Not found

Please help me....

March 07, 2008, 02:53

This only seems to work with IE6. It does not work with IE7 on XP or IE7 on Vista.... I wish he would revise it to make it work for both.

March 21, 2008, 01:39

Got this script wokring by changing

Set Http = CreateObject("Microsoft.XmlHttp")

to

Set Http = CreateObject("MSXML2.ServerXMLHTTP")

Mike R Permalink
May 12, 2011, 10:09

This was brilliant! I already have a script that worked with "Microsoft.XMLHttp" in another app and spend 2 days trying to get it to work with my new app. But this change cracked it first time. Don't know why it just did !!!

March 21, 2008, 01:59

Jo, wow, thanks for fixing that. I did not know why it did not work on IE7 on XP or Vista.

I'll read up on MSXML2.ServerXMLHTTP, make changes to it soon and put it here!

max Permalink
March 21, 2008, 16:32

hi
i followed the whole procedure even that one u told to Harshal and diablo but nothing happens. I mean it does'nt start downloading, it says "this page is accessing information which is not under its control..want to continue"

Gursharan Permalink
April 07, 2008, 08:45

Thanks man, it worked for me on winxp and win2003

steveking Permalink
May 16, 2008, 10:09

YouTubeRobot.com today announces YouTube Robot 2.0, a tool that enables you to download video from YouTube.com onto your PC, convert it to various formats to watch it when you are on the road on mobile devices like mobile phone, iPod, iPhone, Pocket PC, PSP, or Zune.

YouTube Robot allows you to search for videos using keywords or browse video by category, author, channel, language, tags, etc. When you find something noteworthy, you can preview the video right in YouTube Robot and then download it onto the hard disk drive. The speed, at which you will be downloading, is very high: up to 5 times faster than other software when you download a single file and up to 4 times faster when you download multiple files at a time.

Manual download is not the only option with YouTube Robot. You may as well schedule the download and conversion tasks to be executed automatically, even when you are not around. Downloading is followed by conversion to the format of your choice and uploading videos to a mobile device (if needed). For example, you can plug in iPod, select the video, go to bed, and when you wake up next morning, your iPod will be ready to play new YouTube videos.

Product page: 3w.youtuberobot.com
Direct download link: 3w.youtuberobot.com/download/utuberobot.exe
Company web-site: 3w.youtuberobot.com
E-mail: support@youtuberobot.com

Matt Permalink
August 01, 2008, 00:05

My anti-virus scanner told me this was an exploit by the name of JSADODB-BM [Expl]. Why?

Email me at Igorbaltiski@hotmail.co.uk

September 18, 2008, 07:20

Great work man! I was able to use this technique on other things which has to do with http file downloads as well. Thanks a lot!

jake33 Permalink
October 01, 2008, 03:05

I am converting to Visual Basic 2008 - all works well, except I get "Access is Denied" when it is at the "Http.send()" method for "http://www.youtube.com/get_video?..."

Semeolvido Permalink
October 03, 2008, 09:16

Nice page ^^ gratz

chance

Http.open "GET", "http://www.youtube.com/watch?" & Req, False

line 73

vista Permalink
October 22, 2008, 00:22

compatibility with Vista?

I get an error message: "Forbidden"

December 15, 2008, 06:53

I also get "Forbidden" message,what should i do?

January 24, 2009, 17:32

I use Windows XP Pro SP3. It worked when I had IE6 but I upgraded to IE8 and now it says:

Script: C:\...\ytdown.vbs
Line: 74
Char: 5
Error: Access is denied.
Code: 80070005
Source: msxml3.dll
Anonyme Permalink
March 29, 2009, 02:59

Avast! say that is a virus who exploit ressource in Windows, That's true?

April 17, 2009, 04:34

This is a malicious script! DO NOT DOWNLOAD. Peteris Krumins is going to jail.

April 17, 2009, 04:36

This is not a malicious script. Neither it's a virus.

Josh Permalink
May 23, 2009, 17:37

i found an easier and faster way...

This Zillatube downloads the video so easily.. and also plays them for you...

found it at http://www.zillatube.com

September 24, 2009, 04:26

The vbscript script no longer works, maybe becasue youtube changed its way. You have updated the gawk script, Can you also update the vbscript?

Thanks.

September 24, 2009, 05:27

Honglus, ok, I will update it!

March 30, 2010, 03:44

I have 2 fixed source of youtube downloader....

check demo

demo 1----http://pcrole.chemicalservers.com/1/

demo2---- http://pcrole.chemicalservers.com/

If you want then contact me..Email--mbt1370 @ gmail . com

Josh Permalink
June 10, 2010, 12:45

Peteris,

Did you already have the change to update this script? Still getting an 'Bad request' error.

Kind regards, Josh

June 10, 2010, 18:22

Hey, I have dropped support for this script. Can't support all these programs forever. There are better things to think and work about. It was written for fun anyway, not a serious program.

June 18, 2010, 06:37

Check this New Demo--

www.allgrabs.com

Josh Permalink
May 19, 2011, 23:35

does this script still work now ?
i get this error

Failed extracting video title from video at URL: http://www.youtube.com/watch?v=
2mTLO2F_ERY
Will use the video ID '2mTLO2F_ERY' for the filename.
Downloading video '2mTLO2F_ERY'
C:\ffmpeg.rev12665\ytdown.vbs(81, 5) (null): Unspecified error

April 05, 2014, 06:19

script does not seem to work anymore.
My test url
(Cypress Hill Lowrider)
https://www.youtube.com/watch?v=FEmoZ23Weyc

I get the following errors:
Failed extracting video title from video at URL:
https://www.youtube.com/watch?v=FEmoZ23Weyc
Will use the video ID 'FEmoZ23Weyc' for the filename.

And:
Could not extract fmt_url_map from the video page.

It is not that I want to use the script to get videos, I am currently looking at scripting examples while I build and improve my HTA/VBScript media ID3 tag editor and player.

I am currently looking for a way to extract and display album art in the HTA page. I am able to download album art using a executable and save it as filename.jpg but every time it grabs new art from the internet a black box appears for a few seconds. Its not very clean looking. so that's what I am working on, trying to move the amazon search and download of the jpg's into a pure VBScript and away from the executable.

I know it is a very old scrip. Are any plans to update it.

Thank you Rob Moore

Leave a new comment

(why do I need your e-mail?)

(Your twitter name, if you have one. (I'm @pkrumins, btw.))

Type the first letter of your name: (just to make sure you're a human)

Please preview the comment before submitting to make sure it's OK.

Advertisements