Open a BiDi connection: async with driver.bidi_connection() as conn: browsing_context = BrowsingContext(conn.session, driver.current_window_handle)
Subscribe to the domContentLoaded event: await browsing_context.on_dom_content_loaded(lambda event: print(event.url))
Subscribe to fragment navigation events to capture SPA route changes: await browsing_context.on_fragment_navigated(lambda e: log(e))
Trigger navigation with driver.get(url) or by interacting with links on the page
Collect the streamed events and assert expected URLs appear in the correct order
Unsubscribe when done to prevent memory leaks in long-running sessions
Known gotchas
BiDi event subscriptions are asynchronous; if you navigate before the subscription is confirmed, you may miss the first event — await the subscription call before triggering navigation
The browsingContext module uses the internal context ID, not the window handle string; obtain the correct ID from the BiDi session rather than driver.current_window_handle directly in all binding versions
High-frequency SPAs emit many fragment_navigated events; set up filtering or debouncing in the callback to avoid flooding logs
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp