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

Use Poltergeist for the Capybara integration, then configure the underlying PhantomJS page for rendering. In Poltergeist, save_screenshot(path) captures the current viewport; add full: true for the whole page or selector: '#id' for one element. For PDFs, set driver.paper_size. Keep viewport settings (which control responsive layout) separate from paper size (which controls PDF pages).

These examples follow the archived Poltergeist documentation and PhantomJS APIs. Check the versions installed in your test suite before adopting them in a new project.

What Poltergeist and PhantomJS each control

Poltergeist is a Capybara driver that runs tests in a headless PhantomJS browser. Poltergeist exposes test-oriented operations such as save_screenshot, while PhantomJS supplies webpage properties such as viewportSize, paperSize and renderBase64.

  • Capture area: Poltergeist chooses the viewport, full document or a CSS-selected element.
  • Layout size: PhantomJS viewportSize determines the width and height used for page layout.
  • PDF page: PhantomJS paperSize determines page dimensions, margins and orientation.
  • Image encoding: Poltergeist’s render_base64 returns an encoded image buffer; PNG is the default and PNG, GIF and JPEG are documented formats.

Changing PDF orientation does not make a responsive page render as though it had a wider browser window. Set the viewport and paper settings independently.

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

Install and configure the legacy driver

The README documents this basic setup:

require 'capybara/poltergeist'

Capybara.javascript_driver = :poltergeist

Poltergeist lists PhantomJS 1.8.1 or later among its requirements and its repository is archived; the README points to the 1.18.1 release documentation. Confirm that the gem, PhantomJS binary and Capybara versions in your environment are compatible before troubleshooting the examples below.

Window and screen defaults

Poltergeist documents a window_size option as a two-item array, with [1024, 768] as the default. It also documents screen_size for the dimensions used when Window#maximize is called. Neither option is the same concept as PhantomJS’s webpage viewportSize.

Capybara.register_driver :poltergeist do |app|
  Capybara::Poltergeist::Driver.new(
    app,
    window_size: [1280, 900],
    screen_size: [1920, 1080]
  )
end

Capybara.javascript_driver = :poltergeist

Use a registered driver only when you need non-default driver settings. Keep the dimensions explicit in visual tests so a change in a developer’s machine does not alter the result.

Take a viewport screenshot

After visiting a page in a Capybara example, call save_screenshot with a path. With no options, Poltergeist captures what is visible in the current viewport.

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.
feature 'checkout', js: true do
  scenario 'captures the visible state' do
    visit '/checkout'
    save_screenshot('tmp/checkout-viewport.png')
  end
end

The path can be absolute or relative to the process working directory. Create the destination directory first when your test runner does not do so:

FileUtils.mkdir_p('tmp')
save_screenshot('tmp/checkout-viewport.png')

A viewport capture is appropriate for checking a modal, navigation bar or above-the-fold layout. It deliberately excludes content below the current viewport.

Capture the entire page

Pass full: true to request a full-page screenshot:

visit '/article/long-read'
save_screenshot(
  'tmp/long-read-full.png',
  full: true
)

Full-page mode is useful for regression images of documents and landing pages. It does not change the responsive breakpoint used to lay out the page; that still comes from the viewport/window dimensions. If lazy content appears only after scrolling, make the page load it before capturing, or the resulting image may contain unloaded regions.

Rank #2
Sale

Capture one element with a CSS selector

Use selector to bound the image to an element matched by CSS:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
visit '/dashboard'
save_screenshot(
  'tmp/summary-card.png',
  selector: '#summary-card'
)

The selector should identify the intended element in the loaded DOM. A missing or ambiguous selector can produce an error or an unexpected target, so assert the element first:

expect(page).to have_css('#summary-card')
save_screenshot('tmp/summary-card.png', selector: '#summary-card')

Element capture is different from hiding everything else with CSS: the screenshot bounds are derived from the selected element, while the page itself still renders normally.

Choose an image format or return Base64

Save PNG, GIF or JPEG

The documented screenshot examples write an image file. For lower-level access, Poltergeist exposes page.driver.render_base64(format, options). PNG is the default; PNG, GIF and JPEG are documented.

visit '/status'
encoded = page.driver.render_base64('png', full: true)
File.binwrite('tmp/status.png', Base64.decode64(encoded))

Require Ruby’s Base64 library before decoding:

require 'base64'

Use the same capture options you would pass to a screenshot where supported, such as full: true or a selector. Verify the option behavior against the installed Poltergeist release because the project is no longer actively maintained.

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

PhantomJS’s native renderBase64 API

At the PhantomJS page level, the documented method is page.renderBase64(format):

var page = require('webpage').create();
page.open('https://example.com', function (status) {
  if (status !== 'success') {
    console.log('open failed: ' + status);
    phantom.exit(1);
  }
  console.log(page.renderBase64('png'));
  phantom.exit();
});

The PhantomJS API documents PNG, GIF and JPEG output. Poltergeist’s Ruby driver is usually the easier choice inside Capybara tests; the native script is useful when you need direct PhantomJS page control.

Set viewport dimensions before loading

PhantomJS describes viewportSize as the headless equivalent of a traditional browser window. Set both width and height, and set them before loading the URL so responsive CSS is evaluated at the intended size.

var page = require('webpage').create();
page.viewportSize = { width: 1440, height: 900 };
page.open('https://example.com', function (status) {
  if (status === 'success') {
    page.render('/tmp/example-1440.png');
  }
  phantom.exit(status === 'success' ? 0 : 1);
});

PhantomJS specifically warns that height must be included. A width-only assignment can leave the page at an unintended layout size.

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

Viewport choices in a Poltergeist test

When using Poltergeist, set the driver-level window size for the test session, then capture the desired area:

Capybara.register_driver :wide_poltergeist do |app|
  Capybara::Poltergeist::Driver.new(app, window_size: [1440, 900])
end

Capybara.javascript_driver = :wide_poltergeist

Use a separate driver configuration for mobile-like widths. Do not use PDF orientation as a substitute for a viewport change.

Configure PDF output with paper size

Poltergeist advises assigning driver.paper_size= for PDF rendering. The value follows PhantomJS’s paperSize settings.

driver = page.driver
driver.paper_size = {
  format: 'A4',
  orientation: 'portrait',
  margin: '1cm'
}
page.save_page('tmp/report.pdf')

Use the exact PDF-saving method supported by your installed Poltergeist version; the important setting is the assignment to paper_size before rendering. PhantomJS documents named formats including A3, A4, A5, Legal, Letter and Tabloid. Portrait is the documented default, and landscape is also supported.

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

Named formats and custom dimensions

A standard format is predictable for printing:

driver.paper_size = {
  format: 'Letter',
  orientation: 'landscape',
  margin: {
    top: '12mm',
    left: '12mm',
    bottom: '12mm',
    right: '12mm'
  }
}

For a custom page, provide width and height. PhantomJS accepts mm, cm, in and px; unitless dimensions are treated as pixels.

driver.paper_size = {
  width: '5in',
  height: '7in',
  margin: {
    top: '0.25in',
    left: '0.25in',
    bottom: '0.25in',
    right: '0.25in'
  }
}

A single margin measurement is also documented. An object with individual top, left, bottom and right margins gives you independent control. The documented default margin is zero.

Headers and footers

PhantomJS permits a repeating header or footer with a height and callback-based contents. Use this only when your Poltergeist release exposes the corresponding paper-size fields; older driver versions may not pass every PhantomJS option through unchanged.

Viewport size versus PDF paper size

Decision Setting What it changes Typical use
Browser layout viewportSize or Poltergeist window settings CSS breakpoints, available layout width and visible window height Responsive screenshots and visual tests
Capture area save_screenshot options Viewport, full document or selected element Focused image or complete page image
PDF page geometry paperSize/paper_size Paper format, custom dimensions, margins and orientation Printable PDF reports

For a landscape report, set landscape in paperSize. If the page must also switch to a desktop breakpoint, set a wider viewport separately before navigation.

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.

A complete Capybara example

This example fixes the driver window, waits for the page state through normal Capybara assertions, captures both an element and the full page, and configures PDF paper settings:

require 'capybara/rspec'
require 'capybara/poltergeist'
require 'fileutils'

Capybara.register_driver :poltergeist_visual do |app|
  Capybara::Poltergeist::Driver.new(app, window_size: [1280, 900])
end
Capybara.javascript_driver = :poltergeist_visual

RSpec.describe 'invoice rendering', type: :feature do
  it 'captures image and PDF states', js: true do
    FileUtils.mkdir_p('tmp/renders')
    visit '/invoices/42'
    expect(page).to have_css('#invoice')

    save_screenshot('tmp/renders/invoice-element.png', selector: '#invoice')
    save_screenshot('tmp/renders/invoice-full.png', full: true)

    page.driver.paper_size = {
      format: 'A4',
      orientation: 'portrait',
      margin: '1cm'
    }
    page.save_page('tmp/renders/invoice.pdf')
  end
end

If your release uses a different PDF helper, keep the navigation, assertions and paper_size assignment, then use that release’s documented PDF method.

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

Troubleshoot unexpected renders

The image is cropped at the fold

That is the default viewport behavior. Add full: true for the document or use selector for a bounded component.

The page uses the wrong responsive breakpoint

Set both viewport dimensions before navigation. In native PhantomJS, assign page.viewportSize = { width: ..., height: ... } before page.open. In Poltergeist, verify the driver’s window_size and remember that screen_size affects maximize behavior instead.

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

The PDF has the wrong margins or orientation

Inspect driver.paper_size. Use a named format for standard paper, or explicit width/height for custom pages. Set margins in the paper-size object; changing viewport dimensions will not change PDF paper geometry.

A selector capture fails or is empty

Assert that the selector exists after the page has reached its ready state. Check for duplicate IDs, frames and content that is inserted asynchronously. Capture the full page temporarily to determine whether the element is outside the expected document.

Images or charts are missing

Capture only after the page has loaded the required assets. If the application lazy-loads content on scroll, trigger the relevant interaction before taking a full-page image. PhantomJS is an old browser engine, so modern JavaScript or CSS can also render differently; isolate that possibility by comparing a simple static page.

The API works locally but not in CI

Print the installed Poltergeist and PhantomJS versions, use an absolute output path, and make the viewport dimensions explicit. Confirm that the CI image contains the PhantomJS executable and that the test process can write to the destination directory.

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

Performance and reliability considerations

  • Use element or viewport captures when a full document is unnecessary; they produce smaller artifacts and reduce visual-diff noise.
  • Keep one fixed driver size per visual test suite. Mixing implicit defaults makes failures difficult to reproduce.
  • Separate image tests from PDF tests so a paper-size change cannot silently alter screenshot expectations.
  • Store the exact options beside the test. A future maintainer needs to know whether a failure concerns viewport dimensions, capture area or paper geometry.
  • Because Poltergeist and PhantomJS are legacy projects, validate output after dependency or operating-system changes rather than assuming browser behavior is current.

Or skip the browser setup

If you need a current website screenshot rather than a legacy Capybara test, ScreenshotNeo provides a single HTTP request and an MCP server for AI clients. It removes cookie and consent banners, newsletter popups and chat widgets before capture. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and each response identifies the result with X-Page-Verdict and X-Billed headers.

cURL:

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

Python:

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)

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}`);

See the ScreenshotNeo API documentation for the 63 capture options, including full-page and CSS-selector captures, device and viewport settings, retina scale, PDF paper controls, custom CSS and JavaScript, waits, request blocking, cookies and headers, geolocation, caching, signed links, asynchronous jobs and bulk capture. Its MCP tools—take_screenshot, get_page_info and capture_pdf—work with Claude, Cursor and other MCP clients.

The Free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is available on every plan, and yearly billing gives two months free. Create a free ScreenshotNeo account.

Frequently Asked Questions

Is Poltergeist still maintained?

Its repository is archived and points readers to the 1.18.1 release documentation, so verify all examples against the versions already installed in your suite.

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

Can I use paperSize to force a desktop responsive layout?

No. paperSize controls PDF page geometry. Set the browser viewport or Poltergeist window size separately to select a responsive breakpoint.

Which formats does renderBase64 support?

The PhantomJS documentation lists PNG, GIF and JPEG; PNG is the default documented format.

Why does a full-page capture still miss lazy content?

Full mode captures the rendered document, but content that your application loads only after scrolling or another interaction must be triggered before capture.

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.

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