QuerySelector for Web Elements Inside iframe
Asked Answered
G

5

93

Edit: New title. What I'm looking for is a document.querySelector for elements inside an iframe.

I've done quite a bit of Googling for an answer and finally I'm stumped.

I'm trying to query inside an iframe. I'm building string selectors to be used in Selenium and usually I just inspect the element with Firebug, and use document.querySelectorAll("theStringIBuid");

But it doesn't work with elements inside iframes. I've tried all of the below to get an element "radiobutton1" inside the "page-iframe" iframe.

var elem1 = ".page-iframe";
console.log(elem1);
var elem2 = ".radiobutton1";
console.log(elem2);
document.querySelectorAll(elem1+elem2+"");

document.querySelectorAll('.page-iframe').contentWindow.document.body.querySelectorAll('.radiobutton1')
document.getElementById('.page-iframe').contentWindow.document.body.innerHTML;

[].forEach.call( document.querySelectorAll('.page-iframe'), 
function  fn(elem){ 
console.log(elem.contentWindow.document.body.querySelectorAll('.radiobutton1')); });

var contentWindow = document.getElementById('.page-iframe').contentWindow 
var contentWindow = document.querySelectorAll('.page-iframe') 
var contentWindow = document.querySelectorAll('.page-iframe')[0].contentWindow

Thanks-

Gormandize answered 29/10, 2014 at 12:35 Comment(4)
Are you maybe running the script before the iframe is done loading? What do you get if you console.log the contentWindow?Obit
If you're using selenium you will need to call switchTo().frame("id of frame") then run your code.Chameleon
Well I've been working on this for two hours now so I think the page is done loading :)Gormandize
And I'm not using Selenium to write the query, I'm trying to write the query in Firebug console. Any idea how to write a console query to access elements inside an iframe?Gormandize
Y
77

simple es6 adapted from h3manth:

document.querySelectorAll('iframe').forEach( item =>
    console.log(item.contentWindow.document.body.querySelectorAll('a'))
)
Yorktown answered 20/3, 2017 at 15:43 Comment(6)
Uncaught SecurityError: Blocked a frame with origin "xxx.xxx.xx" from accessing a frame with origin "google.com". Protocols, domains, and ports must match.", source: xxx.xxx.xx/#! (1)Joker
are you sure the domain in and out the iframe are the same?Yorktown
I don't know about Selenium, but with puppeteer you can pass "--disable-web-security" in the launch args and access cross-origin frames.Precise
Just sharing an working example with typescript: document.getElementById("...")['contentWindow'].document.querySelectorAll("..."). Ty!Salmonberry
Seems like more often then not the iframe does not have the same URL.Hallette
related: to access the shadow DOM of a custom element, you would use elem.shadowRoot instead of iframe.contentWindow.documentViviparous
R
45

if the original page's url isn't at the same domain with the iframe content, the javascript will treat the iframe as a black box, meaning it will not see anything inside it.

Rozanne answered 28/2, 2015 at 6:29 Comment(1)
That is right. See this question: #25098521Leon
C
35

You can do this:

document.querySelector("iframe").contentWindow.document.querySelector("button")

https://m.youtube.com/watch?v=-mNp3-UX9Qc

Canaanite answered 11/2, 2021 at 14:55 Comment(1)
Why contentWindow.document and not just contentDocument?Desensitize
W
9

You can simply use

document.querySelector("iframe").contentDocument.body.querySelector("#btn")

First query selector is to select the iframe. Then we can access ifram dom using content document and use the 2nd query selector to select the element inside iframe.

Wrongly answered 1/4, 2022 at 11:27 Comment(2)
Code-only answers are considered low quality. You should add some text to your answer explaining what you're doing and why it works.Hoffarth
You need to explain your answer.Interval
S
0

Here's a snippet for diving into same-origin frames (ie-compatible ES5):

function findInFramesRec(selector, doc) {
  var hit = doc.querySelector(selector);
  if (hit) return hit;
  var frames = Array.prototype.slice.call(doc.frames);
  for(var i = 0; (i < frames.length) &&   !hit   ; i++) {
    try {
      if (!frames[i] || !frames[i].document) continue;
      hit = findInFramesRec(selector, frames[i].document);
    } catch(e) {}
  }
  return hit;
}

This dives into both frameset frames and iframes alike. It may even survive (though not enter) cross origin frames.

Soapsuds answered 12/7, 2019 at 6:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.