Q23 of 48 · Cypress
How do you handle iframes in Cypress?
Short answer
Short answer: Get the iframe element, drill into its document via `.its('0.contentDocument.body').then(cy.wrap)`, and continue chaining inside it. `cypress-iframe` plugin wraps this. Same-origin iframes work well; cross-origin needs `cy.origin` and is more constrained.
Detail
Cypress doesn't have a first-class iframe API like Selenium's switchTo().frame() or Playwright's frameLocator. The pattern uses jQuery to dig into the iframe's body:
cy.get('iframe[name=stripe-card]')
.its('0.contentDocument.body')
.should('not.be.empty')
.then(cy.wrap)
.find('input[name=cardnumber]')
.type('4242 4242 4242 4242');
The should('not.be.empty') is a guard — iframes load asynchronously, and querying before the frame body exists yields an empty subject. The .then(cy.wrap) rewraps the body so subsequent commands chain naturally.
The cypress-iframe plugin wraps this pattern as cy.iframe(selector).find(...), which is more readable for repeated use.
Cross-origin iframes (a Stripe checkout, an embedded YouTube) are restricted because the parent and the iframe are different origins. cy.origin('https://js.stripe.com', () => { ... }) lets you switch context, but with caveats — limited subset of commands, no shared variables. Plan tests around stubbing the third-party at the network layer (cy.intercept) when feasible.
For payment-style iframes specifically, Stripe and similar services provide test card numbers and a sandbox; using them is more reliable than fighting iframe boundaries.
// EXAMPLE
iframe.cy.ts
// Same-origin iframe — manual pattern
it('types in an iframe input', () => {
cy.visit('/embedded-form');
cy.get('iframe[name=embed]')
.its('0.contentDocument.body')
.should('not.be.empty')
.then(cy.wrap)
.find('[data-test=name]')
.type('Alice');
});
// Cross-origin (Stripe)
it('handles a cross-origin iframe with cy.origin', () => {
cy.visit('/checkout');
cy.get('iframe[title="Secure card payment input frame"]').then(($iframe) => {
cy.origin('https://js.stripe.com', { args: { iframe: $iframe[0] } }, () => {
// Limited commands available here
});
});
});