What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

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

Use Selenium’s save_screenshot method before the browser is closed: driver.save_screenshot('tmp/screenshots/example.png'). In Capybara specs, call the session’s save_screenshot helper. For hands-off failure artifacts, load capybara-screenshot/rspec after capybara/rspec. The examples below show each approach, where files go, how to handle full-page limits, and how to preserve screenshots in CI.

Choose the screenshot approach that matches your test

The correct API depends on who owns the browser session and whether capture is explicit or automatic.

Use case Recommended method What it captures Important condition
RSpec creates Selenium WebDriver directly driver.save_screenshot(path) PNG image of the current viewport Call it while the driver is alive
Capybara feature or system spec Capybara’s save_screenshot Image through the active Capybara driver Use a Selenium-backed driver, not the default rack-test driver
Every failed Capybara example capybara-screenshot Screenshot plus failed-page HTML for supported drivers Require its RSpec adapter after capybara/rspec

All three methods write local artifacts. They do not upload files to your CI provider automatically; your CI configuration must preserve the directory you choose.

Prerequisites and a predictable artifact directory

Add the libraries to your test dependencies. A direct Selenium spec needs Selenium WebDriver and RSpec. Capybara specs also need Capybara, and automatic failure capture adds capybara-screenshot.

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

Create the destination directory before saving. FileUtils.mkdir_p is ordinary Ruby filesystem setup, not a Selenium requirement. Relative paths are resolved from the process working directory, so a stable path such as tmp/screenshots is easier to collect in CI than a path based on the current source file.

Use unique names when examples can run concurrently. A timestamp, an example identifier, or a worker identifier prevents one process from overwriting another process’s image.

Direct Selenium WebDriver screenshot in RSpec

When your spec owns the driver, call save_screenshot in the example or in an after hook that runs before quit.

require 'fileutils'
require 'selenium-webdriver'

RSpec.describe 'page behavior' do
  before do
    @driver = Selenium::WebDriver.for :chrome
  end

  after do
    @driver&.quit
  end

  it 'captures the current view' do
    @driver.get('https://example.com')

    FileUtils.mkdir_p('tmp/screenshots')
    @driver.save_screenshot('tmp/screenshots/example.png')
  end
end

Selenium’s Ruby API saves a PNG screenshot of the viewport to the path you supply. Use a .png extension; a mismatched extension produces a warning. The browser must have navigated to a page before the image is useful, and the call must happen before the driver is torn down.

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

Capture only when an example fails

An RSpec after hook can inspect the example and save an image only when an exception exists. Keep the capture before quit, and sanitize the description so it is safe as a filename.

require 'fileutils'
require 'selenium-webdriver'

RSpec.describe 'checkout' do
  before do
    @driver = Selenium::WebDriver.for :chrome
  end

  after do |example|
    if example.exception && @driver
      FileUtils.mkdir_p('tmp/screenshots')
      label = example.full_description
                    .downcase
                    .gsub(/[^a-z0-9]+/, '-')
                    .sub(/A-/, '')
                    .sub(/-z/, '')
      @driver.save_screenshot("tmp/screenshots/#{label}.png")
    end

    @driver&.quit
  end

  it 'shows the order confirmation' do
    @driver.get('https://example.com/checkout')
    # assertions that may fail
  end
end

If setup fails before a driver is assigned, the @driver guard prevents the failure hook from raising a second exception. In a parallel test run, add a worker identifier to the filename or give each worker a separate output directory.

Capybara screenshots in an RSpec spec

Capybara’s Session#save_screenshot delegates to the active driver. In a feature or system spec, a relative filename is resolved against Capybara’s configured save directory; with no path, Capybara generates a filename under that directory.

require 'capybara/rspec'

RSpec.describe 'account page', type: :feature do
  it 'captures the page' do
    visit '/account'
    save_screenshot('account-page.png')
  end
end

Set Capybara.save_path, or the equivalent setting supported by your installed Capybara version, when you want a fixed artifact directory. Check the version used by the project because configuration defaults and APIs can evolve.

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.

Select a real browser driver

Capybara’s default :rack_test driver does not execute JavaScript and is not a Selenium browser. A screenshot that depends on browser rendering belongs in an example using a Selenium-backed driver such as :selenium, :selenium_chrome, or a configured headless Selenium driver.

require 'capybara/rspec'

RSpec.describe 'JavaScript account page', type: :feature do
  before do
    Capybara.current_driver = :selenium_chrome
  end

  it 'captures the rendered page' do
    visit '/account'
    save_screenshot('account-rendered.png')
  end
end

If your suite changes drivers globally, prefer the project’s existing driver configuration rather than changing it inside one example. The essential check is that the current session is backed by Selenium.

Automatic screenshots for failed Capybara examples

The capybara-screenshot gem adds automatic failure artifacts. Add it to your test dependencies and load the RSpec adapters in this order:

require 'capybara/rspec'
require 'capybara-screenshot/rspec'

Its documented behavior for supported browser drivers is to save a screenshot and the failed page HTML. Rails-like applications default to tmp/capybara; non-Rails projects use the working directory unless you configure another save path. Review generated HTML before sharing it because it can contain page content or test data.

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

The gem also provides a manual screenshot_and_save_page helper. Its README documents settings for disabling automatic capture, changing filename prefixes, controlling timestamp suffixes, pruning older artifacts, and changing RSpec output links. Configuration names and defaults can vary with the installed gem version, so consult that version’s README instead of copying an option blindly.

Viewport, full-page, and element expectations

A normal Selenium Ruby screenshot is a viewport image: it shows the area visible to the browser at capture time. Selenium’s optional full_page parameter works only when the active driver supports full-page capture. An unsupported driver can raise an unsupported-operation error, so do not assume that a Chrome, Firefox, or remote driver will all behave identically.

If you need content below the fold, first verify full-page support for the exact driver and browser combination used in CI. Otherwise, capture after scrolling or use a tool that explicitly supports full-page rendering. A screenshot failure should not hide the original assertion failure; keep the original exception visible in RSpec output.

Preserving screenshots in CI and parallel runs

  1. Choose one directory, such as tmp/screenshots or Capybara’s configured save path.
  2. Create it in the test process with FileUtils.mkdir_p or equivalent setup.
  3. Use names that include the example and, when needed, the worker number.
  4. Configure your CI system to upload that directory as a build artifact. The exact upload and retention commands depend on the CI provider.
  5. Restrict artifact access when screenshots or saved HTML can contain credentials, personal data, tokens, or other test fixtures.

Do not rely on a local working directory that differs between developers and CI. A deterministic path makes failed examples easier to inspect and prevents cleanup jobs from deleting evidence before it is uploaded.

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

Troubleshooting common failures

“No such file or directory” when saving

Cause: the destination directory does not exist or the process cannot write there. Fix: create it with FileUtils.mkdir_p, use a writable path, and check the process working directory. This is a filesystem problem, not a Selenium screenshot limitation.

The screenshot is blank or not the page you expected

Cause: capture happened before navigation or before the application finished rendering. Fix: navigate first and synchronize with the page state your test actually needs. In Capybara, make sure the example uses a Selenium driver rather than :rack_test.

The failure hook raises after the original test error

Cause: the driver was never created, or it was quit before the hook ran. Fix: guard the object, capture in an after hook before quit, and avoid replacing the original exception with an artifact error.

Automatic Capybara screenshots never appear

Cause: the adapter is missing, loaded in the wrong order, or the current driver is unsupported. Fix: require capybara/rspec first and capybara-screenshot/rspec second, then verify the active driver and the configured save path.

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

Parallel examples overwrite each other

Cause: multiple workers use the same filename. Fix: include a unique example or worker component in each path, or give each worker its own directory.

Full-page capture raises an unsupported-operation error

Cause: the selected driver does not implement Selenium’s full-page option. Fix: use a supported driver, capture the viewport, or implement a scrolling strategy appropriate to your test. Full-page support is driver-dependent.

HTML artifacts expose test data

Cause: automatic failure capture saves the failed page HTML as well as the image. Fix: inspect and protect artifacts, reduce retention, or disable automatic HTML capture using the options documented for your installed capybara-screenshot version.

Performance, reliability, and cost considerations

A screenshot adds filesystem I/O and image encoding to an example. Capturing only on failure avoids slowing every passing test. If you need visual evidence for a known checkpoint, capture once at that checkpoint rather than repeatedly inside polling loops.

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

Browser startup and navigation usually dominate the elapsed time, so reusing a session where your test isolation allows it can matter more than optimizing the save call. Keep screenshot dimensions and frequency reasonable, especially on remote drivers and in large parallel suites.

Local Selenium screenshots have no separate service fee, but they consume browser, CPU, memory, storage, and CI artifact-retention resources. Automatic HTML files can be larger and more sensitive than PNGs. Decide how long failed artifacts should remain available and who can read them.

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

Or skip the browser setup

If your goal is a clean image of a public URL rather than evidence from the exact browser session under test, ScreenshotNeo provides a website screenshot API and MCP server. One GET request returns PNG, JPEG, WebP, or PDF. It accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers.

Here is the one-call cURL form (see the ScreenshotNeo API documentation for parameters):

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

The equivalent Python request is:

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

In Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

ScreenshotNeo also supports full-page capture with lazy images loaded, CSS-selector element capture, dark mode, 12 device presets plus custom viewports, retina scale, PDF paper size and page ranges, HTML/CSS-to-image, custom JavaScript, clicks, hidden selectors, waits for selectors or network idle, ad and tracker blocking, custom headers, cookies, user agents and Authorization, timezone and geolocation, transparent backgrounds, resizing, configurable cache TTLs, signed image links, asynchronous jobs with signed webhooks, bulk capture for 100 URLs per call, a usage API, and an OpenAPI specification. Parameter names used by other screenshot APIs also work to ease migration. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf to 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; yearly billing provides two months free, and every feature is available on every plan. This is a URL capture service, so it complements rather than replaces a Selenium screenshot when you must record the exact authenticated browser state, console state, or DOM produced by a test run.

Create a free ScreenshotNeo account to try 1,000 screenshots a month with no card.

FAQ

Should screenshots be committed to the Git repository?

Usually no. Treat them as generated test artifacts; retain them in CI or a dedicated evidence store unless a screenshot is intentionally serving as a reviewed fixture.

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

Can I use these images as a visual-regression baseline?

The capture methods produce images, but baseline comparison, pixel tolerances, and diff reporting are separate concerns. Choose a visual-testing tool and define browser, viewport, font, and rendering controls before treating differences as failures.

What should I do when a screenshot contains secrets?

Redact the test data before capture where possible, restrict artifact permissions, and set retention appropriate to the sensitivity of the page. Automatic page-HTML capture deserves the same protection as the image.

Frequently Asked Questions

Should screenshots be committed to the Git repository?

Usually no. Treat them as generated test artifacts; retain them in CI or a dedicated evidence store unless a screenshot is intentionally serving as a reviewed fixture.

Can I use these images as a visual-regression baseline?

The capture methods produce images, but baseline comparison, pixel tolerances, and diff reporting are separate concerns. Define browser, viewport, font, and rendering controls before treating differences as failures.

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

What should I do when a screenshot contains secrets?

Redact test data where possible, restrict artifact permissions, and set retention appropriate to the sensitivity of the page. Protect automatic page-HTML artifacts as carefully as the image.

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.