

VBA web scraping uses Excel's built-in Visual Basic for Applications to pull data from web pages straight into a spreadsheet. For static pages, a WinHttp.WinHttpRequest.5.1 call fetches the HTML with nothing extra to install. For pages that load content with JavaScript, SeleniumBasic drives Microsoft Edge. The classic Internet Explorer automation object is no longer supported, so this guide uses the current methods.
Did an old macro suddenly stop working? Many Excel scrapers were built on Internet Explorer, and they broke once Windows turned that browser off. The fix is simpler than it sounds.
VBA web scraping is the use of Excel's Visual Basic for Applications to request a web page and write the values it returns into worksheet cells. A short macro fetches the page over HTTP, reads the parts you name, and fills the rows. It suits small, spreadsheet-bound jobs where installing other software is not an option.
VBA comes with desktop Office for Windows, so the results land right where you need them. No export, no copy and paste. There are two ways to do it: send a plain HTTP request and read the HTML, or open a real browser and read the page once it finishes loading.
Pick the method before writing code. First, check whether the value is already in the page's raw HTML: open the page and search the source for it. If it is there, a WinHttpRequest fetch is enough and it is fast. If the value only appears after JavaScript runs, or the task needs a login or button clicks, use SeleniumBasic with Microsoft Edge. If the job is scheduled or large, it has outgrown Excel.
In Edge, press Ctrl+U to view the page source, then press Ctrl+F and search for a value you can see on screen, such as a price. That one search decides most of what follows.
Work through three questions in order:
The old InternetExplorer.Application object is not a recommended target for new work. Microsoft has retired the browser behind it on current Windows 10 and 11 versions, so rewrite any macro that depends on it. Planning to use a proxy too? Read up on the different proxy types first, since the choice shapes the code later.
1. Turn on the Developer tab. Go to File > Options > Customize Ribbon, tick Developer in the right-hand list, and click OK.
2. Open the Visual Basic Editor. Press Alt+F11, then choose Insert > Module. Your code goes in this blank module.
3. Add the references. In the editor, open Tools > References and tick these two:
4. Save as a macro-enabled workbook. Choose File > Save As and pick Excel Macro-Enabled Workbook (*.xlsm). A regular .xlsx file drops your code when it saves.
Both references ship with Windows and Office, which matters if your IT team doesn't allow extra software. If macros won't run at all, check File > Options > Trust Center.
For a static page, create a WinHttp.WinHttpRequest.5.1 object, open a GET request, then read responseText once you send it. Load that HTML into a Microsoft HTML Object Library document, select elements with getElementsByClassName or querySelectorAll, and write each value to a cell. It runs fast, since there's no browser to load, and it installs nothing beyond references already in Windows.
This example pulls every quote and author from quotes.toscrape.com, a public practice site built for scraping tutorials.
vba Sub ScrapeStatic() Dim http As New WinHttp.WinHttpRequest Dim htmlDoc As New MSHTML.HTMLDocument Dim quotes As Object, authors As Object Dim i As Long http.Open "GET", "https://quotes.toscrape.com/", False http.Send If http.Status <> 200 Then MsgBox "Request failed with status " & http.Status Exit Sub End If htmlDoc.body.innerHTML = http.ResponseText Set quotes = htmlDoc.getElementsByClassName("text") Set authors = htmlDoc.getElementsByClassName("author") With Sheets(1) .Cells(1, 1).Value = "Quote" .Cells(1, 2).Value = "Author" For i = 0 To quotes.Length - 1 .Cells(i + 2, 1).Value = quotes(i).innerText .Cells(i + 2, 2).Value = authors(i).innerText Next i End With End Sub
What each part does:
The Microsoft WinHttpRequest reference lists Open, Send, SetProxy, and SetCredentials as native methods of the object. That's why it's the default choice. It runs without a window and works fine on locked-down machines. Teams use the same pattern for many data collection use cases, from supplier price lists to SEO data collection like title tags.
Keep in mind that this document is a static snapshot where no scripts run. If the site loads its data from a JSON endpoint (check the Network tab in Edge's developer tools), request that URL instead. A few InStr and Split calls go a long way on small JSON responses.
When the values load after JavaScript runs, or the task needs a login and clicks, drive a real browser. Install SeleniumBasic, add the Selenium Type Library reference, and match Edge WebDriver to your Edge version. From VBA, Selenium then drives Microsoft Edge to sign in and read content that the plain HTTP fetch cannot see.
The JavaScript version of the practice site, quotes.toscrape.com/js/, builds its quotes in the browser. The fetch method would come back empty there, so it makes a good test.
vba Sub ScrapeDynamic() Dim bot As New Selenium.EdgeDriver Dim el As Selenium.WebElement Dim r As Long bot.Start bot.Get "https://quotes.toscrape.com/js/" r = 1 For Each el In bot.FindElementsByCss("div.quote span.text") Sheets(1).Cells(r, 3).Value = el.Text r = r + 1 Next el bot.Quit End Sub
bot.Start opens Edge, and bot.Get loads the page and waits for it. FindElementsByCss returns every match, while FindElementByCss returns only the first. el.Text reads what the browser shows, and bot.Quit closes Edge.
Pick this over the fetch for logins and for values that only show up once scripts run. A real browser loads every asset on the page, so each page takes longer than a plain request. Keep SeleniumBasic for the pages that need it and use the fetch everywhere else.
SeleniumBasic also has a ChromeDriver class that works the same way. If you check pages by hand in Chrome before writing a macro, our Chrome proxy extension makes switching proxies quick.
WinHttpRequest is the most direct native VBA object for setting a proxy per request. Call SetProxy on the client, call Open, then pass the gateway credentials with SetCredentials using the proxy flag, and send. Because SetCredentials only works after Open, repeat it after every Open when you reuse the same client for a list of pages. MSXML2.XMLHTTP has no per-request proxy setting, so use WinHttpRequest when a proxy is involved.
Many sites show different prices or search results depending on the visitor's location. A proxy in the right country gives you location-accurate results for price monitoring and localization checks on publicly available data.
How the common native objects compare:
| Native VBA object | Per-request proxy | Proxy credentials | Use it for |
|---|---|---|---|
| WinHttp.WinHttpRequest.5.1 | Yes (SetProxy) | Yes (SetCredentials, proxy flag) | Any request that needs an explicit proxy |
| MSXML2.ServerXMLHTTP.6.0 | Yes (setProxy) | Yes (setProxyCredentials) | Existing code already built on MSXML |
| MSXML2.XMLHTTP | No usable control (uses the Windows proxy settings) | No | Simple calls with no proxy requirement |
The working pattern:
vba Sub ScrapeViaProxy() Dim http As New WinHttp.WinHttpRequest ' 2 = use the proxy named here (host:port from your dashboard) http.SetProxy 2, "your-proxy-host:port" http.Open "GET", "https://api.ipify.org/", False ' 1 = these credentials are for the proxy; call this after Open http.SetCredentials "proxy-username", "proxy-password", 1 http.Send Debug.Print http.Status, http.ResponseText End Sub
In the Microsoft SetProxy reference, setting 2 applies the proxy to this object only, and SetProxy has to run before Send. The Microsoft SetCredentials reference explains that flag 1 sends the credentials to the proxy and that the method returns an error if Open hasn't been called yet. The test URL returns the IP address the site sees, so the Immediate window (Ctrl+G) should show the proxy's IP, not yours.
Your host, port, username, and password are in your Proxy-Cheap dashboard. Here's how to find your proxy host and port if you're unsure.
Match the proxy type to the job:
Proxy-Cheap plans come with no monthly commitment, and you can cancel anytime. Check the live product pages for current pricing.
VBA is single-threaded, so a synchronous request freezes Excel until it returns. Keep each run responsive: pace requests (roughly one per second), write results to the sheet as they arrive, and add a status column so a stopped run resumes from where it left off. Small batches with checkpoints turn a run people cancel into one that finishes.
The easiest pattern is a queue sheet. Put URLs in column A and let the macro write "done" or "error" in column B, so the next run skips finished rows.
vba Function FetchPage(http As WinHttp.WinHttpRequest, url As String) As Boolean On Error GoTo Failed http.Open "GET", url, False http.Send FetchPage = (http.Status = 200) Exit Function Failed: FetchPage = False End Function Sub ScrapeQueue() Dim http As New WinHttp.WinHttpRequest Dim ws As Worksheet, r As Long, ok As Boolean Set ws = ThisWorkbook.Sheets("Queue") For r = 2 To ws.Cells(ws.Rows.Count, 1).End(xlUp).Row If ws.Cells(r, 2).Value <> "done" Then ok = FetchPage(http, ws.Cells(r, 1).Value) If Not ok Then ok = FetchPage(http, ws.Cells(r, 1).Value) ' retry once If ok Then ws.Cells(r, 3).Value = Len(http.ResponseText) ' swap in your own parsing ws.Cells(r, 2).Value = "done" Else ws.Cells(r, 2).Value = "error" End If DoEvents Application.Wait Now + TimeValue("0:00:01") End If Next r End Sub
DoEvents lets Excel redraw between pages, and the one-second wait keeps request rates modest. The same queue works for checking landing pages in ad verification workflows.
VBA scraping suits small, spreadsheet-bound jobs on machines where extra software cannot be added. Once a job runs on a schedule, grows large, or needs heavy rendering, a small script in a language your team already uses is easier to maintain, and it can still write to the same workbook.
VBA is a great fit when the results belong in a spreadsheet anyway, you're pulling tens or hundreds of pages, and you can't install other tools on your work machine. It's time to move on when the job needs to run unattended or covers thousands of pages. At that point, a script that calls a proxy API or runs on a server will scale better for ongoing market research.
If your source is a clean HTML table, try Power Query first. Data > Get Data > From Web imports tables with no code.
| Pros | Cons |
|---|---|
| Built into Office for Windows, so there's nothing new to buy | Tied to Windows and desktop Excel |
| The HTTP method needs no installs | Single-threaded, so large jobs take a while |
| Results land directly in cells | Browser automation needs SeleniumBasic and a matching driver |
| Easy to learn for spreadsheet users | Best paired with a proxy for location-accurate public data |
For a recurring task like price monitoring on a few dozen product pages, the pros usually win.
Proxy-Cheap puts rotating residential, static residential (ISP), datacenter IPv4, and mobile proxies under one account, so you can start small and switch types as your Excel workflows grow.