Foolproof way to detect if iframe is cross domain
Solution 1
You need to do a little more than what's in your try/catch to handle different browsers and to handle different ways that browsers deal with cross domain access:
function canAccessIFrame(iframe) {
var html = null;
try {
// deal with older browsers
var doc = iframe.contentDocument || iframe.contentWindow.document;
html = doc.body.innerHTML;
} catch(err){
// do nothing
}
return(html !== null);
}
In your example, this would be:
var accessAllowed = canAccessIFrame(document.getElementsByTagName('iframe')[0]);
Working demo: http://jsfiddle.net/jfriend00/XsPL6/
Tested in Chrome 21, Safari 5.1, Firefox 14, IE7, IE8, IE9.
Solution 2
A more shorter and more readable function for modern browsers
function canAccessIframe(iframe) {
try {
return Boolean(iframe.contentDocument);
}
catch(e){
return false;
}
}
Tested with Chrome 79 and Firefox 52 ESR.
Explanation: you can check any iframe property that is not accessible cross-origin and convert to boolean. example: contentDocument / contentWindow.document / location.href / etc.
Boolean docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean
Related videos on Youtube
user730569
Updated on June 03, 2022Comments
-
user730569 almost 2 years
I'm trying to determine if any iframe is cross-domain or not. According to the accepted answer in this question: Detect when iframe is cross-domain, then bust out of it it says to put the code accessing the
contentDocument
of the iframe in atry / catch
block. I tried this for a cross-domain iframe in Chrome:try { document.getElementsByTagName('iframe')[0].contentDocument; } catch(err){ console.log("called"); }
and it still throws the cross-domain error and does not catch the error.
I also tried to check if the protocol + host + port of the parent page url is in the
src
of the iframe:function thirdPartyIframe(iframe){ var url = document.location.protocol + "//" + document.location.hostname + (document.location.port === "" ? "" : ":" + document.location.port); var regexp = new RegExp(url.replace(/\//g, "\\/").replace(/\./g, "\\.")); if (iframe.src === '' || regexp.test(iframe.src)){ return false; } else { return true; } }
but this does not seem to work for the first iframe on the homepage of Facebook with
src
equal to (it's long):"http://www.facebook.com/ai.php?aed=AQLlH2cfdnsnLrDUVyqrQPlWpayw9N09Z_iNuhulevbeEfVa4mcVRcT8cjAZOjQb8y1QXab5Ae3aSEJx49U_Qv35rtSp1VC9cY0_CrpOjMDk40hS_Xm57A996YtRVCcWSuRZ_jZERQ_iA_E4621NAbKHT9dsB7uElkRtTvl5K-zPI0jeH-BEnlZIOXbeEdbRC6qCwoToaltolpe-Ot2KWgkfb_vBZYpzUc3jQoEHzLG6tauO9l_hkXpYpHxnt-KYFKIFZ1PgmrHgb0UcGjeKHl7yBR1AbW2n5XgdgaAhFvBjs5GZlKy566nvl8eLRA60orwkwtWYeN8-gKoAmOLm7-6minsWn8lk1h2Qn3p07HCTSnYHfv1aJ6mF5jmuzP0YYe7Ym9ZbmK-tvax4uPAQJ2OdULilKbEh8M-2V9pVY3AC228OPlrRullZuuOg8DI2A8WeMF-fbbOdOFFVCe5Gj1CaZu3LYXiqdG7mUgY6AEpk9ZzGT4fC2K8DInQo1AypCvzG64C_bEWfODeXe0aGbkWwsUUmO7E5HFg0tvZkK5IAR_xxxQ2rlf5jbcEDo_2gdIDdHe1HT75-SJLUsSA0M8EU01oNNPuWwEC2BW6inepc9QPuqeg42tcEbKLU-rIUnXDBLvgutft8azWPPQ6_LafGjCAmC9uTalagoWLLDMpQOThvPg7YeVd7qg_c9Mzn2GAfuswcxDSxyRIZo9MaOhA6mhfXeE1tmjyBBsMxnx08tO21Jsfgch59fmMxpeJzdsNMPK3FAojfglvCQ2Zrt_6ataexUB4xlM7_PhKrfBPtxb5fe2TE9-nlWruNEpoCrzI05yv4Go3CYEWHob06K_9iICfNVTFkSYGTiJnMXCy_fdgfyzUIn5QJIPRo4-Wnyg444zKAO_nyFW59LqbIanHVfFY6ybiA6KeC3meREWzTPSsrU5d_NbYHlJWb8uPNDR04jaH5e2qiYj3Y8qgLQA5m"
My function classifies it as not a third party iframe, but Chrome still throws the cross-domain error when I access its
contentDocument
.I'm looking for a foolproof, cross-browser way to do this.
-
user730569 over 11 yearsok this seems to work but it still throws an error in the console in chrome, i'm guessing it doesn't matter though
-
jfriend00 over 11 yearsYes, it throws the error, but the error is caught by your code so it does not matter. That's how you find out if you can access it or not.
-
Bluu over 10 yearsChrome throws and logs its own error, seemingly uncatchable by this snippet's try..catch. I would say it does matter. I don't want to spam the console with errors, when I safely test iframe access and workaround it.
-
user56reinstatemonica8 about 10 yearsWhat would be a safe equivalent of this going the other direction, from the embedded content testing if the parent is cross-domain or same domain? I've asked this as a separate question if anyone is interested: Foolproof way to detect if this page is INSIDE a cross-domain iframe
-
Hexodus over 3 yearsGood one! But you can shorten it to
!!(iframe.contentDocument)
as well. -
Hexodus over 3 yearsThis seems not to work if you try to embed an https website which is strange...
-
luek baja about 3 years@Hexodus You can also remove the parentheses
-
strix25 over 2 yearsyeah this does not work at all