Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Clear out junk files and repair common Windows errors3Fix the driver behind crashes, sound loss and screen glitchesSome links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
The official name is XMLHttpRequest, not HTTPXMLRequest. In classic Visual Basic 6, an MSXML IXMLHTTPRequest object does not expose onreadystatechange as an ordinary WithEvents COM event. Use a Timer to poll readyState, or use Microsoft’s wrapper-class callback technique. A DOMDocument event is suitable for asynchronous XML loading, while VBScript can assign a function with GetRef.
This article targets VB6 and MSXML. VBA has similar COM limitations but requires host-specific testing; modern VB.NET applications should normally use HttpClient with Async/Await.
| # | Preview | Product | Price | |
|---|---|---|---|---|
| 1 |
|
Programming Microsoft Visual Basic 6.0 | $5.00 | Buy on Amazon |
| 2 |
|
Visual Basic 6 For Dummies | $12.79 | Buy on Amazon |
| 3 |
|
Visual Basic(r) 6.0 Internet Programming | $6.38 | Buy on Amazon |
| 4 |
|
Programming Visual Basic 6.0 | $42.75 | Buy on Amazon |
| 5 |
|
Beginning Visual Basic 6 Database Programming | $21.97 | Buy on Amazon |
What onreadystatechange means
onreadystatechange is a write-only callback property invoked when an MSXML request’s readyState changes. It can run several times, so the handler must check for state 4 before processing the final response. Microsoft documents the property for IXMLHTTPRequest and IServerXMLHTTPRequest.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
| Value | Meaning |
|---|---|
| 0 | Uninitialized; Open has not been called. |
| 1 | Opened; Send has not been called. |
| 2 | Request sent; status and headers are available. |
| 3 | Interactive; some response data has arrived. |
| 4 | Complete; all response data has arrived. |
These states are described in Microsoft’s IXMLHTTPRequest documentation. State 4 means completion, not a successful HTTP response. Read Status only after completion and treat transport failures separately.
#1 Best Overall
- Used Book in Good Condition
Why ordinary WithEvents does not solve XMLHTTP
This declaration is not the general solution:
Private WithEvents xhr As MSXML2.XMLHTTP60
Microsoft explains that the callback was designed primarily for scripting environments, many of which do not support COM events. Consequently, VB6 normally cannot consume IXMLHTTPRequest.onreadystate​change like a control event. Microsoft’s VB6 guidance lists three practical choices: Timer polling, a wrapper class, or an event-bearing DOMDocument when the task is XML loading (Microsoft implementation guidance).
First prepare the MSXML reference
In VB6, open Project → References and select Microsoft XML, v6.0 if that version is installed. Then use the version-qualified type:
Dim xhr As MSXML2.XMLHTTP60
Set xhr = New MSXML2.XMLHTTP60
Available versions and reference labels depend on the Windows installation. Late binding avoids a compile-time reference but moves failures to runtime:
Rank #2
Dim xhr As Object
Set xhr = CreateObject("MSXML2.XMLHTTP.6.0")
Option 1: poll with a VB6 Timer
Timer polling is usually the easiest implementation to debug. Keep the request at form or module scope, open it asynchronously, and disable the Timer before handling the completed response.
Option Explicit
Private xhr As MSXML2.XMLHTTP60
Private Sub cmdGet_Click()
On Error GoTo RequestError
Set xhr = New MSXML2.XMLHTTP60
Timer1.Interval = 50
Timer1.Enabled = True
xhr.Open "GET", "https://example.com/data.xml", True
xhr.Send
Exit Sub
RequestError:
Timer1.Enabled = False
MsgBox Err.Number & ": " & Err.Description, vbExclamation
End Sub
Private Sub Timer1_Timer()
On Error GoTo PollError
If xhr Is Nothing Then Exit Sub
If xhr.readyState <> 4 Then Exit Sub
Timer1.Enabled = False
If xhr.Status >= 200 And xhr.Status < 300 Then
Debug.Print xhr.responseText
Else
MsgBox "HTTP error: " & CStr(xhr.Status), vbExclamation
End If
Set xhr = Nothing
Exit Sub
PollError:
Timer1.Enabled = False
MsgBox Err.Number & ": " & Err.Description, vbExclamation
End Sub
The 50-millisecond interval is only an example; choose a cadence appropriate for the application rather than assuming one interval is universally correct. A Timer will not fire while the UI thread is blocked, and a synchronous request (Open ..., False) can make the interface appear frozen. The first tick must inspect the current state because intermediate states may have passed before polling began.
Option 2: use Microsoft’s VB6 wrapper-class callback
Use this approach when callback-style organization is more useful than polling, especially with multiple requests or forms. The crucial detail is that the handler procedure must be made the class module’s default procedure.
- Create a VB6 Standard EXE project and add the MSXML reference.
- Add a Class Module named
ReadyStateHandler. - Add a public
OnReadyStateChangeprocedure. - Choose Tools → Procedure Attributes → Advanced, set Procedure ID to (Default), and confirm.
- Retain the handler in a form- or module-level variable.
- Assign it to
OnReadyStateChangebefore callingOpenandSend.
The default-procedure attribute is functional, not cosmetic: it is how VB6 supplies the object to this callback property.
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallClass module: ReadyStateHandler
Option Explicit
Public Sub OnReadyStateChange()
Dim request As MSXML2.XMLHTTP60
Set request = Form1.XmlHttp
Debug.Print "readyState = " & CStr(request.readyState)
If request.readyState <> 4 Then Exit Sub
On Error GoTo ResponseError
If request.Status >= 200 And request.Status < 300 Then
Form1.HandleSuccessfulResponse request.responseText
Else
Form1.HandleHttpError request.Status
End If
Exit Sub
ResponseError:
Form1.HandleTransportError Err.Number, Err.Description
End Sub
Form code
Option Explicit
Public XmlHttp As MSXML2.XMLHTTP60
Private readyHandler As ReadyStateHandler
Private Sub cmdGet_Click()
On Error GoTo RequestError
Set XmlHttp = New MSXML2.XMLHTTP60
Set readyHandler = New ReadyStateHandler
XmlHttp.OnReadyStateChange = readyHandler
XmlHttp.Open "GET", "https://example.com/data.xml", True
XmlHttp.Send
Exit Sub
RequestError:
MsgBox Err.Number & ": " & Err.Description, vbExclamation
End Sub
Public Sub HandleSuccessfulResponse(ByVal body As String)
Debug.Print body
End Sub
Public Sub HandleHttpError(ByVal httpStatus As Long)
MsgBox "HTTP status: " & CStr(httpStatus), vbExclamation
End Sub
Public Sub HandleTransportError(ByVal number As Long, ByVal description As String)
MsgBox "Transport error " & CStr(number) & ": " & description, vbExclamation
End Sub
Do not declare the handler only inside cmdGet_Click; releasing it when the procedure ends can remove the callback before the request completes. Also guard against repeated state changes with readyState <> 4. If users can start overlapping requests, disable the command, retain one handler per request, or associate each callback with a request identifier.
Option 3: DOMDocument with WithEvents
For asynchronous XML document loading, VB6 can use the documented DOMDocument event syntax:
Rank #4
Option Explicit
Private WithEvents XmlDoc As MSXML2.DOMDocument60
Private Sub cmdLoadXml_Click()
On Error GoTo LoadError
Set XmlDoc = New MSXML2.DOMDocument60
XmlDoc.async = True
XmlDoc.Load "https://example.com/data.xml"
Exit Sub
LoadError:
MsgBox Err.Number & ": " & Err.Description, vbExclamation
End Sub
Private Sub XmlDoc_onreadystatechange()
If XmlDoc.readyState <> 4 Then Exit Sub
If XmlDoc.parseError.ErrorCode <> 0 Then
MsgBox XmlDoc.parseError.Reason, vbExclamation
Else
Debug.Print XmlDoc.XML
End If
End Sub
See Microsoft’s Visual Basic DOMDocument event documentation. This is an XML-loading alternative, not a universal replacement for IXMLHTTPRequest: Microsoft specifically notes that it is unsuitable when the same operation must first post XML to a web server.
VBScript uses a different binding syntax
VBScript can pass a function reference directly with GetRef:
Recommended Free Tools
Option Explicit
Dim xhr
Set xhr = CreateObject("MSXML2.XMLHTTP.6.0")
xhr.onreadystatechange = GetRef("HandleStateChange")
xhr.Open "GET", "https://example.com/data.xml", True
xhr.Send
Sub HandleStateChange()
If xhr.readyState <> 4 Then Exit Sub
If xhr.Status >= 200 And xhr.Status < 300 Then
WScript.Echo xhr.ResponseText
Else
WScript.Echo "HTTP error: " & xhr.Status
End If
End Sub
Microsoft documents this GetRef pattern. Do not copy it unchanged into VB6; the wrapper class addresses the different callback-binding rules there.
Best Value
Request order and response checks
For an asynchronous VB6 request, the reliable sequence is:
- Create the MSXML request object.
- Create and retain the callback handler, when using the wrapper approach.
- Assign
OnReadyStateChange. - Call
Openwith its third argument set toTrue. - Call
Send. - Wait for
readyState = 4. - Check the HTTP status.
- Read
responseText,responseXML, orresponseBody. - Release the request and handler after completion.
Use False as the third argument only for a synchronous contrast; it blocks the calling thread:
xhr.Open "GET", url, False
xhr.Send
The Status property is an HTTP code. A 2xx range includes successful responses such as 200, 201, 202, and 204. A 204 response may legitimately have no body. Codes such as 400, 401, 403, 404, 500, and 503 are completed HTTP responses but not application success. Redirect, authentication, proxy, and TLS behavior can differ between XMLHTTP and ServerXMLHTTP.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →Diagnose the common failures
- Missing reference or ProgID: verify the installed MSXML version, reference name, and whether early or late binding is appropriate.
- Callback never fires: confirm that the request is asynchronous, the handler is assigned before
Open/Send, and the handler object remains in scope. - Timer never fires: enable the Timer and check that the UI thread is not blocked by synchronous work.
- Repeated completion processing: disable the Timer or add the state-4 guard before handling the response.
- Status raises an error: a DNS, connection, timeout, certificate, proxy, invalid-URL, or permission failure may have occurred before any HTTP response existed. Keep
On ErroraroundSendand final status access. - HTTP error mistaken for COM failure: a 404 or 500 can complete normally; inspect
Status. - XML cannot be parsed: transport success does not guarantee valid XML. For
DOMDocument, inspectparseErrorafter completion; see Microsoft’s XML parsing documentation. - Stale result from an earlier request: prevent overlapping requests or attach an identifier to each retained request and handler.
Which approach should you choose?
| Need | Best fit |
|---|---|
| Simplest VB6 implementation | Timer polling |
| Callback-style VB6 design | Wrapper class with a default procedure |
| Asynchronous XML file loading | DOMDocument with WithEvents |
| VBScript callback | GetRef |
| Modern VB.NET application | HttpClient with Async/Await |
MSXML2.XMLHTTP60 and MSXML2.ServerXMLHTTP60 are related but distinct interfaces. Choose based on the client or service networking context, proxy and timeout requirements, and target environment rather than assuming one is universally faster or better. The techniques above come from archived MSXML/VB6 guidance and are legacy-platform patterns, not the normal design for current .NET applications.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

