The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Use Puppeteer’s Frame for the iframe, then click through a locator on that frame. A selector run on page searches the main document, not the iframe’s document.
Click an element inside an iframe
This runnable example finds an iframe by its title, gets its associated frame with contentFrame(), and clicks a button inside it. Replace the URL, iframe title, and button selector with values from your page.
As an Amazon Associate I earn from qualifying purchases.
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
const iframeHandle = await page.$('iframe[title="Embedded form"]');
if (!iframeHandle) throw new Error('Target iframe not found');
const frame = await iframeHandle.contentFrame();
if (!frame) throw new Error('Iframe content frame is not available');
await frame.locator('button.submit').click();
} finally {
await browser.close();
}
The example assumes puppeteer is already installed and imported in your project. Puppeteer’s Frame API describes a frame as the DOM frame associated with an iframe.
Recommended Free Tools
Choose the correct iframe
If the page has a single iframe, a selector such as iframe may suffice. With several, select by a stable attribute such as title or name, or inspect the frame URLs and match the one containing the target. URL matching is page-specific: redirects and navigation can change a frame’s URL.
#1 Best Overall
const frame = page.frames().find(frame => frame.url().includes('/embedded-form'));
if (!frame) throw new Error('Target frame not found');
await frame.locator('button.submit').click();
page.frames() returns the current frames. Puppeteer also exposes childFrames() and parentFrame(), which help when the target is nested inside another iframe.
Get the frame from an iframe element
When you have an iframe’s element handle, call contentFrame() to obtain its associated Frame. The method can return null, so check the result before using it.
const iframeHandle = await page.$('iframe[name="payment"]');
if (!iframeHandle) throw new Error('Iframe element not found');
const frame = await iframeHandle.contentFrame();
if (!frame) throw new Error('Iframe content frame is not available');
Use a locator or the lower-level click method
| Approach | Example | When to use it |
|---|---|---|
| Frame locator | frame.locator('button.submit').click() |
Recommended for ordinary interactions. Locators wait for the element and check common click preconditions, including visibility, enabled state, viewport position, and a stable bounding box. |
| Frame click | frame.click('button.submit') |
A direct, lower-level alternative when that API better fits your interaction. |
Both methods are frame-scoped: they search within that frame rather than the top-level page. Puppeteer recommends locators for selecting and interacting with elements. See the Page interactions guide and Frame API.
Wait for a click that navigates the frame
If clicking a link or button triggers navigation in that iframe, start waiting for navigation at the same time as the click. Waiting only after the click can miss a fast navigation.
Rank #3
const [response] = await Promise.all([
frame.waitForNavigation(),
frame.locator('a.continue').click(),
]);
Use the navigation wait only when the action is expected to navigate. For an in-place update, wait for the resulting element or state instead.
Troubleshoot iframe clicks
- The selector is not found: If you ran it on
page, it searched the main document. Get the rightFramefirst, then query throughframe.locator(). - No iframe element or frame is returned: The selector may not match, or the iframe may not yet be present. Check the selector and wait for the iframe element before calling
contentFrame(). - The frame exists but the target does not: The frame may still be loading, or the target may be in a nested child frame. Use a locator so Puppeteer can wait for the target, and inspect
childFrames()when needed. - The frame was replaced or detached: Page scripts can remove or replace an iframe during navigation. Reacquire the iframe element and its frame after that change rather than relying on a stale handle.
- The click triggers navigation but the script hangs or misses it: Pair
frame.waitForNavigation()and the click inPromise.allrather than starting the wait afterward.
Or skip the browser setup
ScreenshotNeo takes website screenshots; it does not click elements inside an iframe, so it is not a substitute for the Puppeteer interaction above. If you only need an image or PDF of a page, one GET request can capture it:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo API documentation. Before a capture, it accepts cookie or consent banners as a visitor and removes supported consent platforms, newsletter popups, and chat widgets. Bot checks, blank pages, timeouts, and failed loads are not billed; cache hits are not billed either, and responses include X-Page-Verdict and X-Billed headers. Its MCP server provides screenshot tools for AI agents. The free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Sign up for 1,000 free screenshots a month, with no card required.
Frequently Asked Questions
Can Puppeteer click an element inside a cross-origin iframe?
The frame-scoped interaction pattern is the same: obtain the iframe’s Puppeteer Frame and interact through it. The documented Frame API supports frame-scoped selection and interaction.
Can an iframe contain another iframe?
Yes. Locate the child frame that contains the target element; Puppeteer represents nested frames and exposes child-frame relationships.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




