Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use pytest-html’s image extras: capture a screenshot, add it with pytest_html.extras.image(...), and attach the resulting extras to the test report. For Selenium suites, you can instead use pytest-selenium’s automatic failure debugging. The right route depends on whether you need a screenshot of a particular test state, automatic failure evidence, or a report that can travel as one file.

Choose the screenshot route that matches your tests

There are three practical approaches. Direct pytest-html extras work with screenshots from any browser or tool, provided your test can produce an image file or image data. pytest-selenium can gather screenshots and other debugging information automatically for Selenium tests. A third-party option, pytest-report-extras, offers screenshot and step integrations for pytest-html and Allure, with compatibility constraints to weigh before adopting it.

Route Best fit Trade-off to check
pytest-html extras Custom capture timing, browser stacks beyond Selenium, or precise control over what is attached You must capture the image and add it to the report yourself
pytest-selenium debug capture Selenium suites that want failure-oriented browser evidence with little custom attachment code Debug capture may include page HTML, logs, and URL information as well as screenshots
pytest-report-extras Teams wanting higher-level screenshot or test-step integration across supported tools Parallel execution is unsupported; Playwright support is synchronous only, and self-contained pytest-html reports have limited support

The examples below focus on the direct pytest-html route because it lets you control precisely when a screenshot is captured and attached. Exact browser fixture names vary by test framework and project; the report attachment API does not provide a universal browser fixture.

Install pytest-html and create a report

Install pytest-html in the same environment as the test runner, then request an HTML report when running pytest:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
python -m pip install pytest-html
pytest --html=report.html

Pytest runs the tests and writes report.html. The report is useful only if your test or a plugin adds the screenshot as an extra. You can add extras directly through the extras fixture, or use a pytest hook when you want to attach images centrally after a test outcome is known.

Add a screenshot from a test with the extras fixture

Use this pattern when a test itself decides when the screenshot should be taken. The example assumes your project provides a Selenium driver fixture and that the test has already created the desired browser state. The extras fixture is supplied by pytest-html.

import pytest_html

def test_checkout(driver, extras):
    driver.get("https://example.com/checkout")
    # Perform the actions needed to reach the state you want to document.

    screenshot_path = "checkout.png"
    driver.save_screenshot(screenshot_path)
    extras.append(pytest_html.extras.image(screenshot_path, name="Checkout state"))

    assert "Checkout" in driver.title

Run the test with pytest --html=report.html. If the image path is valid when pytest-html builds the report, the extra appears with that test. Use a path that is unique per test when several tests may run in the same session; otherwise one test can overwrite another test’s file.

The extras image helper accepts image data, a path, or a URL. Format helpers such as pytest_html.extras.png(...) and pytest_html.extras.jpg(...) are also available. Use the helper that matches the data you have; don’t pass a URL where a local file is expected by your own capture code.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Attach screenshots centrally with pytest_runtest_makereport

A hook is useful when screenshot capture should follow a shared policy, such as attaching an image only after a failed test. The hook runs after pytest has produced a report for a test phase. The example below assumes a Selenium driver fixture and captures only the call-phase failure.

import pytest
import pytest_html

@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

    screenshot = driver.get_screenshot_as_png()
    extras = list(getattr(report, "extras", []))
    extras.append(pytest_html.extras.png(screenshot, name="Failure screenshot"))
    report.extras = extras

Save this hook in conftest.py so pytest discovers it for the relevant tests. It uses the plural report.extras attribute; pytest-html deprecated the singular report.extra API in version 4.0.0. The hook checks for a fixture named driver but does not create that fixture. If your suite uses another name or browser framework, adapt the lookup and capture call to the fixture your project actually supplies.

This example attaches a screenshot only for a failed call phase. Setup and teardown failures are separate phases; add handling for them only if your suite can safely access a live browser there. A driver may not exist if setup failed before browser creation, and it may already be closed during teardown.

Use pytest-selenium for automatic failure debugging

If your tests use pytest-selenium, the plugin documents automatic collection of debugging information on failure by default, including a screenshot, page URL, page HTML, and logs. Its capture timing can be configured as never, failure (the default), or always. Always collecting debug information can dramatically increase report size.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choose failure capture when you mainly need evidence to diagnose broken tests. Choose always only when screenshots from passing tests are a deliberate requirement and the extra storage and report weight are acceptable. You can exclude debug categories using the plugin’s configuration or the SELENIUM_EXCLUDE_DEBUG environment variable. Check the plugin’s configuration for the accepted category names and syntax for your installed version rather than guessing them.

The pytest_selenium_capture_debug hook can also save screenshots to the file system, including when you are not using --html. That is useful when the report is not the only artifact consumers need, or when you want to keep image files separately.

Decide whether the report should be one file or a bundle

--self-contained-html creates a report intended to be shared as a standalone HTML file, but pytest-html warns that image extras added as files or links are external resources and may not display as expected in that file. It issues a warning when external resources are added. A report that opens correctly on your workstation may therefore fail to show images after being uploaded or sent alone.

  • For a standalone artifact: generate it with pytest --html=report.html --self-contained-html, read any resource warning, and verify that the screenshots display after copying just the HTML file to the actual destination.
  • For a report plus image files: retain the referenced image files and preserve the expected relative paths when you archive or publish the output. Test the bundle from its delivery location.

Do not assume that changing how the browser captures the screenshot solves the packaging issue. Capture and report packaging are separate decisions: the former produces image content, while the latter determines whether the report can still find that content when moved.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Keep screenshots useful, safe, and manageable

  • Capture at the meaningful point. A screenshot taken before the assertion or before the failing action may not show the state that explains the failure.
  • Use specific names. Label extras with a test-relevant name such as “Checkout state” or “Failure screenshot” so readers can distinguish them.
  • Limit automatic debug collection. Screenshots plus page HTML and logs can make reports larger and may expose information that should not be shared. Exclude unneeded debug categories and restrict access to reports containing sensitive test data.
  • Avoid shared output filenames. In parallel or repeated tests, use per-test paths or in-memory image bytes to prevent collisions and accidental replacement.
  • Check the final artifact. Open the generated report in the same delivery arrangement your team uses, especially when using self-contained HTML or a CI artifact archive.

Troubleshoot missing screenshots

  • The report appears but has no image: confirm the test appended an extra or the hook assigned report.extras, then inspect whether the screenshot path existed when the report was generated.
  • The screenshot belongs to another test: multiple tests likely wrote to the same filename. Generate unique names or attach screenshot bytes directly.
  • The hook runs but does not attach anything: verify that the phase is the one you intended (call in the example), that the test failed in that phase, and that the expected fixture is present in item.funcargs.
  • Standalone report shows a broken image or warning: file and URL extras can remain external resources. Deliver the image files with the HTML or verify the self-contained artifact in its intended destination.
  • Reports are unexpectedly large: automatic capture may be collecting debug categories for every test. Set capture timing to failure or never as appropriate, and exclude data you do not need.
  • A third-party integration fails under parallel execution: pytest-report-extras documents no parallel test execution support. Use the direct pytest-html route or reassess the integration against the project’s execution model.

Or skip the browser setup

If you need a screenshot of a public page rather than the exact in-test browser state, ScreenshotNeo can return an image from one request. Its API is not a substitute for capturing a Selenium session after test actions; use the direct methods above for that. See the ScreenshotNeo API documentation for request options.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Then add shot.webp to pytest-html using pytest_html.extras.image("shot.webp"), or use the image bytes in a hook. ScreenshotNeo removes cookie banners, popups, and chat widgets before capture; bot checks, blank pages, and failed loads are not billed. It also provides an MCP server for AI agents, and the free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000. Learn about ScreenshotNeo, or sign up for 1,000 free screenshots a month with no card.

Frequently Asked Questions

Can I attach a screenshot taken by Playwright instead of Selenium?

Yes. The pytest-html image extra accepts image data or a file path; capture the screenshot with your Playwright page and pass the resulting bytes or saved path to the extra.

Does pytest-html take screenshots automatically?

The examples here explicitly add an image extra. Automatic Selenium debug capture is provided by pytest-selenium, not by the direct extras mechanism.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.