The response from Stack Exchange is always compressed, as indicated by Glorfindel.
Note that browsers offer the decompression to you by default but the MSXML2.serverXMLHTTP COM/OLE component pre-dates the modern compression habits. It simply lacks the option to cope with that kind of responses.
If you inspect the responseHeader "Content-Encoding" after you called send
like so:
MsgBox xh.getResponseHeader("Content-Encoding")
You will see gzip
as an answer.
You can indicate to the server with a RequestHeader Accept-Encoding what encoding/compression you support. Add this line before the send
method:
xh.setRequestHeader "Accept-Encoding", "deflate;q=1.0"
and you'll get deflate
as Content-Encoding response.
According to the HTTP specification identity
is a valid Accept-Encoding and should instruct the server to not use compression. This is where our luck runs out as the Stack Exchange server is non-compliant here. It simply falls back to its preferred default compression: gzip. I think SE should return a 406 Not Acceptable in this case, but meh.
Given that we can't tell the server to send a plain response, we have to somehow decompress the received response body. After some searching I found How to decompress http responses in vba excel? by user Mavin which has a complete native VBA module with an Inflate method.
I'm not sure how recent the Excel is you have but when testing this on Excel 2010 I ran into a problem with the use of Application.WorksheetFunction.Bitlshift
in the checkgzip
function which doesn't exist in older Excel versions. I have replaced that line with
decompressedsize = size(3) * 2 ^ 32 + size(2) * 2 ^ 16 + size(1) * 2 ^ 8 + size(0)
to achieve the same result.
My whole main program now looks like:
Dim xh As Object
Set xh = CreateObject("MSXML2.serverXMLHTTP")
seurl = "https://api.stackexchange.com/2.3/tags?order=desc&sort=popular&site=stackoverflow"
xh.Open "GET", seurl, False
xh.setRequestHeader "Accept-Encoding", "gzip;q=1.0"
xh.Send
MsgBox xh.getResponseHeader("Content-Encoding")
Dim httpresponse() As Byte
httpresponse = xh.responseBody
Mod_Inflate64.Inflate httpresponse
MsgBox StrConv(httpresponse, vbUnicode)
and when run this is the result: