@@ -661,6 +661,11 @@ async def start(self):
661661 if self .config .cdp_url or self .config .use_managed_browser :
662662 self .config .use_managed_browser = True
663663 cdp_url = await self .managed_browser .start () if not self .config .cdp_url else self .config .cdp_url
664+
665+ # Add CDP endpoint verification before connecting
666+ if not await self ._verify_cdp_ready (cdp_url ):
667+ raise Exception (f"CDP endpoint at { cdp_url } is not ready after startup" )
668+
664669 self .browser = await self .playwright .chromium .connect_over_cdp (cdp_url )
665670 contexts = self .browser .contexts
666671 if contexts :
@@ -681,6 +686,24 @@ async def start(self):
681686
682687 self .default_context = self .browser
683688
689+ async def _verify_cdp_ready (self , cdp_url : str ) -> bool :
690+ """Verify CDP endpoint is ready with exponential backoff"""
691+ import aiohttp
692+ self .logger .debug (f"Starting CDP verification for { cdp_url } " , tag = "BROWSER" )
693+ for attempt in range (5 ):
694+ try :
695+ async with aiohttp .ClientSession () as session :
696+ async with session .get (f"{ cdp_url } /json/version" , timeout = aiohttp .ClientTimeout (total = 2 )) as response :
697+ if response .status == 200 :
698+ self .logger .debug (f"CDP endpoint ready after { attempt + 1 } attempts" , tag = "BROWSER" )
699+ return True
700+ except Exception as e :
701+ self .logger .debug (f"CDP check attempt { attempt + 1 } failed: { e } " , tag = "BROWSER" )
702+ delay = 0.5 * (1.4 ** attempt )
703+ self .logger .debug (f"Waiting { delay :.2f} s before next CDP check..." , tag = "BROWSER" )
704+ await asyncio .sleep (delay )
705+ self .logger .debug (f"CDP verification failed after 5 attempts" , tag = "BROWSER" )
706+ return False
684707
685708 def _build_browser_args (self ) -> dict :
686709 """Build browser launch arguments from config."""
0 commit comments