Playwright Frames & iFrames Explained: frameLocator(), Nested Frames & Best Practices (2026)
Reading Time: 20–25 Minutes
Level: Beginner to Advanced
Category: Playwright Tutorial
If you've ever written a Playwright test that couldn't find a button even though it was clearly visible on the page, there's a good chance you were dealing with an iframe.
Frames are one of the most misunderstood topics in browser automation. Many beginners spend hours debugging perfectly valid locators before realizing the element is actually inside another browsing context.
Modern web applications heavily rely on iframes for payment gateways, customer support widgets, embedded dashboards, videos, advertisements, maps, authentication pages, and third-party integrations.
Fortunately, Playwright makes working with frames much easier than traditional automation frameworks through its powerful frameLocator() API.
In this complete guide, you'll learn how frames work, why websites use them, how Playwright interacts with them, and how to automate even complex nested frames confidently.
Table of Contents
- What is a Frame?
- What is an iFrame?
- Frame vs iFrame
- Why Modern Applications Use Frames
- How Browsers Handle Frames
- Why Normal Locators Fail
- Introducing frameLocator()
- Real World Examples
What is a Frame?
A frame is a separate browsing context that allows another HTML document to be displayed inside the current web page.
Think of your browser as a building. The main webpage is the building itself. Each frame is like an independent room inside that building.
Every room has:
- Its own HTML document
- Its own DOM
- Its own JavaScript execution
- Its own CSS styling
Although the rooms are inside the same building, they are isolated from one another.
This isolation improves security and allows different applications to work together without interfering with each other.
What is an iFrame?
An iFrame (Inline Frame) is an HTML element that embeds another webpage inside the current webpage.
Its HTML looks like this:
<iframe
src="https://payments.example.com"
width="600"
height="500">
</iframe>
When the browser loads this page, it also loads the content from the URL specified in the src attribute.
To users, it appears as though everything belongs to the same application. Behind the scenes, however, the browser treats the iframe as a completely separate document.
Frame vs iFrame
| Frame | iFrame |
|---|---|
| General concept of a browsing context | Specific HTML element (<iframe>) |
| Can refer to any browser frame | Embeds another webpage |
| Managed internally by browser | Created by developers using HTML |
In modern web development, the term "frame" usually refers to an iframe. You'll often hear testers and developers use both words interchangeably.
Why Do Modern Applications Use iFrames?
If iframes make automation more difficult, why do developers continue using them?
The answer is security, modularity, and third-party integration.
1. Payment Gateways
Companies such as Stripe and PayPal place sensitive payment fields inside secure iframes.
This prevents the main application from directly accessing users' card information.
Example:
Website
↓
Stripe Card Number Frame
↓
Expiry Date Frame
↓
CVV Frame
2. Authentication
Many websites embed Microsoft, Google, or corporate login pages inside iframes.
Instead of rebuilding authentication from scratch, applications simply embed trusted providers.
3. Chat Widgets
Customer support tools like Intercom, Zendesk, and Freshchat often run inside iframes.
This allows vendors to update their widgets independently without changing the host application.
4. Embedded Dashboards
Business intelligence platforms such as Power BI, Tableau, and Looker frequently expose dashboards through embedded iframes.
Many enterprise applications display reports this way.
5. Google Maps
Location pages commonly embed Google Maps using an iframe.
Instead of building a mapping solution from scratch, developers simply integrate Google's hosted map.
Real-World Examples of iFrames
During enterprise automation projects, you'll encounter iframes in many places.
| Application | Typical Frame Usage |
|---|---|
| E-commerce | Stripe / PayPal Checkout |
| Banking | Secure Payment Screens |
| HRMS | Document Preview |
| CRM | Embedded Reports |
| Learning Platforms | YouTube Videos |
| Support Portals | Live Chat Widgets |
Understanding these patterns helps automation engineers quickly identify when frame handling is required.
Why Normal Playwright Locators Fail
Suppose you inspect a payment form and copy the locator for the "Card Number" field.
await page
.getByPlaceholder(
'Card Number'
)
.fill(
'4111111111111111'
);
At first glance, the locator appears correct.
However, the test fails with an error similar to:
Locator not found
The problem isn't the locator. The problem is that the element exists inside an iframe, not on the main page.
Playwright searches only within the current document unless you explicitly tell it to enter the frame.
This is where frameLocator() becomes essential.
How Browsers See Frames
To understand why this happens, imagine the browser structure like this:
Main Page
│
├── Navigation
├── Products
├── Footer
│
└── Payment iFrame
├── Card Number
├── Expiry Date
└── CVV
The payment fields are not children of the main page's DOM. They belong to an entirely different document.
Because of this separation, Playwright requires a dedicated API to interact with them safely and reliably.
Now that you understand what frames are, why they're used, and why traditional locators fail, it's time to learn the most important Playwright API for frame automation: frameLocator().
Introducing frameLocator()
Playwright introduces the frameLocator() API specifically for interacting with elements inside iframes.
Instead of searching the main document, Playwright first enters the iframe and then searches for elements within it.
Basic syntax:
await page
.frameLocator('iframe')
.getByRole(
'button',
{ name:'Submit' }
)
.click();
Think of frameLocator() as opening the door to another room before interacting with anything inside it.
Main Page
↓
frameLocator()
↓
Find Element
↓
Perform Action
Without entering the frame first, Playwright cannot locate any element inside that browsing context.
Finding an iFrame
Developers identify iframes in several different ways.
By ID
await page
.frameLocator(
'#payment-frame'
)
.getByPlaceholder(
'Card Number'
)
.fill(
'4111111111111111'
);
By CSS Selector
await page
.frameLocator(
'.payment-frame'
)
.getByRole(
'button',
{
name:'Pay'
}
)
.click();
By Name Attribute
await page
.frameLocator(
'iframe[name="payment"]'
)
.getByRole(
'button',
{
name:'Continue'
}
)
.click();
Generic iframe Selector
await page
.frameLocator(
'iframe'
)
.getByText(
'Welcome'
)
.click();
This works only if the page contains a single iframe. If multiple iframes exist, always use a more specific selector.
Your First frameLocator() Example
Imagine an online shopping website where payment details are entered inside a Stripe payment frame.
await page.goto('/checkout');
await page
.frameLocator(
'#card-frame'
)
.getByPlaceholder(
'Card number'
)
.fill(
'4111111111111111'
);
Here, Playwright automatically switches to the iframe before locating the card number field.
Working with Multiple Elements Inside the Same Frame
Once you've entered a frame, you can interact with multiple elements without repeatedly switching contexts.
const paymentFrame =
page.frameLocator(
'#payment-frame'
);
await paymentFrame
.getByPlaceholder(
'Card Number'
)
.fill(
'4111111111111111'
);
await paymentFrame
.getByPlaceholder(
'MM / YY'
)
.fill(
'12/30'
);
await paymentFrame
.getByPlaceholder(
'CVC'
)
.fill(
'123'
);
This approach keeps your tests cleaner and easier to maintain.
Nested Frames
Some enterprise applications contain frames inside other frames.
This structure is called Nested Frames.
Main Page
│
└── Frame A
│
└── Frame B
│
└── Submit Button
To interact with deeply nested elements, chain frame locators together.
await page
.frameLocator('#frame-a')
.frameLocator('#frame-b')
.getByRole(
'button',
{
name:'Submit'
}
)
.click();
Each frameLocator() moves one level deeper into the frame hierarchy.
Real Banking Example
Many banking portals display secure transaction confirmation pages inside iframes.
await page.goto('/transfer');
const secureFrame =
page.frameLocator(
'#secure-frame'
);
await secureFrame
.getByLabel(
'OTP'
)
.fill(
'123456'
);
await secureFrame
.getByRole(
'button',
{
name:'Verify'
}
)
.click();
This ensures sensitive data remains isolated while still allowing reliable automation.
Dynamic Frames
Some applications create iframes only after user interaction.
For example:
Click Checkout
↓
Payment Frame Appears
↓
Enter Card Details
Playwright automatically waits for the iframe to become available before interacting with it.
await page
.getByRole(
'button',
{
name:'Checkout'
}
)
.click();
await page
.frameLocator(
'#payment-frame'
)
.getByPlaceholder(
'Card Number'
)
.fill(
'4111111111111111'
);
No manual wait is required because Playwright's built-in waiting mechanisms handle the synchronization.
frameLocator() vs locator()
| locator() | frameLocator() |
|---|---|
| Searches the main page DOM | Searches inside an iframe |
| Cannot access iframe content | Specifically designed for iframe interactions |
| Used for regular page elements | Used for embedded documents |
A simple rule to remember:
- If the element is on the main page, use
locator(). - If the element is inside an iframe, use
frameLocator().
Best Practices When Working with Frames
- Always identify the iframe before writing locators.
- Store frequently used frames in variables for better readability.
- Avoid generic
iframeselectors on pages with multiple frames. - Use accessibility locators inside frames whenever possible.
- Trust Playwright's auto-waiting instead of adding manual delays.
Following these practices makes your tests easier to understand and significantly reduces maintenance when the application evolves.
Real-World Example 1: Automating Stripe Payment Forms
One of the most common iframe scenarios every automation engineer encounters is Stripe Checkout.
For security reasons, Stripe places each sensitive input field inside its own iframe. This means the card number, expiry date, and CVV are not part of your application's DOM.
A simplified structure looks like this:
Checkout Page
│
├── Name
├── Email
├── Billing Address
│
├── Card Number Frame
├── Expiry Date Frame
└── Security Code Frame
Since every field belongs to a different iframe, you must access each one individually.
await page
.frameLocator('iframe[title="Secure card number input frame"]')
.getByPlaceholder('1234 1234 1234 1234')
.fill('4242424242424242');
await page
.frameLocator('iframe[title="Secure expiration date input frame"]')
.getByPlaceholder('MM / YY')
.fill('12/30');
await page
.frameLocator('iframe[title="Secure CVC input frame"]')
.getByPlaceholder('CVC')
.fill('123');
Notice that Playwright never switches browser context manually. Each call automatically interacts with the correct iframe.
Real-World Example 2: PayPal Checkout
Many e-commerce websites integrate PayPal using embedded frames.
Typical workflow:
Product Page
↓
Checkout
↓
PayPal Popup
↓
Login Frame
↓
Payment Confirmation
Example:
const paypalFrame =
page.frameLocator(
'iframe[title="PayPal"]'
);
await paypalFrame
.getByLabel('Email')
.fill('customer@example.com');
await paypalFrame
.getByRole(
'button',
{
name:'Next'
}
)
.click();
This approach works even though the PayPal login form is hosted outside your application.
Real-World Example 3: Google Maps
Many company websites embed Google Maps inside an iframe on the Contact Us page.
Although testers rarely interact with the map itself, validating its presence is a common functional test.
await expect(
page
.frameLocator('iframe')
.getByText('Map')
).toBeVisible();
Another practical validation is checking that the iframe loads successfully and is visible to users.
Real-World Example 4: Customer Support Chat Widgets
Enterprise applications frequently integrate support platforms such as:
- Intercom
- Zendesk
- Freshchat
- Crisp
- Tawk.to
These widgets usually appear as floating chat icons positioned in the bottom-right corner of the screen.
Internally, they run inside iframes.
const chatFrame =
page.frameLocator(
'iframe'
);
await chatFrame
.getByRole(
'button',
{
name:'Open Chat'
}
)
.click();
After opening the chat:
await chatFrame
.getByPlaceholder(
'Type your message'
)
.fill(
'Hello!'
);
Real-World Example 5: HRMS Document Preview
Human Resource Management Systems often display uploaded resumes and documents inside embedded viewers.
Instead of downloading files, organizations preview them using PDF viewers inside iframes.
const resumeFrame =
page.frameLocator(
'#resume-viewer'
);
await expect(
resumeFrame
.getByText(
'John Smith'
)
).toBeVisible();
This confirms that the uploaded document loaded successfully.
Real-World Example 6: Embedded Business Dashboards
Business Intelligence platforms such as Power BI, Tableau, and Looker commonly expose dashboards through iframes.
Example automation:
const dashboard =
page.frameLocator(
'#analytics-frame'
);
await expect(
dashboard
.getByText(
'Sales Summary'
)
).toBeVisible();
You can also validate KPIs, charts, and filters inside the embedded report.
Handling Multiple Frames on the Same Page
Some enterprise pages contain several iframes simultaneously.
Main Page
│
├── Advertisement Frame
├── Chat Widget Frame
├── Payment Frame
└── Dashboard Frame
Instead of selecting the first iframe found, always target the correct one using unique attributes such as:
- id
- name
- title
- CSS class
- data-testid
Specific selectors reduce maintenance and make tests easier to understand.
Common Mistakes Beginners Make
Using page.locator() Instead of frameLocator()
await page
.locator('#card-number')
.fill('4111111111111111');
This fails because the element belongs to an iframe.
Using Generic iframe Selectors
page.frameLocator('iframe')
If several iframes exist, this may interact with the wrong one.
Always choose a meaningful selector whenever possible.
Adding Manual Waits
await page.waitForTimeout(5000);
Playwright already waits for frames to become available. Hard waits only make tests slower and less reliable.
Enterprise Best Practices
- Use
frameLocator()instead of manually switching contexts. - Store frequently used frame locators in variables or Page Objects.
- Prefer accessibility-based locators inside frames.
- Avoid fragile XPath expressions.
- Trust Playwright Auto-Waiting.
- Keep frame interactions small and reusable.
- Create dedicated helper methods for payment flows.
- Always validate successful interaction with assertions.
Following these practices results in automation suites that are easier to maintain and far more reliable in production environments.
Selenium vs Playwright: Frame Handling Comparison
If you've previously worked with Selenium, you'll immediately notice how much simpler Playwright makes frame automation.
In Selenium, automation engineers typically switch between frames manually before interacting with elements. Forgetting to switch to the correct frame often results in NoSuchElementException or similar errors.
Playwright removes most of this complexity with the frameLocator() API, making frame interactions cleaner and easier to read.
| Feature | Selenium | Playwright |
|---|---|---|
| Switch to Frame | driver.switchTo().frame() | frameLocator() |
| Nested Frames | Manual Switching | Simple Chaining |
| Auto Waiting | Requires Explicit Waits | Built-In |
| Code Readability | Moderate | Excellent |
| Maintenance | Higher | Lower |
Debugging Frame Issues
When a locator doesn't work, don't immediately assume the locator is wrong.
Instead, ask yourself:
- Is the element inside an iframe?
- Did the iframe finish loading?
- Am I using the correct frame selector?
- Has the iframe been recreated dynamically?
- Is the element inside a nested frame?
These simple questions solve many real-world automation problems before you spend time debugging the locator itself.
Interview Questions
1. What is an iframe?
An iframe is an HTML element that embeds another webpage within the current webpage. It creates a separate browsing context with its own DOM and JavaScript execution environment.
2. Why can't Playwright locate elements inside an iframe using page.locator()?
Because elements inside an iframe belong to a different document. You must first enter the frame using frameLocator() before locating elements inside it.
3. What is frameLocator()?
frameLocator() is Playwright's API for locating and interacting with elements inside iframes. It automatically scopes all subsequent locators to the selected frame.
4. How do you automate nested frames?
await page
.frameLocator('#outer-frame')
.frameLocator('#inner-frame')
.getByRole(
'button',
{
name:'Submit'
}
)
.click();
5. Give examples where iframes are commonly used.
- Stripe Payment Gateway
- PayPal Checkout
- Google Maps
- YouTube Videos
- Customer Support Widgets
- Power BI Reports
- Embedded Dashboards
- Document Viewers
6. Does Playwright automatically wait for frames?
Yes. Playwright automatically waits for frames and elements to become available before performing actions, reducing the need for manual waits.
7. What is the difference between locator() and frameLocator()?
| locator() | frameLocator() |
|---|---|
| Main Page | Inside iFrame |
| Regular DOM | Frame DOM |
| Normal Elements | Embedded Documents |
Playwright Certification Notes
If you're preparing for Playwright interviews or certifications, make sure you're comfortable with these concepts:
- frameLocator()
- Nested Frames
- Dynamic Frames
- Stripe Payment Automation
- PayPal Automation
- Chat Widget Automation
- Embedded Reports
- Auto Waiting with Frames
- Locator Strategies Inside Frames
These topics frequently appear in technical interviews because they reflect real enterprise automation challenges.
Quick Revision
Main Page
│
├── locator()
│
└── frameLocator()
│
├── Card Number
├── Expiry Date
├── CVV
└── Submit
Remember this simple rule:
- Regular page → locator()
- Inside iframe → frameLocator()
Frequently Asked Questions (FAQs)
Can one page contain multiple iframes?
Yes. Enterprise applications often contain several iframes for payments, advertisements, analytics, chat widgets, and embedded reports.
Can an iframe contain another iframe?
Yes. This is known as a nested frame. Playwright supports nested frames by chaining multiple frameLocator() calls.
Should I use XPath inside iframes?
It's usually better to use Playwright's accessibility locators such as getByRole(), getByLabel(), or getByPlaceholder(). They are more stable and easier to maintain.
Do I need waitForTimeout() before using frameLocator()?
No. Playwright automatically waits for frames and elements to become ready. Manual delays should be avoided unless absolutely necessary.
Conclusion
Frames are everywhere in modern web applications, from secure payment gateways to embedded dashboards and customer support widgets. Understanding how browsers isolate iframe content is the first step toward writing reliable automation.
With frameLocator(), Playwright provides a clean, readable, and powerful way to interact with elements inside frames without the manual context switching required by older automation frameworks.
As you continue building automation frameworks, mastering frame handling will save hours of debugging and make your tests more reliable across enterprise applications.
About Bugged But Happy
Bugged But Happy is a learning platform dedicated to helping QA Engineers, SDETs, and Software Testers master modern testing tools through practical, real-world tutorials.
We publish in-depth content on:
- Playwright Automation
- API Testing
- Manual Testing
- Performance Testing
- Automation Framework Design
- Career Guidance
- Interview Preparation
- Certification Notes
Learning, Testing, and Growing One Bug at a Time.
🌐 https://thebuggedbuthappy.blogspot.com/
Continue Your Playwright Journey
- What is Playwright?
- Installing Playwright
- Your First Playwright Test
- Playwright Architecture
- Playwright Test Runner
- Playwright Locators
- Playwright Assertions
- Playwright Auto-Waiting
- Playwright Actions
Next Blog in This Series
Playwright Browser Contexts Explained: Isolation, Sessions & Multi-User Testing (2026)
In the next article, we'll explore one of Playwright's most powerful features—Browser Contexts. You'll learn how to isolate sessions, simulate multiple users, manage cookies, test different roles simultaneously, and build scalable enterprise automation frameworks.

Comments
Post a Comment