Skip to content

Navigating IFrames ​

Modern web applications frequently embed third-party content (like payment gateways, complex captchas, or external video players) using <iframe> elements.

By default, DOM selectors (like id or css chains) cannot cross the boundary from the main page into an iframe. If you try to extract text from a paragraph inside an iframe using a normal BaseStep, the Playwright engine will crash, claiming the element does not exist.

StepWright provides two straightforward parameters—frameSelector and frameSelectorType—to safely bridge this gap.


Interacting Within an IFrame ​

If you need to click a button, type into an input field, or extract data that lives inside an embedded frame, you must provide the locator for the iframe itself alongside the standard object locator.

Example: Extracting Data ​

Imagine an embedded article viewer:

html
<!-- Main Page -->
<div id="container">
    <iframe name="article-viewer" src="...">
        <!-- Inside the IFrame! -->
        <h1 class="title">Hidden Secrets of Web Automaton</h1>
    </iframe>
</div>

To extract that h1.title:

python
from stepwright import BaseStep

BaseStep(
    id="extract_iframe_title",
    action="data",
    
    # 1. Target the actual element you want
    object_type="class",
    object="title",
    key="article_title",
    
    # 2. Tell StepWright where the element is housed
    frameSelectorType="name",
    frameSelector="article-viewer"
)

StepWright handles the Playwright page.frame_locator() context-switching for you behind the scenes.


Deep Actions Inside IFrames ​

The frameSelector logic supports all interactive actions as well, such as filling out an embedded payment or login form.

python
# Type into an embedded username field
BaseStep(
    id="fill_embedded_login",
    action="input",
    
    object_type="id",
    object="username-input",
    value="admin",
    
    frameSelectorType="css",
    frameSelector="iframe#auth-module"
)

Dealing with Nested IFrames ​

If the architecture is wildly complex (an iframe inside an iframe), it is often cleaner to write a raw Custom Callback that utilizes native Playwright locators rather than passing deeply chained frameSelector strings.

python
def deep_iframe_interaction(page, collector, step):
    # Native playwright access
    frame = page.frame_locator('#parent').frame_locator('#child')
    text = frame.locator('p.content').text_content()
    collector['deepMsg'] = text

BaseStep(id="nested", action="custom", callback=deep_iframe_interaction)

Released under the MIT License.