VBA - scraping websites videos | Excel VBA Part 49 - Downloading Files from Websites

Posted by Andrew Gould on 21 November 2016

PLEASE NOTE - The design of the website used in this video has changed since the video was recorded. This means that the code shown in the video no longer works. The downloadable file contains both the original version of the code and a version which works with the current version of the website. Excel VBA doesn't have a native method for downloading files from websites but you can declare an API function that will enable you to do this. This video takes you through the process of declaring the API function and using it in your code, along with a bunch of other useful techniques such as using folder pickers, creating folders with FileSystemObjects and opening a Windows Explorer window using the Shell function.

You can download any files that you need to follow the video here.

You can increase the size of the video:

Full screen mode for YouTube

You can view the video in full screen mode as shown on the left, using the icon at the bottom right of the frame.

You can also increase the quality of the video:

Changing resolution

You can improve the resolution of the video using another icon at the bottom right of the frame. This will slow down the connection speed, but increase the display and sound quality. This icon only becomes visible when you start playing the video.

Finally, if nothing happens when you play the video, check that you're not using IE in compatibility view.

This page has 6 threads Add post
14 May 20 at 17:45

Hi Andrew,

In the video "Excel VBA Part 49 - Downloading Files from Websites", you told, if user uses 32 bit or 64 bit Microsoft Office 2010 or later, then prtsafe API function (1st API Function on this Video) will be effective, but if user uses Microsoft Office prior to 2010 (like Microsoft Office 2003 or 2007), then 2nd API function (which is only for 32 bit version of Microsoft Office) will be effective. My question is, what if someone uses 64 bit version of Microsoft Office 2007 or earlier? Then, is there any of these API Functions useful? Or I've to write any other extra coding to get this function work on correctly? Please reply to my questions Andrew.

Thank you for these wonderful videos. I really owe my career to you and Mike Girvin (Excelisfun). Whatever I'm today, just because two of you. I would rather say that, learning front part of Excel is incomplete without watching the videos of Excelisfun and learning VBA is incomplete without watching your videos. Both of you are doing noble work to make us educated. I regard both of you as my Guru.

15 May 20 at 06:30

Hi! The good news is that you don't need to worry about this for Office 2007 as there isn't a 64bit edition of the software! As for earlier versions of Office, I'm afraid I don't know.

I'm very happy to hear that you've found the videos so useful, thank you for the kind comments!

15 May 20 at 19:47

Hi Andrew,

I know only saying "Thank you" is not enough for what you've been doing for us over the past couple of years. I can only pray to the God that all your dreams come true in this life. Truly to speak, I've never seen a teacher like you and Excelisfun in my whole life so far.

Andrew G  
16 May 20 at 08:24

That's very kind of you to say but you should give yourself the credit for taking the time to learn - it takes a lot of dedication so well done to you as well!

14 May 19 at 11:47

Hi Andrew,

Great video and great explanation'

I have a problem to download a file form a web page, may be you can help me'  The problem is that there is no link to use the URLDownloadToFile Function. All I have is an event.click .... this is not the original website, but I can explain myself


This is the code I'm analysing:

Sub Downloadparamostrarproblema()
Dim IE As InternetExplorer
Dim HTMLdoc As HTMLDocument
Dim URL As String
Dim Pepe As Object
URL = "https://www.cenace.gob.mx/SIM/VISTA/REPORTES/PreEnergiaSisMEM.aspx"
Set IE = CreateObject("InternetExplorer.Application")
With IE .navigate URL
Do Until .readyState = 4: DoEvents: Loop
End With
IE.Visible = True
Set HTMLdoc = IE.document
Dim HTMLdiv As HTMLDivElement
Set HTMLdiv = HTMLdoc.getElementById("ctl00_ContentPlaceHolder1_treePrincipal")
Dim HTMLspan As HTMLSpanElement
Set HTMLspan = HTMLdiv.getElementsByTagName("span").Item(2)
Set Pepe = HTMLdoc.getElementById("ctl00_ContentPlaceHolder1_ListViewNodos_ctrl0_ListViewArchivosSIN_ctrl0_linkCSV")
Set HTMLdiv = Nothing
Set HTMLdoc = Nothing
Set IE = Nothing End Sub

I know that in this case I have a Href I could use to download the file, but in the web page I'm working on it has NO link, and I want to download automatically the file.

Any idea how to download pepe.click automatically?

Regards, Santos.

13 Dec 17 at 08:25

Hi, I have one question. Partly by using your super useful vide's I started trying extracting data from websites to excel. There is one thing though that just keeps failing. Here is an example of the code written. The line:

Debug.print Classnames.length

keeps returning 0, whatever searchtype I use, classname, tagname, id. Could you find any incorrect use of code in here?

Thanks in advance for your answer.


Const HappyEmpURL As String = "https://happyemployees.nle.nl/"

Sub GetDataFromWebsite()

Dim HTMLDoc As New MSHTML.HTMLDocument
Dim Article1 As MSHTML.IHTMLElement
Dim Classnames As MSHTML.IHTMLElementCollection

XMLReq.Open "GET", HappyEmpURL, False

If XMLReq.Status <> 200 Then
    MsgBox "Problem" & vbNewLine & XMLReq.Status & "-" & XMLReq.statusText
    Exit Sub
End If

HTMLDoc.Body.innerHTML = XMLReq.responseText
Set Classnames = HTMLDoc.getElementsByClassName("mx-layoutcontainer-center mx-scrollcontainer-center ")
Debug.Print Classnames.Length
For Each Article1 In Classnames
Article1.getElementsByid ("159b6aef-dbc3-5b23-a735-cf99f8341771-1")
Debug.Print Article1.getAttribute("href"), Article1.innerText, Article1.className
Next Article1

End Sub

14 Dec 17 at 09:21

Hi Jonathan,

I think the main problem here is that most of the page content appears to be generated by javascript.  I believe this means that that an XML HTTP request won't contain the elements you're looking for because the javascript won't be executed to create them in the first place. An alternative would be to use Internet Explorer as described in this video.

So, for example, this code will return a couple of elements from the login form on the page you've linked to:

Sub GetHTMLDocument()

    Dim IE As New SHDocVw.InternetExplorer
    Dim HTMLDoc As MSHTML.HTMLDocument
    Dim Article1 As MSHTML.IHTMLElement
    Dim Classnames As MSHTML.IHTMLElementCollection
    IE.Visible = True
    IE.navigate "https://happyemployees.nle.nl/"
    Do While IE.ReadyState <> READYSTATE_COMPLETE
    Application.Wait Now + TimeValue("00:00:02")
    Set HTMLDoc = IE.Document
    Set Classnames = HTMLDoc.getElementsByClassName("form-control")
    Debug.Print Classnames.Length
    For Each Article1 In Classnames
        Debug.Print Article1.className, Article1.getAttribute("name")
    Next Article1
End Sub

The results I see are:

form-control mx-focus       username
form-control  password

I hope that helps!

19 Jun 17 at 08:57

I'm trying to scrape data from the Racing Post website, but of of their class name are ridiculously long. For instance "ui-table__body


taken from https://www.racingpost.com/profile/horse/836785/danish-duke#race-id=676975.

I can't get my scraper to recognise these names.

Can you help?

19 Jun 17 at 11:49

I'd be tempted to use the VBA REPLACE function before you start scraping, to replace the long class names with shorter, more manageable ones.  If you find this doesn't work, you may find that the long class names include some strange carriage return character codes.  If you find a good solution, please do reply to this thread letting me (and everyone else) know.

07 Jun 17 at 20:51

Using Excel 2007, and it doesn't recognise  'PtrSafe' . I downloaded the workbook and the "Private Declare PtrSafe Function"  shows as all red. However if i remove the 'PtrSafe' , it's ok?


08 Jun 17 at 10:21

You could use conditional compilation:

#If VBA7 Then
  Declare PtrSafe Function ...
   Declare Function ...
#End If

I'd love to claim the credit for this, but I got it from this MSDN page.

25 Nov 16 at 15:12

Kaspersky keeps blocking the file from being downloaded; the message I get says: HEUR: Trojan-Downloader.Script.Generic



25 Nov 16 at 22:26

Hi Joni,

Do you see this message for a specific file or for every file that it downloads?  If the former then I'd bet that it's a false-positive from Kaspersky. If you're concerned, however, please don't use the file. You can easily recreate the code simply by following along with the video.

Thanks for bringing it to our attention!

11 Apr 17 at 17:11

I have the same problem.

Kaspersky Internet Security said: The object is infected by HEUR:Trojan-Downloader.Script.Generic.

This only for this one file. Other files can be downloaded succesfully.

Andrew G  
11 Apr 17 at 21:31

It seems to be a Kaspersky specific issue - the HEUR indicates that a heuristic analysis has detected code in the file which matches a particular pattern of potentially malicious code. The file contains code which automatically downloads files from URLs which, as you can imagine, out of context could be construed as malicious. As I wrote the code I know that it's not and can only assume that Kaspersky is returning a false positive but, as I said in the previous response, if you're at all concerned by it, don't download it. You can easily recreate the code by simply following along with the video.

I hope that helps!