Resource library

QA How-To

Selenium full page screenshot in Python (2026)

Learn Selenium full page screenshot Python methods for Firefox and Chrome, with runnable code, lazy-load handling, pytest reporting, and practical CI tips.

20 min read | 2,778 words

TL;DR

Firefox can save the complete document with save_full_page_screenshot(). Chrome and Edge require a Chromium-specific Page.captureScreenshot call with captureBeyondViewport enabled. In both cases, synchronize the page first and keep capture logic in a tested helper.

Key Takeaways

  • Use Firefox save_full_page_screenshot for the simplest native full-document capture.
  • Use Page.getLayoutMetrics and Page.captureScreenshot for full-page Chrome or Edge artifacts.
  • Do not confuse save_screenshot, fullscreen browser mode, or a tall window with full-document capture.
  • Wait for application data, fonts, animations, and selected lazy assets before taking evidence.
  • Centralize browser detection and preserve the original test failure if artifact creation fails.
  • Use unique artifact names and validate every PNG before uploading it from CI.

The most reliable Selenium full page screenshot Python workflow depends on the browser. Firefox provides a native full-document screenshot method, while Chromium browsers can capture the document through the Chrome DevTools Protocol. A normal save_screenshot() call usually captures only the visible viewport, so it is not a full-page solution.

This guide gives you runnable Selenium 4 examples for Firefox and Chrome, a browser-aware helper, synchronization techniques for lazy content, and pytest integration for failure evidence. It also explains when a stitched screenshot is still appropriate and how to validate that an image really covers the document.

TL;DR

Need Recommended approach Important limitation
Full page in Firefox save_full_page_screenshot() Firefox-specific API
Full page in Chrome or Edge execute_cdp_cmd() with Page.captureScreenshot Chromium-specific CDP command
Current viewport only save_screenshot() Does not include content below the fold
One element element.screenshot() Captures the element, not the document
Portable fallback Scroll and stitch image tiles Requires overlap and fixed-element handling

Use the browser-native path where possible. Wait for the page state you care about, reveal lazy-loaded content, capture into a unique artifact path, and verify that the file is a nonempty PNG.

1. Selenium full page screenshot Python: viewport versus document

WebDriver's standard screenshot command captures the current top-level browsing context. In practice, the output commonly represents the visible viewport, which is the rectangular area currently rendered inside the browser window. The document can be much taller because it includes content that becomes visible only after scrolling.

That distinction matters in defect evidence. A viewport image may show the error banner but omit the submit button, footer, or later validation message. A full-document image provides page-level context in one artifact. It is useful for layout reviews, long checkout forms, content audits, and debugging responsive pages. It is not automatically a visual regression strategy, because animation, timestamps, personalized content, and font rendering can still produce noise.

Three screenshot scopes are easy to confuse:

  1. driver.save_screenshot(path) captures the browser's screenshot result, normally the current viewport.
  2. element.screenshot(path) captures one located element and is ideal when the defect is local.
  3. A browser-specific full-page command captures the entire document surface beyond the visible viewport.

Fullscreen browser mode is also unrelated. driver.fullscreen_window() changes window chrome and viewport size, but it does not guarantee that a page taller than the screen will fit. Similarly, setting a very tall window can hit operating-system or browser limits and can change responsive breakpoints. Treat screenshot scope as an explicit technical choice, not a side effect of window sizing.

2. Install Selenium and create a deterministic capture directory

Use a current Selenium 4 Python package and let Selenium Manager resolve a compatible local driver when your environment permits it. A minimal setup is:

python -m venv .venv
source .venv/bin/activate
python -m pip install -U selenium pillow pytest

On Windows PowerShell, activate with .venv\\Scripts\\Activate.ps1. Pillow is not required to take the screenshot, but it is useful for validating image dimensions and for implementing a stitching fallback. Pin the exact versions in your project lock file after you prove the setup in CI.

Create artifact directories before capture and use filenames that cannot collide across parallel tests:

from datetime import datetime, timezone
from pathlib import Path
import re


def screenshot_path(test_name: str, browser_name: str) -> Path:
    safe_name = re.sub(r'[^A-Za-z0-9_.-]+', '_', test_name)
    stamp = datetime.now(timezone.utc).strftime('%Y%m%dT%H%M%S_%fZ')
    directory = Path('artifacts') / 'screenshots' / browser_name
    directory.mkdir(parents=True, exist_ok=True)
    return directory / f'{safe_name}_{stamp}.png'

UTC timestamps simplify correlation with Grid and application logs. The microseconds reduce collisions, but a worker identifier or UUID is appropriate for very large parallel suites. Keep the path relative to the test workspace so CI can upload the entire artifacts directory. If screenshots might contain customer data, define retention and access controls just as you would for logs.

For related locator setup, see Selenium CSS selector examples in Python. Stable locators and stable page state are prerequisites for useful evidence.

3. Capture a native full-page screenshot in Firefox

Selenium's Firefox driver exposes save_full_page_screenshot(filename). It asks Firefox to capture the full document and returns True when the file is written successfully. This is the cleanest Python solution when Firefox is an acceptable capture browser.

from pathlib import Path
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait


output = Path('artifacts/screenshots/firefox-home.png').resolve()
output.parent.mkdir(parents=True, exist_ok=True)

options = webdriver.FirefoxOptions()
options.add_argument('-headless')

driver = webdriver.Firefox(options=options)
try:
    driver.set_window_size(1440, 900)
    driver.get('https://www.selenium.dev/')
    WebDriverWait(driver, 15).until(
        EC.visibility_of_element_located((By.CSS_SELECTOR, 'main'))
    )

    written = driver.save_full_page_screenshot(str(output))
    if not written:
        raise OSError(f'Firefox did not write {output}')
finally:
    driver.quit()

print(output)

The alias get_full_page_screenshot_as_file() is also available, but save_full_page_screenshot() communicates intent clearly. Firefox also provides byte and Base64 variants when an attachment system accepts in-memory data. Prefer a file when your CI system already uploads artifacts, and bytes when a reporter API accepts them without an intermediate file.

Set the window width before navigation or capture. Full-page means full height, not an arbitrary universal width. A 1440-pixel viewport and a 390-pixel mobile viewport can produce radically different documents because responsive CSS changes navigation, wrapping, and component order. Record the chosen viewport in test metadata. The native method handles the vertical extent, while your test retains control of the layout width.

4. Capture the full page in Chrome with CDP

ChromeDriver and EdgeDriver expose Selenium's execute_cdp_cmd() bridge. The workflow reads the CSS document size with Page.getLayoutMetrics, then asks Page.captureScreenshot to capture that rectangle beyond the viewport. The response contains Base64-encoded PNG bytes.

import base64
from pathlib import Path
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait


def save_chromium_full_page(driver: webdriver.Chrome, filename: Path) -> Path:
    metrics = driver.execute_cdp_cmd('Page.getLayoutMetrics', {})
    size = metrics['cssContentSize']
    width = max(1, int(round(size['width'])))
    height = max(1, int(round(size['height'])))

    result = driver.execute_cdp_cmd(
        'Page.captureScreenshot',
        {
            'format': 'png',
            'fromSurface': True,
            'captureBeyondViewport': True,
            'clip': {
                'x': 0,
                'y': 0,
                'width': width,
                'height': height,
                'scale': 1,
            },
        },
    )
    filename.parent.mkdir(parents=True, exist_ok=True)
    filename.write_bytes(base64.b64decode(result['data']))
    return filename


options = webdriver.ChromeOptions()
options.add_argument('--headless=new')
options.add_argument('--window-size=1440,900')

driver = webdriver.Chrome(options=options)
try:
    driver.get('https://www.selenium.dev/')
    WebDriverWait(driver, 15).until(
        EC.visibility_of_element_located((By.CSS_SELECTOR, 'main'))
    )
    image = save_chromium_full_page(
        driver, Path('artifacts/screenshots/chrome-home.png')
    )
    print(image.resolve())
finally:
    driver.quit()

Use cssContentSize, not the older device-pixel contentSize, so the clip is expressed consistently in CSS pixels. captureBeyondViewport is essential because the requested rectangle extends below the visible area. This path is browser-specific and should be isolated behind a helper. It is not part of the cross-browser WebDriver screenshot contract, and a remote vendor can restrict raw CDP access.

Very tall pages can exceed renderer, protocol, memory, or PNG dimension limits. For an unbounded feed, define a business-relevant stopping point rather than trying to capture an infinite document. For a finite but extreme page, use tiled capture and stitching.

5. Selenium full page screenshot Python: build one browser-aware helper

A test should request a full-page artifact without knowing the low-level protocol. Centralize browser detection, file creation, and failure messages in one function. This keeps test code readable and makes unsupported environments visible.

import base64
from pathlib import Path
from selenium.webdriver.remote.webdriver import WebDriver


def save_full_page(driver: WebDriver, filename: str | Path) -> Path:
    path = Path(filename).resolve()
    path.parent.mkdir(parents=True, exist_ok=True)
    browser = str(driver.capabilities.get('browserName', '')).lower()

    if browser == 'firefox':
        save_method = getattr(driver, 'save_full_page_screenshot', None)
        if save_method is None or not save_method(str(path)):
            raise OSError(f'Could not save Firefox screenshot to {path}')
        return path

    if browser in {'chrome', 'msedge'}:
        metrics = driver.execute_cdp_cmd('Page.getLayoutMetrics', {})
        size = metrics['cssContentSize']
        response = driver.execute_cdp_cmd(
            'Page.captureScreenshot',
            {
                'format': 'png',
                'captureBeyondViewport': True,
                'fromSurface': True,
                'clip': {
                    'x': 0,
                    'y': 0,
                    'width': max(1, int(round(size['width']))),
                    'height': max(1, int(round(size['height']))),
                    'scale': 1,
                },
            },
        )
        path.write_bytes(base64.b64decode(response['data']))
        return path

    raise NotImplementedError(
        f'Full-page capture is not configured for browser {browser!r}'
    )

The getattr check is deliberate. Static typing sees a generic WebDriver, while the full-page method belongs to the Firefox-specific driver. The runtime capability selects the branch safely. Avoid silently falling back to save_screenshot(), because that would produce a plausible PNG with the wrong scope. A hard, explanatory failure is better evidence than a misleading success.

If you use a cloud grid, test this helper against the actual provider. Capabilities can report branded or vendor-specific names, and providers may offer their own artifact APIs. Keep vendor mapping in the helper rather than scattering conditions through tests.

6. Wait for a capture-ready page, not just page load

Navigation completion does not mean the screenshot is ready. Client-rendered applications may still be fetching data, loading fonts, replacing skeletons, or animating panels. A fixed sleep guesses at timing and makes both test duration and output inconsistent. Wait for a state that represents the evidence you need.

from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait


wait = WebDriverWait(driver, 20)
wait.until(EC.invisibility_of_element_located((By.CSS_SELECTOR, '[data-testid="loading"]')))
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, '[data-testid="report"]')))

driver.execute_script('''
    for (const animation of document.getAnimations()) {
        animation.finish();
    }
''')

Use application signals where available: a loading indicator disappears, a results container becomes visible, or a known API-driven count reaches the expected value. Finishing Web Animations can reduce transient frames in a controlled test environment, but do not do it in a test whose purpose is to validate motion.

Web fonts deserve attention because a late font swap changes line wrapping and total document height. A JavaScript wait can check document.fonts.ready:

driver.set_script_timeout(15)
driver.execute_async_script('''
    const done = arguments[arguments.length - 1];
    document.fonts.ready.then(() => done(true), () => done(false));
''')

For general asynchronous JavaScript patterns, read Selenium executeAsyncScript in Python. The core rule is to capture a defined application state. The screenshot should explain a test result, not merely prove that a browser window existed.

7. Reveal lazy-loaded content without creating an infinite-scroll loop

Full-page capture can include blank placeholders when images or cards load only after intersection with the viewport. Scroll through the finite document before taking the final native capture. Recalculate height on every iteration because lazy content can extend the page.

from time import monotonic, sleep


def warm_lazy_content(driver, timeout: float = 15.0, step: int = 700) -> None:
    deadline = monotonic() + timeout
    position = 0
    stable_rounds = 0
    previous_height = 0

    while monotonic() < deadline and stable_rounds < 3:
        height = int(driver.execute_script(
            'return Math.max(document.body.scrollHeight, '
            'document.documentElement.scrollHeight);'
        ))
        position = min(position + step, height)
        driver.execute_script('window.scrollTo(0, arguments[0]);', position)
        sleep(0.15)

        if position >= height and height == previous_height:
            stable_rounds += 1
        else:
            stable_rounds = 0
        previous_height = height

    driver.execute_script('window.scrollTo(0, 0);')

This helper has a deadline and a stability condition, so it cannot scroll forever. Still, use it only when scrolling is an intended way to reveal content. Some applications paginate automatically and can keep adding records. In that case, stop at a known card, mock the dataset to a fixed size, or capture a defined component instead of the full feed.

Native lazy loading for images can also be checked by waiting until relevant images report complete and have a nonzero naturalWidth. Do not fail on tracking pixels or intentionally broken fixtures. Select the images that are part of the scenario.

Fixed headers and cookie notices can obscure content. A native single-surface capture often paints a fixed element once, while a manual stitch may repeat it on every tile. Dismiss legitimate overlays through the UI when that matches the test. Do not inject CSS to hide a real defect unless the artifact is explicitly a layout diagnostic with that modification documented.

8. Validate the PNG and prove that it covers the document

A screenshot call can complete while the resulting artifact is empty, truncated, or the wrong scope. Add lightweight validation before attaching it to a report. At minimum, check existence, size, format, and dimensions.

from pathlib import Path
from PIL import Image


def assert_valid_full_page_png(driver, path: Path) -> None:
    assert path.is_file(), f'Missing screenshot: {path}'
    assert path.stat().st_size > 0, f'Empty screenshot: {path}'

    with Image.open(path) as image:
        image.verify()

    with Image.open(path) as image:
        width, height = image.size

    document_height = int(driver.execute_script(
        'return Math.ceil(Math.max(document.body.scrollHeight, '
        'document.documentElement.scrollHeight));'
    ))
    assert width > 0 and height > 0
    assert height >= document_height, (
        f'Image height {height} is below document height {document_height}'
    )

Pixel height may differ from CSS document height when device scale factor, browser zoom, or protocol scaling is involved. The simple height >= document_height assertion works for a scale of one or higher, but your team should record device pixel ratio and adjust the expectation if it deliberately uses another scale. The strongest functional check is scenario-specific: confirm that a footer, final row, or sentinel element appears in the intended page state before capture.

Do not compare file size as a visual assertion. PNG compression varies with content, and a nearly blank image can sometimes be smaller without being invalid. For visual regression, normalize dynamic regions and use an image comparison tool designed for baselines. A screenshot helper should establish artifact integrity, while a visual test establishes UI equivalence.

9. Attach full-page screenshots to pytest failures

A pytest hook can capture after a failed test call while the driver is still alive. Keep driver lifecycle and reporting responsibilities clear. The example below assumes a driver fixture and writes artifacts even without a third-party report plugin.

# conftest.py
from pathlib import Path
import pytest


@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
    outcome = yield
    report = outcome.get_result()
    if report.when != 'call' or not report.failed:
        return

    driver = item.funcargs.get('driver')
    if driver is None:
        return

    browser = str(driver.capabilities.get('browserName', 'browser'))
    target = Path('artifacts/screenshots') / f'{item.nodeid.replace("/", "_").replace("::", "_")}_{browser}.png'

    try:
        save_full_page(driver, target)
        item.add_report_section('call', 'screenshot', str(target.resolve()))
    except Exception as error:
        item.add_report_section(
            'call', 'screenshot-error', f'{type(error).__name__}: {error}'
        )

Because pytest_runtest_makereport is a hook wrapper, it observes the completed report. Capture only during the call phase in this example to avoid duplicate files for setup and teardown failures. If setup failures matter, explicitly handle those phases and make sure the driver fixture has been created.

Sanitize nodeid more thoroughly on Windows and add the parallel worker ID when using pytest-xdist. Report plugins have different attachment APIs, so treat the local file as the portable foundation and add an adapter for Allure, HTML reports, or your CI provider.

Capture can itself fail if the original test closed the window, crashed the renderer, or invalidated the session. Never replace the original assertion with the screenshot exception. The hook above records capture failure as supplementary information. This distinction protects the real root cause.

10. Choose native capture, CDP, element capture, or stitching

The right method follows the diagnostic goal and supported browser matrix.

Approach Browser reach Best use Main tradeoff
Firefox native full page Firefox Simple document evidence Not available on generic drivers
Chromium CDP capture Chrome and Edge High-quality full surface Protocol-specific integration
Standard viewport screenshot All conforming drivers Failure at current scroll position Misses below-fold content
Element screenshot Supported modern drivers Focused component evidence Omits surrounding page context
Scroll and stitch Potentially broad Fallback for unsupported environments Complex around fixed UI and overlap

Stitching works by taking viewport tiles, scrolling by a measured amount, cropping any overlap, and composing the tiles with Pillow. It must account for device pixel ratio, the final partial tile, horizontal scrollbars, fixed elements, and content that changes while scrolling. That is enough complexity to justify a tested library or a small internal component with dedicated fixtures. It should not be a twenty-line utility copied into each test class.

Use an element image when the issue is a single widget. The Selenium element screenshot Python guide covers that narrower and often more stable option. For Java teams investigating the same scope, Selenium element screenshot in Java provides equivalent patterns.

A good policy is explicit: native full-page for supported browsers, element or viewport capture for targeted evidence, and stitching only for a documented compatibility requirement. Store the chosen method with the artifact metadata so a reviewer knows what was and was not visible.

Interview Questions and Answers

Q: Why does save_screenshot() not always capture the whole page?

It uses the standard WebDriver screenshot command for the current browsing context, which normally represents the rendered viewport. The document can extend below that viewport. A browser-specific full-page method or protocol capture is required to include that extra surface.

Q: What is the preferred full-page method for Firefox in Selenium Python?

Use driver.save_full_page_screenshot(path). It is exposed by Selenium's Firefox driver and returns a boolean indicating whether the PNG was written. Set a deliberate viewport width and wait for the intended state before calling it.

Q: How do you capture the full page in Chrome?

Read cssContentSize through Page.getLayoutMetrics, then call Page.captureScreenshot with a clip covering that size and captureBeyondViewport set to True. Decode the returned Base64 data and write it as bytes. Encapsulate the CDP commands because they are Chromium-specific.

Q: Why is resizing the browser to scrollHeight a weak solution?

Window managers and browsers can cap dimensions, and an extreme height can consume substantial memory. Resizing can also alter responsive layout and trigger application behavior. Native surface capture avoids depending on a giant OS window, although it still has image-size limits.

Q: How would you handle lazy-loaded images before capture?

Scroll through a finite page in measured steps, wait for the selected images or content sentinels to become ready, then return to the top and capture. Add a deadline and a stable-height limit so an infinite feed cannot hang the test. Prefer a fixed test dataset for repeatable output.

Q: How do screenshots behave in frames?

A full-page browser capture is primarily about the top-level document surface. If the defect is inside an iframe, switch to the frame, locate the meaningful element, and consider an element screenshot plus a top-level context image. Cross-origin frames and provider implementations can affect what is available.

Q: What should happen if screenshot capture fails during test reporting?

Preserve the original test failure and record the screenshot error as secondary diagnostic data. A reporting hook must not mask the application assertion with an artifact exception. Always quit the driver in fixture teardown after the hook has had a chance to capture.

Q: Is a full-page screenshot the same as a visual regression test?

No. It is an image artifact with broad page context. Visual regression additionally needs a controlled viewport, fonts, data, animations, masking rules, approved baselines, comparison thresholds, and useful diff output.

Common Mistakes

  • Calling save_screenshot() and labeling the viewport PNG as full page.
  • Using fullscreen_window() as if fullscreen meant full document.
  • Taking the image immediately after get() while skeletons, fonts, or API data are still changing.
  • Hard-coding sleeps instead of waiting for a meaningful UI state.
  • Running an unbounded scroll loop on an infinite feed.
  • Ignoring viewport width, which makes responsive screenshots impossible to compare.
  • Writing every parallel test to screenshot.png and losing earlier evidence.
  • Swallowing a capture exception or, at the other extreme, masking the original test failure with it.
  • Assuming raw CDP commands work on every remote Grid and every browser.
  • Hiding sticky elements with JavaScript without documenting that the artifact was modified.
  • Keeping screenshots containing secrets, tokens, addresses, or payment data without a retention policy.
  • Comparing raw color pixels across uncontrolled machines and treating every rendering difference as a product defect.

The practical prevention pattern is small: centralize capture, synchronize on application state, use unique artifact paths, validate the PNG, and test the helper on every browser and Grid configuration that will run it.

Conclusion

For a Selenium full page screenshot in Python, use Firefox's save_full_page_screenshot() when you run Firefox, and use Page.getLayoutMetrics plus Page.captureScreenshot for Chrome or Edge. Keep the protocol detail behind a browser-aware helper, and fail clearly when a full-page path is unsupported.

Your next step is to add the helper to one representative end-to-end test, exercise it against a lazy-loaded page in local and CI environments, and confirm that the artifact includes the final page sentinel. Once that works, integrate it into failure reporting without allowing capture problems to hide the original test result.

Interview Questions and Answers

What is the difference between a viewport screenshot and a full-page screenshot in Selenium?

A viewport screenshot contains the area currently rendered inside the browser window. A full-page screenshot includes document content beyond the viewport, usually down to the document bottom. The latter needs a browser-specific capability in current Selenium implementations.

What API would you use for a Firefox full-page screenshot in Python?

I would use driver.save_full_page_screenshot(path) on a Firefox WebDriver instance. I would set a deliberate viewport width, wait for the expected page state, check its boolean result, and verify the PNG before attaching it.

How would you implement full-page capture for Chrome?

I would use execute_cdp_cmd to call Page.getLayoutMetrics and read cssContentSize. Then I would call Page.captureScreenshot with a clip covering that size and captureBeyondViewport set to true, decode the Base64 payload, and write the PNG. I would hide this Chromium-specific code behind a helper.

Why should a test not rely on a very tall browser window?

Window dimensions can be capped and a huge surface can consume excessive memory. Resizing can also change responsive behavior, so it may capture a different layout from the intended viewport. Native surface capture is more explicit and predictable.

How do you make a full-page screenshot deterministic?

I fix viewport width, data, locale, fonts, and relevant feature flags. I wait for business-ready UI signals, finish or disable irrelevant animation in the test environment, reveal finite lazy content, and use unique artifact names. I also record browser and viewport metadata.

How do you handle screenshot errors in a pytest failure hook?

I catch the artifact error and add it as secondary report information. The original assertion or exception remains the test's primary failure. Driver teardown happens only after the reporting hook has attempted capture.

When would you use an element screenshot instead of a full-page screenshot?

I use an element screenshot when the defect is confined to a component and page context adds noise. It creates smaller, more stable evidence and avoids unrelated dynamic regions. I may attach one viewport image as context if needed.

What are the risks of scroll-and-stitch capture?

Fixed elements can repeat, tiles can overlap or leave gaps, and lazy content can change document height during capture. Device pixel ratio and the final partial viewport also complicate cropping. I prefer browser-native capture and keep stitching as a tested fallback.

Frequently Asked Questions

How do I take a full page screenshot with Selenium in Python?

In Firefox, call driver.save_full_page_screenshot with a PNG path. In Chrome or Edge, use execute_cdp_cmd to read Page.getLayoutMetrics and call Page.captureScreenshot with a full-document clip and captureBeyondViewport enabled.

Does driver.save_screenshot capture the entire page?

Usually no. It invokes the standard screenshot command and commonly captures the current viewport. Use a browser-specific full-page API when content below the fold must be included.

Can Selenium take a full page screenshot in headless Chrome?

Yes. ChromeDriver can execute Page.captureScreenshot through CDP in headless mode. Read cssContentSize first, request a matching clip, and set captureBeyondViewport to true.

How do I capture lazy-loaded content in a Selenium screenshot?

Scroll through the finite page with a timeout so the content intersects the viewport, wait for selected assets to become ready, then capture the final document. Use fixed test data or a clear stopping sentinel for infinite feeds.

Why is my full-page screenshot cut off?

The capture may be using viewport scope, stale document dimensions, or a page that expanded after measurement. Extremely tall pages can also exceed browser or image limits. Wait for stable content, measure immediately before capture, and use tiles for genuinely large finite pages.

Is Chrome CDP full-page capture cross-browser?

No. execute_cdp_cmd and the Page domain are Chromium-specific. Firefox provides a separate native Selenium method, while other browsers or remote providers need a documented alternative.

Should screenshots be taken for every test?

Usually capture on failure and at a few high-value checkpoints. Capturing every step increases runtime, storage, review noise, and the risk of retaining sensitive data.

Related Guides