pub struct Page {
pub contexts: Arc<Mutex<HashMap<String, u32>>>,
pub domain_manager: Arc<DomainManager>,
pub network_monitor: Arc<NetworkMonitor>,
pub response_monitor_manager: Arc<ResponseMonitorManager>,
/* private fields */
}Fields§
§contexts: Arc<Mutex<HashMap<String, u32>>>Frame ID -> Execution Context ID mapping
domain_manager: Arc<DomainManager>Domain manager (unified management of CDP Domain enabling/disabling)
network_monitor: Arc<NetworkMonitor>Network monitor
response_monitor_manager: Arc<ResponseMonitorManager>Response monitor manager
Implementations§
Source§impl Page
Response monitoring convenience methods
impl Page
Response monitoring convenience methods
Sourcepub async fn monitor_responses<F, H>(
self: &Arc<Self>,
filter: F,
handler: H,
) -> Result<()>
pub async fn monitor_responses<F, H>( self: &Arc<Self>, filter: F, handler: H, ) -> Result<()>
Registers a non-blocking handler for all responses that pass the filter.
§Parameters
filter- Returnstruewhen a response should be forwarded to the handler.handler- Receives the captured response metadata.
§Examples
page.monitor_responses(
|url| url.contains("/api/"),
|response| {
println!("API Response: {} - {}", response.status_code, response.status_text);
if let Some(body) = &response.body {
println!("Body: {}", body);
}
},
).await?;Sourcepub async fn monitor_responses_matching<H>(
self: &Arc<Self>,
url_pattern: &str,
handler: H,
) -> Result<()>
pub async fn monitor_responses_matching<H>( self: &Arc<Self>, url_pattern: &str, handler: H, ) -> Result<()>
Registers a handler for responses whose URLs contain the given pattern.
§Parameters
url_pattern- Substring that must be present in the URL.handler- Invoked with the captured response metadata.
§Examples
page.monitor_responses_matching(
"data.json",
|response| {
println!("Data Response: {}", response.status_code);
},
).await?;Source§impl Page
impl Page
Sourcepub async fn connect_to_active_page(
port: Option<u16>,
pattern: Option<&str>,
) -> Result<Arc<Self>>
pub async fn connect_to_active_page( port: Option<u16>, pattern: Option<&str>, ) -> Result<Arc<Self>>
Mode 2 entry: Connect directly
Sourcepub async fn connect_to_active_page_with_browser(
port: Option<u16>,
pattern: Option<&str>,
browser_process: Option<&str>,
) -> Result<Arc<Self>>
pub async fn connect_to_active_page_with_browser( port: Option<u16>, pattern: Option<&str>, browser_process: Option<&str>, ) -> Result<Arc<Self>>
Mode 2 entry: Connect directly (supports custom browser process)
pub fn accessibility(self: &Arc<Self>) -> AccessibilityController
pub fn emulation(self: &Arc<Self>) -> EmulationController
pub fn tracing(self: &Arc<Self>) -> TracingController
pub fn on<E>(&self) -> Pin<Box<dyn Stream<Item = E> + Send + 'static>>
pub async fn wait_for_loaded(&self) -> Result<LoadEventFiredEvent>
pub async fn get_title(&self) -> Result<String>
Sourcepub async fn main_frame(self: &Arc<Self>) -> Result<Frame>
pub async fn main_frame(self: &Arc<Self>) -> Result<Frame>
Get main Frame (cached)
Sourcepub async fn query_selector(
self: &Arc<Self>,
selector: &str,
) -> Result<Option<ElementHandle>>
pub async fn query_selector( self: &Arc<Self>, selector: &str, ) -> Result<Option<ElementHandle>>
Queries the first element matching the CSS selector.
This method automatically searches across all frames (including iframes):
- First searches in the main frame
- If not found, searches in all child frames
§Parameters
selector- CSS selector string
§Returns
First matching element handle, or None if no match
§Examples
// Automatically search for first matching button in all frames
if let Some(button) = page.query_selector(".submit-btn").await? {
button.click().await?;
}Sourcepub async fn query_selector_all(
self: &Arc<Self>,
selector: &str,
) -> Result<Vec<ElementHandle>>
pub async fn query_selector_all( self: &Arc<Self>, selector: &str, ) -> Result<Vec<ElementHandle>>
Queries all elements matching the CSS selector.
This method automatically searches across all frames (including iframes):
- First searches in the main frame
- Then searches in all child frames and collects all matches
§Parameters
selector- CSS selector string
§Returns
List of all matching element handles, or empty list if no match
§Examples
// Automatically search for all matching links in all frames
let links = page.query_selector_all("a").await?;
println!("Found {} links across all frames", links.len());
for (i, link) in links.iter().enumerate() {
let href = link.get_attribute("href").await?;
println!("Link {}: {:?}", i + 1, href);
}Sourcepub async fn all_frames(self: &Arc<Self>) -> Result<Vec<Frame>>
pub async fn all_frames(self: &Arc<Self>) -> Result<Vec<Frame>>
Returns a flat list of all frames attached to this page.
Sourcepub async fn clear_frame_cache(&self)
pub async fn clear_frame_cache(&self)
Clear Frame cache (called after navigation)
Sourcepub async fn register_execution_context(
&self,
frame_id: String,
context_id: u32,
)
pub async fn register_execution_context( &self, frame_id: String, context_id: u32, )
Register Execution Context (called by event handler)
Sourcepub async fn remove_execution_context(&self, context_id: u32)
pub async fn remove_execution_context(&self, context_id: u32)
Remove specified Execution Context (called by event handler)
Sourcepub async fn clear_execution_contexts(&self)
pub async fn clear_execution_contexts(&self)
Clear all Execution Contexts (called by event handler)
Sourcepub async fn get_parent_frame(&self, frame_id: &str) -> Option<Frame>
pub async fn get_parent_frame(&self, frame_id: &str) -> Option<Frame>
Get parent Frame of specified Frame
Sourcepub async fn get_child_frames(&self, frame_id: &str) -> Vec<Frame>
pub async fn get_child_frames(&self, frame_id: &str) -> Vec<Frame>
Get all child Frames of specified Frame
Sourcepub async fn get_ancestor_frames(&self, frame_id: &str) -> Vec<Frame>
pub async fn get_ancestor_frames(&self, frame_id: &str) -> Vec<Frame>
Get all ancestor Frames of specified Frame (from near to far)
Sourcepub async fn get_descendant_frames(&self, frame_id: &str) -> Vec<Frame>
pub async fn get_descendant_frames(&self, frame_id: &str) -> Vec<Frame>
Get all descendant Frames of specified Frame (DFS)
Sourcepub async fn query_frame(
self: &Arc<Self>,
selector: &str,
) -> Result<Option<Frame>>
pub async fn query_frame( self: &Arc<Self>, selector: &str, ) -> Result<Option<Frame>>
Find Frame by selector
§Selector Syntax
name:iframe-name- Match by nameurl:https://example.com- Match by URL prefixurl~pattern- Match by URL regexdepth:2- Match by depth (0 = Main Frame, 1 = Direct Child Frame)
§Examples
// Find Frame named "login-iframe"
if let Some(frame) = page.query_frame("name:login-iframe").await? {
println!("Found iframe: {}", frame.id());
}
// Find Frame with URL containing "checkout"
if let Some(frame) = page.query_frame("url~checkout").await? {
println!("Found checkout frame: {}", frame.id());
}Sourcepub async fn query_frames(
self: &Arc<Self>,
selector: &str,
) -> Result<Vec<Frame>>
pub async fn query_frames( self: &Arc<Self>, selector: &str, ) -> Result<Vec<Frame>>
Find all Frames matching selector
Sourcepub async fn on_frame_lifecycle(&self, callback: FrameLifecycleCallback)
pub async fn on_frame_lifecycle(&self, callback: FrameLifecycleCallback)
Register Frame lifecycle callback
§Examples
use cdp_core::{Page, FrameLifecycleEvent};
use std::sync::Arc;
page.on_frame_lifecycle(Arc::new(|event| {
match event {
FrameLifecycleEvent::Attached { frame_id, parent_frame_id } => {
println!("Frame attached: {}", frame_id);
}
FrameLifecycleEvent::Detached { frame_id } => {
println!("Frame detached: {}", frame_id);
}
FrameLifecycleEvent::Navigated { frame_id, url } => {
println!("Frame navigated: {} to {}", frame_id, url);
}
}
})).await;Sourcepub async fn on_dom_mutation(&self, callback: DomMutationCallback)
pub async fn on_dom_mutation(&self, callback: DomMutationCallback)
Register DOM mutation callback
§Examples
use cdp_core::{Page, DomMutationEvent};
use std::sync::Arc;
// Enable DOM monitoring
page.enable_dom_mutations().await?;
// Register callback
page.on_dom_mutation(Arc::new(|event| {
match event {
DomMutationEvent::ChildNodeInserted { parent_node_id, .. } => {
println!("Child node inserted into {}", parent_node_id);
}
DomMutationEvent::AttributeModified { node_id, name, value } => {
println!("Attribute {} = {} on node {}", name, value, node_id);
}
_ => {}
}
})).await;Sourcepub async fn enable_dom_mutations(&self) -> Result<()>
pub async fn enable_dom_mutations(&self) -> Result<()>
Enable DOM mutation monitoring
Source§impl Page
impl Page
Sourcepub async fn create_frame_snapshot(
&self,
frame_id: &str,
include_html: bool,
) -> Result<FrameSnapshot>
pub async fn create_frame_snapshot( &self, frame_id: &str, include_html: bool, ) -> Result<FrameSnapshot>
Create Frame snapshot
§Arguments
frame_id- Frame IDinclude_html- Whether to include HTML content
§Examples
let main_frame = page.main_frame().await?;
// Create snapshot (without HTML)
let snapshot = page.create_frame_snapshot(&main_frame.id, false).await?;
println!("Snapshot: {:?}", snapshot);
// Create snapshot (with HTML)
let snapshot_with_html = page.create_frame_snapshot(&main_frame.id, true).await?;
println!("HTML length: {}", snapshot_with_html.html_content.as_ref().map(|s| s.len()).unwrap_or(0));Sourcepub async fn create_all_frames_snapshot(
self: &Arc<Self>,
include_html: bool,
) -> Result<Vec<FrameSnapshot>>
pub async fn create_all_frames_snapshot( self: &Arc<Self>, include_html: bool, ) -> Result<Vec<FrameSnapshot>>
Create snapshots for all Frames
§Examples
let snapshots = page.create_all_frames_snapshot(false).await?;
println!("Created {} snapshots", snapshots.len());
// Save as JSON
let json = serde_json::to_string_pretty(&snapshots)?;
std::fs::write("frame_snapshots.json", json)?;Sourcepub fn compare_snapshots(
snapshot1: &FrameSnapshot,
snapshot2: &FrameSnapshot,
) -> Vec<String>
pub fn compare_snapshots( snapshot1: &FrameSnapshot, snapshot2: &FrameSnapshot, ) -> Vec<String>
Compare differences between two snapshots
§Examples
let snapshot1 = page.create_all_frames_snapshot(false).await?;
// Wait for some changes...
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
let snapshot2 = page.create_all_frames_snapshot(false).await?;
for (snap1, snap2) in snapshot1.iter().zip(snapshot2.iter()) {
let diff = Page::compare_snapshots(snap1, snap2);
println!("Frame {}: {} changes", snap1.frame_id, diff.len());
}Sourcepub async fn type_text(&self, text: &str) -> Result<()>
pub async fn type_text(&self, text: &str) -> Result<()>
Type text into current focused element (insert all text at once)
This method uses CDP’s Input.insertText command to insert all text at once.
Suitable for fast input, but does not simulate real user character-by-character input.
§Parameters
text- Text to type
§Examples
// Focus on input box first
if let Some(input) = page.query_selector("input[type='text']").await? {
input.click().await?;
}
// Fast type text
page.type_text("Hello, World!").await?;Sourcepub async fn type_text_with_delay(
&self,
text: &str,
min_delay_ms: u64,
max_delay_ms: u64,
) -> Result<()>
pub async fn type_text_with_delay( &self, text: &str, min_delay_ms: u64, max_delay_ms: u64, ) -> Result<()>
Type text into current focused element character by character, with random delay between each character
This method simulates real user input behavior, each character triggers keyDown, keyUp events.
Delay time is randomly generated within [min_delay_ms, max_delay_ms].
§Parameters
text- Text to typemin_delay_ms- Minimum delay (ms)max_delay_ms- Maximum delay (ms)
§Examples
// Focus on input box first
if let Some(input) = page.query_selector("input[type='text']").await? {
input.click().await?;
}
// Type with random delay
page.type_text_with_delay("Hello, World!", 50, 150).await?;Sourcepub async fn screenshot(
&self,
full_page: bool,
save_path: Option<PathBuf>,
) -> Result<String>
pub async fn screenshot( &self, full_page: bool, save_path: Option<PathBuf>, ) -> Result<String>
Takes a screenshot of the page.
Takes a screenshot of the page.
§Parameters
full_page- Whether to capture full page (including scroll area). If false, only capture current viewportsave_path- Optional save path (including filename). If None, save to current directory with namescreenshot_timestamp.png
§Returns
Saved file path
§Examples
// Capture current viewport and save automatically
let path = page.screenshot(false, None).await?;
println!("Screenshot saved to: {}", path);
// Capture full page and save to specified path
let path = page.screenshot(true, Some("screenshots/fullpage.png".into())).await?;
println!("Full page screenshot saved to: {}", path);Sourcepub async fn screenshot_with_options(
&self,
full_page: bool,
save_path: Option<PathBuf>,
auto_resolve_dpr: bool,
) -> Result<String>
pub async fn screenshot_with_options( &self, full_page: bool, save_path: Option<PathBuf>, auto_resolve_dpr: bool, ) -> Result<String>
Takes a screenshot of the page with custom options.
Takes a screenshot of the page with custom options.
§Parameters
full_page- Whether to capture full page (including scroll area). If false, only capture current viewportsave_path- Optional save path (including filename). If None, save to current directory with namescreenshot_timestamp.pngauto_resolve_dpr- Whether to automatically adapt to device pixel ratio. If true, automatically detect and use actual DPR to avoid screenshot being too large or distorted
§Returns
Saved file path
§Examples
// Capture full page, do not adapt DPR (use fixed 1.0, compatible with old behavior)
let path = page.screenshot_with_options(true, None, false).await?;
// Capture full page, adapt DPR (recommended, avoid screenshot being too large)
let path = page.screenshot_with_options(true, None, true).await?;Sourcepub async fn wait_for_selector(
self: &Arc<Self>,
selector: &str,
options: Option<WaitForSelectorOptions>,
) -> Result<ElementHandle>
pub async fn wait_for_selector( self: &Arc<Self>, selector: &str, options: Option<WaitForSelectorOptions>, ) -> Result<ElementHandle>
Wait for element matching selector to appear
§Parameters
selector- CSS selector or XPath expressionoptions- Wait options (timeout, visibility, etc.)
§Returns
Matching element handle
§Examples
// Wait for element to appear (default 30s timeout)
let button = page.wait_for_selector("#submit-btn", None).await?;
// Custom timeout and visibility requirements
let element = page.wait_for_selector(
".dynamic-content",
Some(WaitForSelectorOptions {
timeout_ms: Some(5000),
visible: Some(true),
hidden: Some(false),
})
).await?;Sourcepub async fn wait_for_function(
self: &Arc<Self>,
function: &str,
timeout_ms: Option<u64>,
poll_interval_ms: Option<u64>,
) -> Result<()>
pub async fn wait_for_function( self: &Arc<Self>, function: &str, timeout_ms: Option<u64>, poll_interval_ms: Option<u64>, ) -> Result<()>
Wait for custom function to return true
§Parameters
function- JavaScript function string, should return booleantimeout_ms- Timeout in milliseconds, default 30000poll_interval_ms- Polling interval (ms), default 100
§Examples
// Wait for page title to change
page.wait_for_function(
"() => document.title === 'Loaded'",
Some(5000),
None
).await?;
// Wait for global variable
page.wait_for_function(
"() => window.myApp && window.myApp.ready",
None,
None
).await?;Wait for page navigation to complete
Supports multiple wait conditions:
- Load: Wait for
loadevent (all resources loaded) - DOMContentLoaded: Wait for DOM tree construction to complete
- NetworkIdle0: Wait for network to be fully idle (no requests for 500ms)
- NetworkIdle2: Wait for network to be almost idle (<= 2 requests for 500ms)
§Parameters
options- Navigation wait options (timeout, wait condition, etc.)
§Examples
// Wait for load event (default)
page.wait_for_navigation(None).await?;
// Wait for DOMContentLoaded (faster)
page.wait_for_navigation(Some(WaitForNavigationOptions {
timeout_ms: Some(5000),
wait_until: Some(WaitUntil::DOMContentLoaded),
})).await?;
// Wait for network idle (suitable for SPA)
page.wait_for_navigation(Some(WaitForNavigationOptions {
timeout_ms: Some(10000),
wait_until: Some(WaitUntil::NetworkIdle2),
})).await?;Sourcepub async fn on_network(&self, callback: NetworkEventCallback)
pub async fn on_network(&self, callback: NetworkEventCallback)
Register network event callback
§Examples
page.enable_network_monitoring().await?;
page.on_network(Arc::new(|event| {
match event {
NetworkEvent::RequestWillBeSent { url, method, .. } => {
println!("[{}] {}", method, url);
}
NetworkEvent::ResponseReceived { request_id, status, .. } => {
println!("[{}] Status: {}", request_id, status);
}
NetworkEvent::LoadingFailed { request_id, error_text } => {
eprintln!("[{}] Failed: {}", request_id, error_text);
}
_ => {}
}
})).await;Sourcepub fn get_inflight_requests_count(&self) -> usize
pub fn get_inflight_requests_count(&self) -> usize
Sourcepub async fn wait_for_timeout(&self, ms: u64)
pub async fn wait_for_timeout(&self, ms: u64)
Sourcepub async fn cleanup(&self) -> Result<()>
pub async fn cleanup(&self) -> Result<()>
Clean up Page resources (explicit async cleanup)
This method will:
- Clear all network monitors and interceptors
- Disable all enabled CDP Domains
- Clear Frame cache and callbacks
§Best Practices
Although Page automatically cleans up on Drop, it is recommended to call this method explicitly when Page is no longer used:
let browser = Browser::launcher().launch().await?;
let page = browser.new_page().await?;
// Use page...
// Explicitly cleanup when no longer used
page.cleanup().await?;§Note
- After calling this method, Page will be in an unusable state
- If Page is shared via
Arc, ensure no other places are still using it - Cleanup is also performed automatically on Drop, but explicit call gives better control over timing and error handling
Trait Implementations§
Source§impl CookieManager for Page
impl CookieManager for Page
Source§impl Drop for Page
RAII automatic cleanup implementation
impl Drop for Page
RAII automatic cleanup implementation
Automatically cleans up all resources when Page is dropped