Skip to main content

Playwright frameLocator() Guide (2026): Automate Frames & iFrames Like a Pro

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 iframe selectors 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

Popular posts from this blog

Selenium 5: What’s New and Why It Still Matters in 2025

Selenium 5: What’s New and Why It Still Matters in 2025 data-full-width-responsive="true"> Selenium has been the backbone of web automation testing for over a decade. From the early days of Selenium RC to WebDriver and the release of Selenium 4, it has enabled QA engineers worldwide to automate browsers reliably. But as modern frameworks like Playwright and Cypress gained attention, critics started asking: “Is Selenium dead?” In 2025, the answer is clear: Selenium is not dead — it has evolved. With the release of Selenium 5 , the project has modernized to support new browser technologies, improve stability, and remain a cornerstone of test automation strategies. 1. Introduction — Selenium’s Legacy Selenium started in 2004 as a tool to automate browsers for functional testing. Over the years: Selenium RC gave way to Selenium WebDriver. Selenium Grid enabled parallel execution at scale. Selenium 4 introduced W3C WebDriver com...

Chaos Testing for Automation Engineers

Chaos Testing for Automation Engineers Why automation passes in CI but fails in production ⏱ Reading time: 10–12 minutes Most automation engineers have experienced this moment: All test cases are green. Pipelines are passing. Confidence is high. And then production fails. This blog explains why that happens — and how Chaos Testing , inspired by Anti-Gravity thinking, helps automation engineers test reality instead of assumptions. Why Automation Testing Often Gives False Confidence Automation scripts usually validate: Stable environments Correct inputs Predictable flows Fast responses But real systems don’t behave this way. Production systems face: Network delays Service timeouts Partial failures Unexpected user behavior Chaos Testing exists to simulate these conditions intentionally — before users experience them. What Is Chaos Testing (In Simple Terms) Chaos Testing is n...

Google Anti-Gravity Thinking in Software Testing (With Real-World Examples & Tools)

Google Anti-Gravity Thinking in Software Testing A practical mindset that prepares testers to break systems the right way Software testing is often taught as a structured activity. Write test cases. Follow steps. Verify expected results. Mark Pass or Fail. This works well in training environments — but real users don’t behave this way. They don’t read requirements. They don’t follow flows. They don’t wait patiently. They click early. They click repeatedly. They lose network. They rotate screens. They refresh pages. And when this happens, many applications fail silently. That is why production bugs exist. To catch these bugs early, testers must think differently. They must think beyond rules. They must think beyond assumptions. This is where Anti-Gravity Thinking becomes powerful. What Is Anti-Gravity Thinking in Testing? Google Anti-Gravity is a visual experiment where UI elements do not stay fixed. They float. They move. They fall out of place. In...