Handling Iframes using Python and Playwright

Learn how to work with iframes and nested iframes using Microsoft’s automation library.

Photo by pine watt on Unsplash

Inline frames (more commonly known as an iframe) are used for displaying 3rd party content or embedding new pages within the content of a web page. In the world of test automation, iframes can be difficult to work with.

Selenium requires an engineer to use the switch_to method to change the driver’s focus to the frame itself. Once done performing actions, the driver needs to be re-focused to the main page using switch_to.default_content(). While this is not a difficult workflow, it certainly can be a hassle to continue switching between frames whenever an action needs to be taken.

Cypress does not natively handle iframes. This is due to the fact that the cy prefix used in all Cypress commands will traverse the DOM until a #document has been located. Once located, traversal will end. Custom code (or the cypress-iframe plugin) is required in order to use Cypress with iframes.

Playwright on the other hand, makes working with iframes simple and intuitive. In this tutorial, we will learn how to use Playwright with both conventional iframes and nested iframes. We will use the DemoQA Frames and Nested Frames pages as the focus for our tests.

Getting Started

You will need to install the following packages for this tutorial:

  • Pytest
  • Playwright

I personally recommend using the pytest-playwright library as it comes with a bunch of useful fixtures and methods for automated testing, such as screenshot on failure and simplified page creation.

Selector Methods

Playwright provides engineers with three options for selecting iframes:

  • element_handle.content_frame()
  • page.frame()
  • page.frames[i]

Engineers should use page.frame() when an iframe has a uniquename or url attribute. Should an iframe have neither, then the element_handle.content_frame() method should be used along with a selector for the frame’s parent element.

The page.frames[i] property should be used in instances where an iframe has no unique attributes or parent element. The property will list all active frames on the page which can be indexed for a specific frame. I would not recommend using this method unless you do not have access to application source code and cannot use the previous two methods.

Focusing on an Iframe

The DemoQA Frames page contains two iframes, one in the center-left of the page and one in the bottom left.

The DemopQA Frames page.

The iframes on the DemoQA Frames page do not have unique url attributes, nor do they feature name attributes. We will use the element_handle.content_frame() method for locating them as they do have unique selectors for their parent elements.

The beginning of our iframe test.

We now have access to the first frame on the page. Playwright assertions can be used with the ElementHandles frame_one and heading in order to write Pytest assertions.

Our finished iframe test.

Nested Frames

Playwright provides an additional method for selecting frames within existing iframes using the frame.child_frame[i] property. The property returns a list of all child frames within an iframe on the page. Similar to the page.frames[i] property, this is useful for when a child iframe does not have a unique name or urlattribute, or a parent element with a unique locator strategy.

The Demo QA Nested Frames page.

The child iframe on the DemoQA Nested Frames page does not have any unique locator strategies so we must use the frame.child_frame[i] property in order to select it.

The start of a test for a child-frame.

The child iframe contains a body element and a single p element with the text “Child Iframe”. We can use this for crafting Playwright assertions in order to build Pytest assertion statements.

Our finished child-frame test.


The above tests may be run in your terminal using the following commands (if using pytest-playwright):

  • pytest for a headless run
  • pytest --headful for headful

If you have chosen not to use the pytest-playwright library, you can run the tests in a headful state by adding headless=False when initializing the browser:

browser = {browser_type}.launch(headless=False)

Project Directory

Your directory should resemble the following upon completion of this tutorial:

|__ test_frames.py


Playwright allows engineers to write neat and readable test code for finding and taking action against iframes. Unlike Playwright’s competitors within the automation space, engineers do not need to write out custom code or keep track of driver focus when working with inline frame elements.

Jonathan Thompson is a Senior Quality Engineer specializing in test automation. He currently resides in Raleigh, NC with his wife and a Goldendoodle named Winston. You can connect with him on LinkedIn, or follow him on either Twitter (@jacks_elsewhere) or Github (ThompsonJonM).

Senior Quality Engineer at Pendo.io | Writing about JavaScript and Python test automation

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store