What is window.origin?

Quite an interesting question! 😊

We can start with some investigation - let's see the output from window

console.log(window)

That file is quite big... The Window interface represents a window containing a DOM document; the document property points to the DOM document loaded in that window and describes several features common to the Window and WorkerGlobalScope.

more details here

But then you want to see a very particular property window.origin.

window.origin That one is quite boring for stack overflow (code snippet) as you saw, the json obj returned for window brings:

"origin": "null"

This response is the way the window tell us that the origin is not the same and that we were not allowed the same-origin for that window. Quite common effect for iframe as you deducted yourself!

You also saw that the window.location is less boring... as it contains some more data to it as the Location interface represents the location (URL) of the object it is linked to and the cool thing is that any changes done on it are reflected on the object it relates to. So that is why we don't get a null in here.

window.location...

"location": {
    "ancestorOrigins": {
        "0": "https://stackoverflow.com",
        "length": 1,
        "item": function item() {
            [native code
            ]
        },
        "contains": function contains() {
            [native code
            ]
        }
    },
    "origin": "https://stacksnippets.net",
    ...
}

WindowOrWorkerGlobal.origin returns the origin of the environment, Location.origin returns the origin of the URL of the environment.

Unfortunately Stack-Snippets null-origined frames will make for a confusing example...

At the risk of paraphrasing the specs themselves, let's say we are on https://example.com and from there, we create a new <iframe> element without an src attribute:

var frame = document.createElement("iframe")
frame.onload = function() {
  var frameWin = frame.contentWindow;
  console.log(frameWin.location.href); // "about:blank"
  console.log(frameWin.location.origin) // "null"
  console.log(frameWin.origin) // "https://example.com"
}
document.body.appendChild(frame);

Live example

The location of our frameWin is "about:blank" and its location.origin is "null", because "about:blank" is an opaque origin.

However, the frame's Window frameWin got its own origin set to the one of the parent Window ("https://example.com") which was set when frameWin's browsing context got initialized.


If you wish a little diving into the specs here are the relevant steps for the previous example:

  • At frame creation: https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-iframe-element:about:blank

If the element has no src attribute specified, or its value is the empty string, let url be the URL "about:blank".

  • When creating a new browsing context for frame https://html.spec.whatwg.org/multipage/browsers.html#creating-browsing-contexts:about:blank

If invocationOrigin is not null, and url is about:blank, then return invocationOrigin.

So here it has been determined that origin of the new browsing context is invocationOrigin, i.e the origin of the browsing context that did create frame, while url, used by location, is "about:blank".


Now the case of StackSnippets sandboxed frames is a bit particular in that they do have an src and thus a tuple-origin url, but since their sandbox attribute makes their origin opaque, they'll behave at the inverse of what is exposed in the previous example, making self.origin return "null" and location return the iframe's src's URL.