W3cubDocs

/DOM

XMLHttpRequest.HTML in XMLHttpRequest

The W3C XMLHttpRequest specification adds HTML parsing support to XMLHttpRequest, which originally supported only XML parsing. This feature allows Web apps to obtain an HTML resource as a parsed DOM using XMLHttpRequest.

To get an overview of how to use XMLHttpRequest in general, see Using XMLHttpRequest.

Limitations

To discourage the synchronous use of XMLHttpRequest, HTML support is not available in the synchronous mode. Also, HTML support is only available if the responseType property has been set to "document". This limitation avoids wasting time parsing HTML uselessly when legacy code uses XMLHttpRequest in the default mode to retrieve responseText for text/html resources. Also, this limitation avoids problems with legacy code that assumes that responseXML is null for HTTP error pages (which often have a text/html response body).

Usage

Retrieving an HTML resource as a DOM using XMLHttpRequest works just like retrieving an XML resource as a DOM using XMLHttpRequest, except you can't use the synchronous mode and you have to explicitly request a document by assigning the string "document" to the responseType property of the XMLHttpRequest object after calling open() but before calling send().

var xhr = new XMLHttpRequest();
xhr.onload = function() {
  console.log(this.responseXML.title);
}
xhr.open("GET", "file.html");
xhr.responseType = "document";
xhr.send();

Feature detection

Method 1

This method relies on the "force async" nature of the feature. When you try to set responseType of an XMLHttpRequest object after it is opened as "sync". This throws an error in the browsers that implement the feature and works on others.

function HTMLinXHR() {
  if (!window.XMLHttpRequest)
    return false;
  var req = new window.XMLHttpRequest();
  req.open('GET', window.location.href, false);
  try {
    req.responseType = 'document';
  } catch(e) {
    return true;
  }
  return false;
}

View on JSFiddle

This method is synchronous, does not rely on external assets though it may not be as reliable as method 2 described below since it does not check the actual feature but an indication of that feature.

Method 2

There are two challenges to detecting exactly if a browser supports HTML parsing in XMLHttpRequest. First, the detection result is obtained asynchronously, because HTML support is only available in the asynchronous mode. Second, you have to actually fetch a test document over HTTP, because testing with a data: URL would end up testing data: URL support at the same time.

Thus, to detect HTML support, a test HTML file is needed on the server. This test file is small and is not well-formed XML:

<title>&amp;&<</title>

If the file is named detect.html, the following function can be used for detecting HTML parsing support:

function detectHtmlInXhr(callback) {
  if (!window.XMLHttpRequest) {
    window.setTimeout(function() { callback(false); }, 0);
    return;
  }
  var done = false;
  var xhr = new window.XMLHttpRequest();
  xhr.onreadystatechange = function() {
    if (this.readyState == 4 && !done) {
      done = true;
      callback(!!(this.responseXML && this.responseXML.title && this.responseXML.title == "&&<"));
    }
  }
  xhr.onabort = xhr.onerror = function() {
    if (!done) {
      done = true;
      callback(false);
    }
  }
  try {
    xhr.open("GET", "detect.html");
    xhr.responseType = "document";
    xhr.send();
  } catch (e) {
    window.setTimeout(function() {
      if (!done) {
        done = true;
        callback(false);
      } 
    }, 0);
  }
}

The argument callback is a function that will be called asynchronously with true as the only argument if HTML parsing is supported and false as the only argument if HTML parsing is not supported.

View on JSFiddle

Character encoding

If the character encoding is declared in the HTTP Content-Type header, that character encoding is used. Failing that, if there is a byte order mark, the encoding indicated by the byte order mark is used. Failing that, if there is a <meta> element that declares the encoding within the first 1024 bytes of the file, that encoding is used. Otherwise, the file is decoded as UTF-8.

Handling HTML on older browsers

XMLHttpRequest originally supported only XML parsing. HTML parsing support is a recent addition. For older browsers, you can even use the XMLHttpRequest.responseText property in association with regular expressions in order to get, for example, the source code of an HTML element given its ID:

function getHTML (oXHR, sTargetId) {
  var  rOpen = new RegExp("<(?!\!)\\s*([^\\s>]+)[^>]*\\s+id\\=[\"\']" + sTargetId + "[\"\'][^>]*>" ,"i"),
       sSrc = oXHR.responseText, aExec = rOpen.exec(sSrc);

  return aExec ? (new RegExp("(?:(?:.(?!<\\s*" + aExec[1] + "[^>]*[>]))*.?<\\s*" + aExec[1] + "[^>]*[>](?:.(?!<\\s*\/\\s*" + aExec[1] + "\\s*>))*.?<\\s*\/\\s*" + aExec[1] + "\\s*>)*(?:.(?!<\\s*\/\\s*" + aExec[1] + "\\s*>))*.?", "i")).exec(sSrc.slice(sSrc.indexOf(aExec[0]) + aExec[0].length)) || "" : "";
}

var oReq = new XMLHttpRequest();
oReq.open("GET", "yourPage.html", true);
oReq.onload = function () { console.log(getHTML(this, "intro")); };
oReq.send(null);
Note: This solution is very expensive for the interpreter. Use it only when it is really necessary.

Specifications

Specification Status Comment
XMLHttpRequest Living Standard Initial definition

Browser compatibilityUpdate compatibility data on GitHub

XMLHttpRequest interface

Desktop
Chrome Edge Firefox Internet Explorer Opera Safari
Basic support 1 Yes 1 7 Yes 1.2
onreadystatechange 1 12 1 7
7
Internet Explorer version 5 and 6 supported ajax calls using ActiveXObject()
Yes 1.2
readyState 1 12 1 7 Yes 1.2
response Yes 12 Yes ? Yes Yes
responseText Yes 12 Yes ?
?
Before IE 10, the value of XMLHttpRequest.responseText could be read only once the request was complete.
Yes 10
responseType 31 12 6 10 18 7
responseURL 37 14 32 No 24 8
responseXML Yes 12 Yes
Yes
Prior to Firefox 51, an error parsing the received data added a <parsererror> node to the top of the Document and then returned the Document in whatever state it happens to be in. This was inconsistent with the specification. Starting with Firefox 51, this scenario now correctly returns null as per the spec.
Yes Yes Yes
status 1 12 1 7
7
Internet Explorer version 5 and 6 supported ajax calls using ActiveXObject()
Yes 1.2
statusText 1 12 1 7
7
Internet Explorer version 5 and 6 supported ajax calls using ActiveXObject()
Yes 1.2
timeout 29 12 12 8 17
17
12 — 16
Yes
upload 1 12 Yes ? Yes 10
withCredentials Yes 12 3.5
3.5
Starting with Firefox 11, it's no longer supported to use the withCredentials attribute when performing synchronous requests. Attempting to do so throws an NS_ERROR_DOM_INVALID_ACCESS_ERR exception.
10
10
Internet Explorer versions 8 and 9 supported cross-domain requests (CORS) using XDomainRequest
12 4
abort 18 12 Yes 7
7
5
Implemented via ActiveXObject
Yes 1.2
getAllResponseHeaders 1 12 4
4
Starting from Firefox 49, empty headers are returned as empty strings in case the preference network.http.keep_empty_response_headers_as_empty_string is set to true, defaulting to false. Before Firefox 49 empty headers had been ignored. Since Firefox 50 the preference defaults to true.
7
7
5
Implemented via ActiveXObject
Yes 1.2
getResponseHeader 1 12 Yes
Yes
Starting from Firefox 49, empty headers are returned as empty strings in case the preference network.http.keep_empty_response_headers_as_empty_string is set to true, defaulting to false. Before Firefox 49 empty headers had been ignored. Since Firefox 50 the preference defaults to true.
7
7
5
Implemented via ActiveXObject
Yes 1.2
open 1 12 Yes
Yes
Starting in Firefox 30, synchronous requests on the main thread have been deprecated due to their negative impact on performance and the user experience. Therefore, the async parameter may not be false except in a Worker.
7
7
5
Implemented via ActiveXObject
Yes 1.2
overrideMimeType 1 12 Yes 11
11
5
Implemented via ActiveXObject
Yes 1.2
send 1 12 1 7
7
5
Implemented via ActiveXObject
Yes 1.2
sendAsBinary No
No
There is a polyfill available to support sendAsBinary().
No 2 — 31 No No No
setRequestHeader 1 12 Yes 7
7
5
Implemented via ActiveXObject
Yes 1.2
Mobile
Android webview Chrome for Android Edge Mobile Firefox for Android Opera for Android iOS Safari Samsung Internet
Basic support Yes 18 12 4 Yes ? Yes
onreadystatechange 1 18 Yes 4 Yes ? Yes
readyState Yes 18 Yes 4 Yes ? Yes
response Yes Yes Yes Yes Yes ? Yes
responseText Yes Yes Yes Yes Yes ? Yes
responseType 55 55 Yes 50 Yes ? 6.0
responseURL 37 37 ? 32 24 ? Yes
responseXML Yes Yes Yes Yes
Yes
Prior to Firefox 51, an error parsing the received data added a <parsererror> node to the top of the Document and then returned the Document in whatever state it happens to be in. This was inconsistent with the specification. Starting with Firefox 51, this scenario now correctly returns null as per the spec.
Yes Yes Yes
status Yes Yes Yes 4 Yes ? Yes
statusText Yes 18 Yes 4 Yes ? Yes
timeout Yes Yes Yes Yes Yes ? Yes
upload Yes 18 ? ? Yes ? Yes
withCredentials Yes Yes ? 4
4
Starting with Firefox 11, it's no longer supported to use the withCredentials attribute when performing synchronous requests. Attempting to do so throws an NS_ERROR_DOM_INVALID_ACCESS_ERR exception.
Yes ? Yes
abort Yes Yes Yes Yes Yes ? Yes
getAllResponseHeaders Yes Yes Yes 4
4
Starting from Firefox 49, empty headers are returned as empty strings in case the preference network.http.keep_empty_response_headers_as_empty_string is set to true, defaulting to false. Before Firefox 49 empty headers had been ignored. Since Firefox 50 the preference defaults to true.
Yes ? Yes
getResponseHeader Yes 18 Yes Yes
Yes
Starting from Firefox 49, empty headers are returned as empty strings in case the preference network.http.keep_empty_response_headers_as_empty_string is set to true, defaulting to false. Before Firefox 49 empty headers had been ignored. Since Firefox 50 the preference defaults to true.
Yes ? Yes
open Yes 18 Yes Yes
Yes
Starting in Firefox 30, synchronous requests on the main thread have been deprecated due to their negative impact on performance and the user experience. Therefore, the async parameter may not be false except in a Worker.
Yes Yes Yes
overrideMimeType Yes 18 Yes Yes Yes Yes Yes
send Yes 18 Yes 4 Yes Yes Yes
sendAsBinary No
No
There is a polyfill available to support sendAsBinary().
No
No
There is a polyfill available to support sendAsBinary().
No 4 — 31 No No No
setRequestHeader Yes 18 Yes Yes Yes Yes Yes

See also

© 2005–2018 Mozilla Developer Network and individual contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/HTML_in_XMLHttpRequest