puppeteerchrome-devtools-protocol

Get nodeIds of elements within iframe using chrome dev tools protocol


Chrome Devtools Protocol DOM.querySelectorAll returns all nodeIs of the elements in the html. But it does not return the id's of the iframe contents. Is there a way to get them ?

const doc = await page._client.send('DOM.getDocument');
const result = await page._client.send('DOM.querySelectorAll', {nodeId: doc.root.nodeId, selector: '*'});
        
<!-- Host Page -->
<!DOCTYPE html>
<html lang="en">
<body>
    <div>Hello World</div>
    <iframe src="demo.html" frameborder="0"></iframe>
</body>
</html>


<!-- IFrame Page -->
<!DOCTYPE html>
<html lang="en">
<body>
    <!-- I need to access this div from dev tools -->
    <div>Demo Page</div> 
</body>
</html>

Solution

  • Found the answer in this gist

    async function findElementInIframe(DOM, iframeSelector, elementSelector) {
        const doc = await DOM.getDocument({depth: 0});
    
        const iframeQueryResult = await DOM.querySelector({nodeId: doc.root.nodeId, selector: iframeSelector});
        const iframeDescription = await DOM.describeNode({nodeId: iframeQueryResult.nodeId});
    
        const contentDocRemoteObject = await DOM.resolveNode({backendNodeId: iframeDescription.node.contentDocument.backendNodeId});
        const contentDocNode = await DOM.requestNode({objectId: contentDocRemoteObject.object.objectId});
    
        const elementQueryResult = await DOM.querySelector({nodeId: contentDocNode.nodeId, selector: elementSelector});
        return await DOM.describeNode({nodeId: elementQueryResult.nodeId});
    }