Work with browser-driven pages
Some pages load content through JavaScript — single-page applications, lazy-loaded lists, content behind client-side rendering. For these, Ferret can drive a real browser through the Chrome DevTools Protocol (CDP).
This guide covers when to use a browser, how to set one up, and how to wait for dynamic content.
When to use a browser
Use static extraction (WEB::HTML::OPEN without a driver) when the data is in the initial HTML response. Use the cdp driver when the page:
- renders content with JavaScript
- loads data asynchronously after the initial page load
- requires user interaction (clicking, scrolling, filling forms) before content appears
- depends on browser APIs (cookies, local storage, service workers)
If you are unsure, try static extraction first. It is faster and simpler. Switch to the browser driver only if the data is missing from the static HTML.
Set up a browser
Ferret connects to a Chrome or Chromium instance over CDP.
Option 1: Docker (recommended for reproducible environments)
docker run -d -p 9222:9222 montferret/chromium
Option 2: Managed browser (the CLI starts and stops a browser for you)
ferret browser start
Option 3: Connect to an existing browser launched with remote debugging enabled.
See CLI Browser for full details on browser management.
Open a page with a browser
Pass { driver: "cdp" } to WEB::HTML::OPEN:
Once opened, querying and element access work the same as with static pages. The difference is that the page value reflects the live browser DOM, including content added by JavaScript.
Wait for content
JavaScript-rendered pages may not have all content immediately after the page loads. Use WAITFOR to pause until the data appears.
Wait for an element
WAITFOR EXISTS re-checks the expression on a polling interval until it is non-empty according to EXISTS semantics or the timeout is reached.
Wait for a value
Use WAITFOR VALUE when you need the result of the check itself:
Wait for network idle
After a navigation or interaction, you may want to wait until the page finishes loading resources:
Tune the polling
WAITFOR supports several clauses to control timing:
EVERY— how often to re-check (with optional cap)BACKOFF— how the interval grows (LINEAR,EXPONENTIAL, orNONE)JITTER— randomize the interval to avoid synchronized retriesTIMEOUT— maximum wait time
Handle timeouts
When WAITFOR times out, it returns false (or NONE for WAITFOR VALUE). Add ON TIMEOUT RETURN for a custom fallback:
Extract from a browser-backed page
Once the content is loaded, extraction works the same as with static pages:
Navigate within a page
Use NAVIGATE to go to a different URL within the same browser session:
NAVIGATE_BACK(page) and NAVIGATE_FORWARD(page) move through the browser history.