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

Use pytest-html’s extras API to attach screenshots to a test’s HTML report. Add an image with pytest_html.extras.image(...), either from a report hook or the extras fixture. For Selenium tests, pytest-selenium can also collect screenshots automatically when a test fails. Choose the approach based on when you need captures, which browser framework you use, and whether the report must be a single portable file.

Install pytest-html and create a report

Install the reporting plugin in the same Python environment used to run your tests:

python -m pip install pytest-html

Run pytest with the HTML report option:

pytest --html=report.html

This creates report.html in the current working directory. The report will contain test results, but screenshots appear only after you add them as extra content or configure a plugin that gathers them.

Add a screenshot with the extras fixture

If a test can capture its own screenshot, the extras fixture is the most direct route. Capture the image to a file, then attach it using pytest_html.extras.image:

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


def test_page_loads(driver, extras):
    driver.get("https://example.com")

    screenshot_path = "page-loads.png"
    driver.save_screenshot(screenshot_path)
    extras.append(pytest_html.extras.image(screenshot_path, name="Page screenshot"))

    assert "Example" in driver.title

Here, driver is assumed to be a Selenium WebDriver fixture provided by your project or another plugin; pytest does not supply a universal browser fixture. Replace the example URL and fixture with the ones your test suite actually uses. The screenshot is attached after capture, so place the capture and append operation at the point in the test when the page state is useful.

The extras API also accepts image data or a URL. The documentation provides format helpers including pytest_html.extras.png(...) and pytest_html.extras.jpg(...). Use a helper when you want to make the image format explicit; use image(...) when a path, URL, or image data is more convenient.

Attach screenshots from a report hook

A report hook is useful when screenshot handling should happen as part of pytest’s reporting lifecycle—for example, to add a screenshot only when a test fails. The hook below assumes your project provides a driver fixture. Adjust the fixture lookup for your browser setup.

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_path = f"{item.name}.png"
    driver.save_screenshot(screenshot_path)

    extras = getattr(report, "extras", [])
    extras.append(pytest_html.extras.image(screenshot_path, name="Failure screenshot"))
    report.extras = extras

The hook runs after a test phase has produced a report. Checking report.when == "call" restricts this example to failures in the test body; setup and teardown failures have different report phases. Remove that condition or handle those phases separately if you also need captures for setup or teardown problems. The check for a missing driver avoids failing the reporting hook for tests that do not use a browser.

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

Use the plural property report.extras. The singular report.extra API was deprecated in pytest-html 4.0.0. If your report hook is composed with other plugins, append to the existing extras list rather than replacing content that another plugin has already added.

Choose the capture approach that fits your tests

Approach Best fit Trade-off to consider
pytest-html extras fixture A test already knows when and what to capture. Each relevant test must capture and attach its image.
pytest_runtest_makereport hook Centralized attachment logic, such as screenshots on test failure. The hook must find the browser fixture and handle tests without one.
pytest-selenium automatic debug capture Selenium suites that want plugin-collected diagnostics, especially on failure. Collecting debug data always can make the report substantially larger.
pytest-report-extras Teams wanting documented screenshot and step integrations for pytest-html or Allure, including Selenium and Playwright. Its documented constraints include no parallel test execution support, sync Playwright only, and limited support for pytest-html’s self-contained option.

Use pytest-selenium for automatic failure screenshots

The pytest-selenium plugin documents collection of browser debug information on failure by default, including the page URL, page HTML, logs, and a screenshot. Its capture timing can be set to never, failure (the default), or always. Capturing debug information always may dramatically increase report size, so enable it only when the additional evidence is useful.

You can also exclude debug categories through configuration or the SELENIUM_EXCLUDE_DEBUG environment variable. This is useful when you want to keep screenshots while omitting other collected data, or when a report should avoid carrying unnecessary or sensitive diagnostics. The pytest_selenium_capture_debug hook can save screenshots to the file system, including in workflows that do not use --html.

Handle report files and self-contained HTML

A report that references a screenshot file is not necessarily a self-contained artifact. pytest-html supports --self-contained-html, but its guide warns that images added as files or links are external resources and may not display as expected in the standalone HTML. pytest-html issues a warning when such resources are added.

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

Decide how the report will be delivered before choosing a packaging approach:

  • Report plus image files: Preserve the referenced image files and the relative paths expected by the report when you archive or publish the results.
  • Standalone HTML: Run with --self-contained-html, then inspect the generated file in the destination environment. Do not assume that an attached file or URL image has been embedded just because the report is a single HTML document.
  • CI artifact: Upload the report and any linked screenshot assets together unless you have verified that the screenshots are embedded and render without external files.

Always open the delivered artifact in the same kind of environment where readers will view it. A report that works beside the test output directory may lose its screenshots after someone downloads only the HTML file.

Keep capture costs and failure modes under control

Limit screenshots to useful test states

Failure-only capture is a practical default for a large suite: it preserves evidence for diagnosing problems without creating an image for every passing test. Capture on success as well when the purpose is visual review or when the test state itself is the deliverable. If a screenshot is taken too early, it may show a loading state rather than the state under test; trigger capture only after the relevant page condition is met.

Watch report size and diagnostic exposure

Images and other debug attachments increase the amount of data your report must store and move. If your CI system retains reports or enforces artifact limits, review the combined report and screenshot assets. Browser screenshots can also contain account details, personal information, tokens displayed in the page, or internal application data. Capture only what is needed and restrict access to reports accordingly.

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

Make screenshot filenames safe and distinct

When writing screenshots from a hook, avoid filenames that can collide across tests or workers. A test name may be sufficient in a simple sequential run, but parallel or parametrized suites can require a unique identifier or per-test directory. The third-party pytest-report-extras guide specifically lists no parallel test execution support, so check its constraints against your execution model before adopting it.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Common problems and fixes

Symptom Likely cause What to check
No screenshot appears in the report. The image was saved but never added as an extra, or the hook did not run for the report phase you expected. Confirm extras.append(...) runs and is assigned to report.extras; check failure conditions and the report.when filter.
The hook raises an error on non-browser tests. The test has no driver fixture. Use a guarded lookup such as item.funcargs.get("driver") and skip attachment when there is no driver.
A screenshot is missing after sharing the report. The report points to an external image file that was not included or its relative path changed. Ship the report with its image assets and verify the paths, or test the self-contained output in the intended viewer.
The HTML file is large. Every test may be collecting screenshots or other debug data. Use failure-only capture where appropriate and exclude unneeded debug categories.
The screenshot shows the wrong state. Capture ran before navigation or a required page update completed. Wait for the page condition your test relies on, then capture at that point.

Or skip the browser setup

If you need a screenshot of a public page rather than a browser state produced inside the test, ScreenshotNeo offers a screenshot API and MCP server. Its one-request API can return a PNG, JPEG, WebP, or PDF; the request below saves a WebP response. See the ScreenshotNeo 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

ScreenshotNeo accepts cookie or consent banners as a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and responses identify the page verdict and billing status in headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots per month without a card; paid plans start at $5 for 3,000 screenshots.

For screenshots of an app state created by a test, keep using the test’s browser driver and attach its captured image to pytest-html. For page captures that do not need that browser setup, visit ScreenshotNeo. Sign up for 1,000 free screenshots a month with no card.

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

Frequently Asked Questions

Can I add screenshots to pytest-html without Selenium?

Yes. The pytest-html extras API accepts an image path, data, or URL; capture the image with your browser framework or another method, then attach it through the fixture or report hook.

Can I attach screenshots from Playwright tests?

The pytest-html image extras mechanism is not limited to Selenium, but capture code depends on your Playwright fixtures. The documented pytest-report-extras integration supports sync Playwright only.

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.