diff --git a/Dockers/puppeteer-api/app/services/browser.py b/Dockers/puppeteer-api/app/services/browser.py index 3818e58..b40c696 100644 --- a/Dockers/puppeteer-api/app/services/browser.py +++ b/Dockers/puppeteer-api/app/services/browser.py @@ -188,6 +188,12 @@ async def interactions_service( async def interactions_operation(page): try: + # When the API caller sets viewport.height = -1, treat that as "capture full webpage". + # We implement this by resizing the viewport to the document's scroll height just + # before the final screenshot. (This keeps existing coordinate-click behavior intact.) + full_page_via_viewport = False + requested_viewport_width = None + async def resolve_viewport_point(px: int, py: int) -> tuple[float, float]: """ Playwright's `document.elementFromPoint(x, y)` uses viewport coordinates. @@ -251,8 +257,15 @@ async def interactions_service( vp_width = getattr(viewport, "width", None) vp_height = getattr(viewport, "height", None) + requested_viewport_width = vp_width if vp_width and vp_height: - await page.set_viewport_size({"width": vp_width, "height": vp_height}) + if int(vp_height) == -1: + # Defer height calculation until after navigation/interactions. + full_page_via_viewport = True + vp_size = page.viewport_size or {"width": 1280, "height": 720} + await page.set_viewport_size({"width": int(vp_width), "height": int(vp_size.get("height", 720))}) + else: + await page.set_viewport_size({"width": int(vp_width), "height": int(vp_height)}) except Exception as e: print(f"Error setting viewport: {e}") @@ -405,7 +418,30 @@ async def interactions_service( if return_type == "html": return await page.content() - # For coordinate-based workflows, return the viewport screenshot so pixel coords align. + if full_page_via_viewport: + try: + # Chromium has practical limits on viewport height; cap to avoid errors. + max_vp_h = 16384 + + # Ensure we capture from the top of the document. + await page.evaluate("() => window.scrollTo({ left: 0, top: 0, behavior: 'auto' })") + await page.wait_for_timeout(250) + + full_h = await page.evaluate( + "() => Math.max(document.body?.scrollHeight || 0, document.documentElement?.scrollHeight || 0)" + ) + target_h = int(min(max(full_h, 1), max_vp_h)) + + cur_vp = page.viewport_size or {"width": 1280, "height": 720} + target_w = int(requested_viewport_width or cur_vp.get("width", 1280)) + + await page.set_viewport_size({"width": target_w, "height": target_h}) + await page.wait_for_timeout(500) + except Exception as e: + print(f"Error resizing viewport for full-page capture: {e}") + + # For coordinate-based workflows, default is viewport screenshot so pixel coords align. + # If full_page_via_viewport is enabled, the viewport has been expanded to the full document height. return await page.screenshot(full_page=False, type="png") except Exception as e: