5

I want to get an iframe as frame and click an element in the frame, but the iframe does not have a name and the website has many frames (page.frames() returns 14).

And I don't have permission to edit html. I can only edit the JavaScript.

I think the best way to identify the iframe in this case is from its parent element.

How can I do this with puppeteer?

<div id="foo">
  <iframe>
    #document
  </iframe>
</div>
Thomas Dondorf
  • 23,416
  • 6
  • 84
  • 105
invalid
  • 1,215
  • 4
  • 13
  • 30

3 Answers3

10

You can use the elementHandle.contentFrame() function to return a frame from an element handle.

Quote from the docs:

Resolves to the content frame for element handles referencing iframe nodes, or null otherwise

Example:

const elementHandle = await page.$('div#foo iframe');
const frame = await elementHandle.contentFrame();
Thomas Dondorf
  • 23,416
  • 6
  • 84
  • 105
  • 1
    great! I solved this with frame´s url, but your way is better. I will fix my code. thank you. – invalid Apr 29 '19 at 16:07
9

Note that you should also add these browser startup options to run contentFrame method, otherwise it will return null:

const browser = await puppeteer.launch({
    headless: false,
    args: [
      '--disable-web-security',
      '--disable-features=IsolateOrigins,site-per-process'
    ]
});
Ilya Shevyryaev
  • 756
  • 6
  • 8
  • See [Puppeteer iframe contentFrame returns null](https://stackoverflow.com/questions/65049531/puppeteer-iframe-contentframe-returns-null) for the full post of this answer – ggorlen Aug 10 '21 at 18:26
1

Having an id of any element you can easily loop through its children and find all, that fulfill specific criteria, for example being an iframe.
Filter function cannot be used, since this is not an Array, but a NodeList.

var parent = document.getElementById("foo");
var iframes = [];
for(var i = 0; i < parent.children.length; i++){
  var child = parent.children[i];
  if(child.localName == 'iframe'){
    iframes.push(child);
  }
  };
console.log(iframes)
<div id="foo">
  <iframe>
    #document
  </iframe>
</div>
matvs
  • 1,763
  • 16
  • 26
  • thank you. But in this way, how can I click a iframe? – invalid Apr 29 '19 at 12:01
  • For a given element click() function should work, and you can use content​Document in order to get iframe's nodes. – matvs Apr 29 '19 at 12:24
  • noooo... I wrote this `const parent = document.getElementById('foo'); const framedom = parent.children[0].contentDocument;` and `framedom` is null. Is this wrong? – invalid Apr 29 '19 at 13:40
  • Are you trying this on real life example? Because for an example above it can be null, since it is not really #document. – matvs Apr 29 '19 at 14:41