How to identify if a webpage is being loaded inside an iframe or directly into the browser window?
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
}
akshat
Updated on July 08, 2022Comments
-
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 over 15 yearsThis seems to work fine in Firefox. Does it work in other browsers too?
-
sglessard about 12 yearsHaving 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 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 over 11 yearsHas the bug been fixed in the meantime? I can't reproduce it in IE8. I always get the correct
window.parent
. -
scunliffe over 11 yearsNot sure - I'll run my test suite against IE9 and below again and post an update.
-
Marius Balčytis about 11 yearsYour 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 almost 11 yearsWhy do you do this:
.indexOf("HTMLIFrameElement")
? -
piotr_cz over 10 yearsTo add to Eneko Alonso: this works
(parent.location == self.location)
-
jeremysawesome over 10 yearsThis 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 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 over 10 yearsTry
document.defaultView.self === document.defaultView.top
orwindow !== window.top
. In Firefox's add-on SDK's content script, the globalself
object is an object used to communicate with the main script. -
Dan over 10 years@MNVOH, tripple check this in IE8
-
Dan over 10 years@MNVOH Updated the solution, please check it out.
-
Dan over 10 years@piotr_cz, it works only if same-origin policy allows access to
parent.location
. Otherwise an exception is thrown -
Mike over 10 yearsThe last update is causing an error for me. Doesn't catch require a parameter?
-
TommyAutoMagically over 10 yearsYeah, I'm pretty sure catch requires a parameter... Not working as-is for me, either.
-
Jabran Saeed about 10 yearsThis will fail if origins match. Window.top will be available to the iframe.
-
Percy over 8 yearsNot 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 over 8 yearsI 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 about 8 years
-
MarkosyanArtur over 7 yearsin 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 about 7 yearsFor those still rocking the latest in 1995 tech,
window.self !== window.top
returnstrue
when run from within contents offrame
, oriframe
. -
CalculatorFeline about 7 yearsOr simply
!(window===window.parent)
-
OlehZiniak over 6 yearsgetting
null
inside and outside ofiframe
-
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 towindow.top
itself. The page you linked to seems to back this up (see Cross-origin script API access). -
xeophin over 6 yearsThe 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 about 6 yearsDOES 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 almost 6 yearswindow !== window.parent
-
Art3mix over 5 yearsJust 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 over 5 years@JoshHabdas - I'd like to understand why this is a better approach?
-
vhs over 5 years@phillyslick in a word: expressiveness.
-
Raymond Nijland over 5 yearsframing 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 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 almost 5 years@Skitterm thank you. now I see why this approach is better.
-
mkoryak almost 4 yearsexcept when you open an iframe of your own website.
-
Michael Scheper about 3 yearsIt's 2021, and I'm still dancing on IE's grave.
-
scunliffe about 3 yearsSadly I'm still supporting IE... though I will definitely be celebrating the day that I no longer have to. ;-)
-
Ivan almost 3 yearsWorks like a charm including on same-domain nested iframes. Thanks a lot!
-
mikep almost 3 years
iFrameDetection
returns false positive in case of popup window. So to detect iframe correctly it should bevar iFrameDetection = (window === window.parent || window.opener) ? false : true;
-
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 almost 3 yearsWhat about Ivan's suggestion to use
!==
? -
TheMaster over 2 years@Percy why not? Isn't
window.frames
is allowed cross origin property? -
iamskok over 2 years@james-gentes @greg can you explain in which situation
window.self !== window.top
will throw an error? -
Noitidart almost 2 years
window.self
is undefined for me, is this normal? im using latest Firefox. I ended up doingconst isIframe = window !== window.parent