Foolproof way to detect if iframe is cross domain

19,797

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

Share:
19,797

Related videos on Youtube

user730569
Author by

user730569

Updated on June 03, 2022

Comments

  • user730569
    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 a try / 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
    user730569 over 11 years
    ok this seems to work but it still throws an error in the console in chrome, i'm guessing it doesn't matter though
  • jfriend00
    jfriend00 over 11 years
    Yes, 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
    Bluu over 10 years
    Chrome 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
    user56reinstatemonica8 about 10 years
    What 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
    Hexodus over 3 years
    Good one! But you can shorten it to !!(iframe.contentDocument) as well.
  • Hexodus
    Hexodus over 3 years
    This seems not to work if you try to embed an https website which is strange...
  • luek baja
    luek baja about 3 years
    @Hexodus You can also remove the parentheses
  • strix25
    strix25 over 2 years
    yeah this does not work at all