How to identify if a webpage is being loaded inside an iframe or directly into the browser window?

382,024

Solution 1

Browsers can block access to window.top due to same origin policy. IE bugs also take place. Here's the working code:

function inIframe () {
    try {
        return window.self !== window.top;
    } catch (e) {
        return true;
    }
}

top and self are both window objects (along with parent), so you're seeing if your window is the top window.

Solution 2

When in an iframe on the same origin as the parent, the window.frameElement method returns the element (e.g. iframe or object) in which the window is embedded. Otherwise, if browsing in a top-level context, or if the parent and the child frame have different origins, it will evaluate to null.

window.frameElement
  ? 'embedded in iframe or object'
  : 'not embedded or cross-origin'

This is an HTML Standard with basic support in all modern browsers.

Solution 3

RoBorg is correct, but I wanted to add a side note.

In IE7/IE8 when Microsoft added Tabs to their browser they broke one thing that will cause havoc with your JS if you are not careful.

Imagine this page layout:

MainPage.html
  IframedPage1.html   (named "foo")
  IframedPage2.html   (named "bar")
    IframedPage3.html (named "baz")

Now in frame "baz" you click a link (no target, loads in the "baz" frame) it works fine.

If the page that gets loaded, lets call it special.html, uses JS to check if "it" has a parent frame named "bar" it will return true (expected).

Now lets say that the special.html page when it loads, checks the parent frame (for existence and its name, and if it is "bar" it reloads itself in the bar frame. e.g.

if(window.parent && window.parent.name == 'bar'){
  window.parent.location = self.location;
}

So far so good. Now comes the bug.

Lets say instead of clicking on the original link like normal, and loading the special.html page in the "baz" frame, you middle-clicked it or chose to open it in a new Tab.

When that new tab loads (with no parent frames at all!) IE will enter an endless loop of page loading! because IE "copies over" the frame structure in JavaScript such that the new tab DOES have a parent, and that parent HAS the name "bar".

The good news, is that checking:

if(self == top){
  //this returns true!
}

in that new tab does return true, and thus you can test for this odd condition.

Solution 4

I'm not sure how this example works for older Web browsers but I use this for IE, Firefox and Chrome without an issue:

var iFrameDetection = (window === window.parent) ? false : true;

Solution 5

if ( window !== window.parent ) 
{
      // The page is in an iframe   
} 
else 
{     
      // The page is not in an iframe   
}
Share:
382,024
akshat
Author by

akshat

Updated on July 08, 2022

Comments

  • akshat
    akshat almost 2 years

    I am writing an iframe based facebook app. Now I want to use the same html page to render the normal website as well as the canvas page within facebook. I want to know if I can determine whether the page has been loaded inside the iframe or directly in the browser?

  • akshat
    akshat over 15 years
    This seems to work fine in Firefox. Does it work in other browsers too?
  • sglessard
    sglessard about 12 years
    Having a page with an iframe within an iframe, to test from my child iframe if my parent iframe was embeded in the page, I used if (parent === top)
  • Gaurang Jadia
    Gaurang Jadia almost 12 years
    @sglessard If the child page and parent are from different domains then Firefox will complain for Same Origin Policy (www.w3.org/Security/wiki/Same_Origin_Policy) and code won't work
  • Ansel Halliburton
    Ansel Halliburton over 11 years
    Has the bug been fixed in the meantime? I can't reproduce it in IE8. I always get the correct window.parent.
  • scunliffe
    scunliffe over 11 years
    Not sure - I'll run my test suite against IE9 and below again and post an update.
  • Marius Balčytis
    Marius Balčytis about 11 years
    Your redirect will work when you're not if frame. So I would not be able to navigate in your site. Secondly, techniques exists to prevent from redirecting from the parent page.
  • Luke
    Luke almost 11 years
    Why do you do this: .indexOf("HTMLIFrameElement") ?
  • piotr_cz
    piotr_cz over 10 years
    To add to Eneko Alonso: this works (parent.location == self.location)
  • jeremysawesome
    jeremysawesome over 10 years
    This works in IE 11, 10, and 9 for me. Also it works in FF and Opera as well as, of course, Chrome. I haven't run into any issues with it.
  • Chuck Kollars
    Chuck Kollars over 10 years
    .indexOf('foobarbaz') > -1 is a way to check for "substring match" (i.e. can 'foobarbaz' be found somewhere within the string?), but without using regular expressions. It's logically equivalent to .match(/foobarbaz/). It (used to:-) work on a wider range of browsers, and still may be used either out of habit or because of fears about the performance of regular expression machinery.
  • Rob W
    Rob W over 10 years
    Try document.defaultView.self === document.defaultView.top or window !== window.top. In Firefox's add-on SDK's content script, the global self object is an object used to communicate with the main script.
  • Dan
    Dan over 10 years
    @MNVOH, tripple check this in IE8
  • Dan
    Dan over 10 years
    @MNVOH Updated the solution, please check it out.
  • Dan
    Dan over 10 years
    @piotr_cz, it works only if same-origin policy allows access to parent.location. Otherwise an exception is thrown
  • Mike
    Mike over 10 years
    The last update is causing an error for me. Doesn't catch require a parameter?
  • TommyAutoMagically
    TommyAutoMagically over 10 years
    Yeah, I'm pretty sure catch requires a parameter... Not working as-is for me, either.
  • Jabran Saeed
    Jabran Saeed about 10 years
    This will fail if origins match. Window.top will be available to the iframe.
  • Percy
    Percy over 8 years
    Not a very elegant solution to determining whether or not the window is inside an iframe or not, and there's no guarantee you'll be able to read from parent.frames either.
  • Andrew Richard Miller
    Andrew Richard Miller over 8 years
    I thought this wasn't working on IE11 (Windows 7), unless I enabled the dev console; then it did work. Turns out my code had a "console.log" to show me what was happening in the logic, and it looks like IE11 throws if you call console.log and there is no console attached. Without logging, this works for me in Chrome, Firefox, IE11 and Safari (Windows 7 and OSX where appropriate).
  • Oriol
    Oriol about 8 years
    Note attempting to read frameElement will throw a SecurityError exception in cross-origin iframes, according to W3C (WHATWG says it should return null instead). So you might want to wrap it inside a try...catch statement.
  • MarkosyanArtur
    MarkosyanArtur over 7 years
    in chrome in main window context window.parent === window is true. So your answer is incorrect. And this comparsion could be used for check (at least in chrome, didn't test it in another browsers).
  • Jeromy French
    Jeromy French about 7 years
    For those still rocking the latest in 1995 tech, window.self !== window.top returns true when run from within contents of frame, or iframe.
  • CalculatorFeline
    CalculatorFeline about 7 years
    Or simply !(window===window.parent)
  • OlehZiniak
    OlehZiniak over 6 years
    getting null inside and outside of iframe
  • Aaronius
    Aaronius over 6 years
    "Browsers can block access to window.top due to same origin policy." Are you sure? It can block access to properties on window.top, but my understanding is it won't block access to window.top itself. The page you linked to seems to back this up (see Cross-origin script API access).
  • xeophin
    xeophin over 6 years
    The description at MDN says that "if the document into which it's embedded has a different origin (such as having been located from a different domain), this is null."
  • www-0av-Com
    www-0av-Com about 6 years
    DOES NOT WORK in context of iFrame, but ` if(window === window.parent){ ` does. I'm not marking you down as I don't know why it doesn't work
  • Ivan Leonenko
    Ivan Leonenko almost 6 years
    window !== window.parent
  • Art3mix
    Art3mix over 5 years
    Just to clerify what the return should be: Returns the element (such as <iframe> or <object>) in which the window is embedded, or null if the element is either top-level or is embedded into a document with a different script origin; that is, in cross-origin situations.
  • phillyslick
    phillyslick over 5 years
    @JoshHabdas - I'd like to understand why this is a better approach?
  • vhs
    vhs over 5 years
    @phillyslick in a word: expressiveness.
  • Raymond Nijland
    Raymond Nijland over 5 years
    framing is not the only threat, what about objecting (meaning using HTML5 object tag which replaces iframe tag).. i think this will not work against that..
  • Skitterm
    Skitterm almost 5 years
    @JoshHabdas frameElement will give false-positives if page is embedded into a page on another origin: "returns... null if the element is either top-level or is embedded into a document with a different script origin; that is, in cross-origin situations." developer.mozilla.org/en-US/docs/Web/API/Window/frameElement
  • vhs
    vhs almost 5 years
    @Skitterm thank you. now I see why this approach is better.
  • mkoryak
    mkoryak almost 4 years
    except when you open an iframe of your own website.
  • Michael Scheper
    Michael Scheper about 3 years
    It's 2021, and I'm still dancing on IE's grave.
  • scunliffe
    scunliffe about 3 years
    Sadly I'm still supporting IE... though I will definitely be celebrating the day that I no longer have to. ;-)
  • Ivan
    Ivan almost 3 years
    Works like a charm including on same-domain nested iframes. Thanks a lot!
  • mikep
    mikep almost 3 years
    iFrameDetection returns false positive in case of popup window. So to detect iframe correctly it should be var iFrameDetection = (window === window.parent || window.opener) ? false : true;
  • mikep
    mikep almost 3 years
    @CalculatorFeline I prefer explicit statement as author wrote because it is quicker to understand at first look so code is less buggy. Minificator tools do this job for me to rewrite it in shortest way when deployed. Why I should write minified code which is worse readable for humans?
  • CalculatorFeline
    CalculatorFeline almost 3 years
    What about Ivan's suggestion to use !==?
  • TheMaster
    TheMaster over 2 years
    @Percy why not? Isn't window.frames is allowed cross origin property?
  • iamskok
    iamskok over 2 years
    @james-gentes @greg can you explain in which situation window.self !== window.top will throw an error?
  • Noitidart
    Noitidart almost 2 years
    window.self is undefined for me, is this normal? im using latest Firefox. I ended up doing const isIframe = window !== window.parent