820

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?

asked Nov 28, 2008 at 15:45
2
  • 4
    A few nice ways (including comments): tommcfarlin.com/check-if-a-page-is-in-an-iframe Commented Jan 20, 2019 at 8:03
  • 3
    External links aren't a very good way of answering questions. Especially if the content of those external links can be reduced to return window.location !== window.parent.location. Commented Sep 17, 2021 at 9:05

18 Answers 18

1463

Update (2024):

According to the docs on cross-origin script API access, window.self and window.top are both included in the list of properties that browsers of potentially-different origins can access.

const inIframe = window.self !== window.top;

Previous Answer

Note: 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.

gondo
1,1281 gold badge11 silver badges31 bronze badges
answered Nov 28, 2008 at 15:47
Sign up to request clarification or add additional context in comments.

17 Comments

This seems to work fine in Firefox. Does it work in other browsers too?
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)
@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
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.
For those still rocking the latest in 1995 tech, window.self !== window.top returns true when run from within contents of frame, or iframe.
|
122

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.

CertainPerformance
373k55 gold badges354 silver badges359 bronze badges
answered Sep 7, 2013 at 22:55

6 Comments

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.
getting null inside and outside of iframe
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."
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.
Works like a charm including on same-domain nested iframes. Thanks a lot!
|
46
if ( window !== window.parent ) 
{
 // The page is in an iframe 
} 
else 
{ 
 // The page is not in an iframe 
}
PowerKiKi
4,7955 gold badges42 silver badges48 bronze badges
answered May 4, 2020 at 15:41

4 Comments

except when you open an iframe of your own website.
This was the most straightforward and readable in my opinion.
@mkoryak: I'm actually doing exactly this: Iframing my website into itself at one specific juncture: How can this then be detected reliably ?
It doesn't matter if the iframe points to the same website, the parent and the child are never going to have the same window object.
34

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;
answered Nov 19, 2015 at 9:30

8 Comments

Or simply !(window===window.parent)
window !== window.parent
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;
@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?
What about Ivan's suggestion to use !==?
|
29

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.

answered Nov 28, 2008 at 17:53

4 Comments

Has the bug been fixed in the meantime? I can't reproduce it in IE8. I always get the correct window.parent.
Not sure - I'll run my test suite against IE9 and below again and post an update.
It's 2021, and I'm still dancing on IE's grave.
Sadly I'm still supporting IE... though I will definitely be celebrating the day that I no longer have to. ;-)
21

The accepted answer didn't work for me inside the content script of a Firefox 6.0 Extension (Addon-SDK 1.0): Firefox executes the content script in each: the top-level window and in all iframes.

Inside the content script I get the following results:

 (window !== window.top) : false 
 (window.self !== window.top) : true

The strange thing about this output is that it's always the same regardless whether the code is run inside an iframe or the top-level window.

On the other hand Google Chrome seems to execute my content script only once within the top-level window, so the above wouldn't work at all.

What finally worked for me in a content script in both browsers is this:

 console.log(window.frames.length + ':' + parent.frames.length);

Without iframes this prints 0:0, in a top-level window containing one frame it prints 1:1, and in the only iframe of a document it prints 0:1.

This allows my extension to determine in both browsers if there are any iframes present, and additionally in Firefox if it is run inside one of the iframes.

answered Oct 14, 2011 at 14:32

1 Comment

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.
5

I'm using this:

var isIframe = (self.frameElement && (self.frameElement+"").indexOf("HTMLIFrameElement") > -1);
Chuck Norris
15.2k15 gold badges96 silver badges128 bronze badges
answered Jun 20, 2012 at 10:04

2 Comments

Why do you do this: .indexOf("HTMLIFrameElement") ?
.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.
2

Best-for-now Legacy Browser Frame Breaking Script

The other solutions did not worked for me. This one works on all browsers:

One way to defend against clickjacking is to include a "frame-breaker" script in each page that should not be framed. The following methodology will prevent a webpage from being framed even in legacy browsers, that do not support the X-Frame-Options-Header.

In the document HEAD element, add the following:

<style id="antiClickjack">body{display:none !important;}</style>

First apply an ID to the style element itself:

<script type="text/javascript">
 if (self === top) {
 var antiClickjack = document.getElementById("antiClickjack");
 antiClickjack.parentNode.removeChild(antiClickjack);
 } else {
 top.location = self.location;
 }
</script>

This way, everything can be in the document HEAD and you only need one method/taglib in your API.

Reference: https://www.codemagi.com/blog/post/194

answered Apr 12, 2018 at 9:24

1 Comment

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..
1

Since you are asking in the context of a facebook app, you might want to consider detecting this at the server when the initial request is made. Facebook will pass along a bunch of querystring data including the fb_sig_user key if it is called from an iframe.

Since you probably need to check and use this data anyway in your app, use it to determine the the appropriate context to render.

answered Dec 11, 2008 at 22:04

Comments

1

Use this javascript function as an example on how to accomplish this.

function isNoIframeOrIframeInMyHost() {
// Validation: it must be loaded as the top page, or if it is loaded in an iframe 
// then it must be embedded in my own domain.
// Info: IF top.location.href is not accessible THEN it is embedded in an iframe 
// and the domains are different.
var myresult = true;
try {
 var tophref = top.location.href;
 var tophostname = top.location.hostname.toString();
 var myhref = location.href;
 if (tophref === myhref) {
 myresult = true;
 } else if (tophostname !== "www.yourdomain.com") {
 myresult = false;
 }
} catch (error) { 
 // error is a permission error that top.location.href is not accessible 
 // (which means parent domain <> iframe domain)!
 myresult = false;
}
return myresult;
}
answered Sep 21, 2011 at 2:32

Comments

1

I actually used to check window.parent and it worked for me, but lately window is a cyclic object and always has a parent key, iframe or no iframe.

As the comments suggest hard comparing with window.parent works. Not sure if this will work if iframe is exactly the same webpage as parent.

window === window.parent;
answered Mar 4, 2014 at 3:47

2 Comments

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).
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
1
function amiLoadedInIFrame() {
 try {
 // Introduce a new propery in window.top
 window.top.dummyAttribute = true;
 // If window.dummyAttribute is there.. then window and window.top are same intances
 return !window.dummyAttribute;
 } catch(e) {
 // Exception will be raised when the top is in different domain
 return true;
 }
}
answered Nov 27, 2020 at 8:32

Comments

0

Following on what @magnoz was saying, here is a code implementation of his answer.

constructor() {
 let windowLen = window.frames.length;
 let parentLen = parent.frames.length;
 if (windowLen == 0 && parentLen >= 1) {
 this.isInIframe = true
 console.log('Is in Iframe!')
 } else {
 console.log('Is in main window!')
 }
}
answered Dec 20, 2020 at 16:04

Comments

-2

It's an ancient piece of code that I've used a few times:

if (parent.location.href == self.location.href) {
 window.location.href = 'https://www.facebook.com/pagename?v=app_1357902468';
}
answered Oct 25, 2011 at 3:57

2 Comments

To add to Eneko Alonso: this works (parent.location == self.location)
@piotr_cz, it works only if same-origin policy allows access to parent.location. Otherwise an exception is thrown
-2

If you want to know if the user is accessing your app from facebook page tab or canvas check for the Signed Request. If you don't get it, probably the user is not accessing from facebook. To make sure confirm the signed_request fields structure and fields content.

With the php-sdk you can get the Signed Request like this:

$signed_request = $facebook->getSignedRequest();

You can read more about Signed Request here:

https://developers.facebook.com/docs/reference/php/facebook-getSignedRequest/

and here:

https://developers.facebook.com/docs/reference/login/signed-request/

answered Jun 17, 2013 at 18:08

Comments

-4

This ended being the simplest solution for me.

 <p id="demofsdfsdfs"></p>
<script>
if(window.self !== window.top) {
//run this code if in an iframe
document.getElementById("demofsdfsdfs").innerHTML = "in frame";
}else{
//run code if not in an iframe
document.getElementById("demofsdfsdfs").innerHTML = "no frame";
}
</script>
answered Jul 25, 2018 at 1:15

Comments

-6
if (window.frames.length != parent.frames.length) { page loaded in iframe }

But only if number of iframes differs in your page and page who are loading you in iframe. Make no iframe in your page to have 100% guarantee of result of this code

answered Oct 27, 2012 at 15:31

2 Comments

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.
@Percy why not? Isn't window.frames is allowed cross origin property?
-7

Write this javascript in each page

if (self == top)
 { window.location = "Home.aspx"; }

Then it will automatically redirects to home page.

Alexis Wilke
21.2k11 gold badges111 silver badges183 bronze badges
answered Feb 8, 2013 at 6:15

1 Comment

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.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.