How to Handle iframe in Cypress: Fix and Best Practices
iframe because it runs in a different document context. To handle iframes, use a custom command to get the iframe's body and then chain Cypress commands inside it.Why This Happens
Cypress runs tests inside the main window document. An iframe loads a separate document, so Cypress commands like cy.get() cannot directly access elements inside it. This causes commands to fail or time out when trying to select iframe content.
cy.get('iframe').find('button').click()
The Fix
To interact with elements inside an iframe, first get the iframe's contentDocument and then its body. Wrap the body with cy.wrap() to use Cypress commands inside the iframe context.
Define a custom command to simplify this process.
Cypress.Commands.add('getIframeBody', (iframeSelector) => { return cy .get(iframeSelector) .its('0.contentDocument.body').should('not.be.empty') .then(cy.wrap) }) // Usage in test cy.getIframeBody('iframe').find('button').click()
Prevention
Always create and reuse a custom command to handle iframes instead of trying to access iframe elements directly. This keeps tests clean and reliable.
- Wait for the iframe body to load before interacting.
- Use
should('not.be.empty')to ensure iframe content is ready. - Keep iframe selectors specific and stable.
Related Errors
Common related errors include:
- Timed out retrying: When Cypress cannot find elements inside the iframe because it tries to access before iframe loads.
- Cross-origin errors: When iframe content is from a different domain, Cypress cannot access it due to browser security.
For cross-origin iframes, consider stubbing or mocking the iframe content or testing it separately.