From 421517d7ecbc233f33ba05e807422d60eef7abcd Mon Sep 17 00:00:00 2001 From: Battleplus <3559424769@qq.com> Date: Mon, 24 Aug 2026 13:06:49 +0800 Subject: [PATCH] fix(crawler): skip body visibility check when ignore_body_visibility=True (#2129) When ignore_body_visibility=True (the default), the crawler still waited for body to become attached (30s timeout) and ran a visibility check, only to discard the result. This added a hardcoded 30s penalty on every page where body is never visible (e.g., AngularJS ng-cloak, Vue v-cloak). Wrap the entire body visibility block in `if not config.ignore_body_visibility` so the default path skips it entirely. Remove redundant inner guards. Closes #2129 --- crawl4ai/async_crawler_strategy.py | 60 ++++++++++++++++-------------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/crawl4ai/async_crawler_strategy.py b/crawl4ai/async_crawler_strategy.py index 265c376e9..620b1440a 100644 --- a/crawl4ai/async_crawler_strategy.py +++ b/crawl4ai/async_crawler_strategy.py @@ -808,41 +808,45 @@ async def handle_request_failed_capture(request): response_headers = {} # Wait for body element and visibility - try: - await page.wait_for_selector("body", state="attached", timeout=30000) + # Skip entirely when ignore_body_visibility=True (the default) + # to avoid a hardcoded 30s penalty on pages where body is never visible + # (e.g., AngularJS ng-cloak, Vue v-cloak). See #2129. + if not config.ignore_body_visibility: + try: + await page.wait_for_selector("body", state="attached", timeout=30000) + + # Use the new check_visibility function with csp_compliant_wait + is_visible = await self.csp_compliant_wait( + page, + """() => { + const element = document.body; + if (!element) return false; + const style = window.getComputedStyle(element); + const isVisible = style.display !== 'none' && + style.visibility !== 'hidden' && + style.opacity !== '0'; + return isVisible; + }"", + timeout=30000, + ) - # Use the new check_visibility function with csp_compliant_wait - is_visible = await self.csp_compliant_wait( - page, - """() => { - const element = document.body; - if (!element) return false; - const style = window.getComputedStyle(element); - const isVisible = style.display !== 'none' && - style.visibility !== 'hidden' && - style.opacity !== '0'; - return isVisible; - }""", - timeout=30000, - ) + if not is_visible: + visibility_info = await self.check_visibility(page) + raise Error(f"Body element is hidden: {visibility_info}") - if not is_visible and not config.ignore_body_visibility: + except Error: visibility_info = await self.check_visibility(page) - raise Error(f"Body element is hidden: {visibility_info}") - - except Error: - visibility_info = await self.check_visibility(page) - if self.browser_config.verbose: - self.logger.debug( - message="Body visibility info: {info}", - tag="DEBUG", - params={"info": visibility_info}, - ) + if self.browser_config.verbose: + self.logger.debug( + message="Body visibility info: {info}", + tag="DEBUG", + params={"info": visibility_info}, + ) - if not config.ignore_body_visibility: raise Error(f"Body element is hidden: {visibility_info}") + # try: # await page.wait_for_selector("body", state="attached", timeout=30000)