Work with iframes
Some pages embed content in iframes — login forms, embedded widgets, third-party content. This guide shows how to access iframe content with Ferret.
Iframe access requires the cdp driver. See Browser-driven pages for setup.
Cross-origin iframes restrict access to their content. The iframe must be on the same domain as the parent page, or the browser will block property and content access.
List frames on a page
A browser-backed page exposes its frames through the frames property:
example.fql
LET page = WEB::HTML::OPEN("https://mockery.ferretlang.org", { driver: "cdp" })
FOR frame IN page.frames
RETURN {
url: frame.URL,
title: frame.title
}
Find a frame by URL
Use FILTER to locate a specific frame:
example.fql
LET page = WEB::HTML::OPEN("https://mockery.ferretlang.org", { driver: "cdp" })
LET target = (
FOR frame IN page.frames
FILTER CONTAINS(frame.URL, "embedded-form")
LIMIT 1
RETURN frame
)
LET frame = FIRST(target)
RETURN frame?.title
Extract content from a frame
Once you have a frame reference, query it the same way you query a page:
example.fql
LET page = WEB::HTML::OPEN("https://mockery.ferretlang.org", { driver: "cdp" })
LET target = FIRST((
FOR frame IN page.frames
FILTER CONTAINS(frame.URL, "embedded")
LIMIT 1
RETURN frame
))
LET items = target != NONE
? target[~ css`.content-item`]
: []
RETURN items[*].textContent
Interact with elements inside a frame
Dispatch events to elements within the frame just as you would on the main page:
example.fql
LET page = WEB::HTML::OPEN("https://mockery.ferretlang.org", { driver: "cdp" })
LET frame = FIRST((
FOR f IN page.frames
FILTER CONTAINS(f.URL, "login")
LIMIT 1
RETURN f
))
LET input = QUERY ONE "input[name='email']" IN frame USING css
DISPATCH "input" IN input WITH "user@example.com"
LET submit = QUERY ONE "button[type='submit']" IN frame USING css
submit <- "click"
RETURN "submitted"
Handle missing frames
A frame might not be present on every page. Use error recovery or conditional checks:
example.fql
LET page = WEB::HTML::OPEN("https://mockery.ferretlang.org", { driver: "cdp" })
LET frames = (
FOR f IN page.frames
FILTER CONTAINS(f.URL, "target-frame")
LIMIT 1
RETURN f
)
RETURN LENGTH(frames) > 0
? FIRST(frames)[~ css`.data`][*].textContent
: []
Next steps
Guide
Browser-driven pages
Use a browser for JavaScript-rendered pages and dynamic content.
Guide
Interact with pages
Click elements, fill forms, and trigger browser events.
Guide
Error handling
Handle missing elements, network failures, and timeouts.
Learn
For Loops
Iterate over collections and ranges, and shape results with FILTER, SORT, LIMIT, and COLLECT.