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

Choose the file you actually need before writing code. Use capture() or PhantomJS page.render() for a visual image or PDF, captureSelector() for one element, getHTML() for the JavaScript-rendered DOM, and download() only for fetching a remote resource. CasperJS and PhantomJS can perform these tasks, but both are legacy projects: the PhantomJS homepage says development is “suspended until further notice,” and the CasperJS project says it is “no longer actively maintained.” Treat the examples below as maintenance guidance for an existing legacy environment, not as a current compatibility guarantee.

Decide what “save a webpage” means

The output determines the API call:

Goal Use Result
Visual snapshot CasperJS capture() or PhantomJS page.render() PNG, JPEG, GIF, or PDF
One visual region CasperJS captureSelector() The rendered area matching a CSS selector
Rendered markup CasperJS getHTML() A string containing the current DOM HTML
Static file or remote resource CasperJS download() The fetched resource written to a local target

getHTML() is the relevant choice when scripts change the page after navigation. download() retrieves a remote resource; it does not serialize the JavaScript-rendered DOM. The CasperJS API documentation describes these distinctions.

Save a full page image with CasperJS

Minimal capture

CasperJS starts a browser session, opens the URL, runs steps in order, and exits from run(). Capture after navigation has completed:

var casper = require('casper').create();

casper.start('https://example.com/', function() {
    this.capture('page.png');
});

casper.run();

This is the documented usage pattern. It saves the viewport rendering to page.png. The callback is the place to add checks, waits, clicks, or other state changes before the screenshot.

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

Control the capture rectangle and image options

capture(filepath, clipRect, imgOptions) wraps PhantomJS rendering and can apply a temporary clipping rectangle. The rectangle defines the part of the rendered page to write. Image options can specify a format and quality; CasperJS documents quality as a 1–100 setting, not as a measured quality score.

var casper = require('casper').create();

casper.start('https://example.com/', function() {
    this.capture(
        'header.jpg',
        { top: 0, left: 0, width: 1280, height: 240 },
        { format: 'jpg', quality: 85 }
    );
});

casper.run();

A viewport setting controls what the page lays out inside the browser. A clip rectangle controls what is exported. Setting a viewport does not automatically capture an arbitrarily long page; choose dimensions and clipping deliberately.

Capture one element

Use captureSelector() when the target is a DOM element rather than the whole viewport:

var casper = require('casper').create();

casper.start('https://example.com/', function() {
    this.captureSelector('article.png', 'main article');
});

casper.run();

The selector must match the element that exists after the page has loaded. If it matches nothing, the capture cannot represent the intended region, so verify the selector in the page’s markup and add a wait when the element is inserted by JavaScript.

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

Save a page directly with PhantomJS

Documented render flow

PhantomJS exposes the lower-level page.render() call. Open the page, test the status, render only after a successful open, then exit:

var page = require('webpage').create();

page.open('https://example.com/', function(status) {
  if (status === 'success') {
    page.render('page.png');
  }
  phantom.exit();
});

The official PhantomJS screen-capture guide demonstrates PNG, JPEG, GIF, and PDF output. Change the filename extension to select the format supported by that rendering path:

page.render('page.pdf');
page.render('page.jpg');
page.render('page.gif');

Keep the success check. Rendering after a failed navigation can produce an empty or misleading artifact.

Set viewport and clipping

Set the browser viewport before opening the page when you need a specific layout:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
var page = require('webpage').create();
page.viewportSize = { width: 1440, height: 900 };
page.clipRect = { top: 0, left: 0, width: 1440, height: 900 };

page.open('https://example.com/', function(status) {
  if (status === 'success') {
    page.render('viewport.png');
  }
  phantom.exit();
});

viewportSize affects responsive layout. clipRect defines the rendered rectangle exported to the file. Neither setting is a guarantee of full-document capture for a page longer than the viewport; a long-page workflow must account for the page’s actual dimensions and the limitations of this legacy renderer.

Save JavaScript-rendered HTML with CasperJS

Retrieve the current DOM

Call getHTML() after the relevant scripts have run:

var casper = require('casper').create();

casper.start('https://example.com/', function() {
    var html = this.getHTML();
    require('fs').write('rendered.html', html, 'w');
});

casper.run();

getHTML() returns a string. Retrieving it and writing it to disk are separate actions. To limit the result to an element, pass a selector. The outer option controls whether the selected node itself is included:

var fragment = this.getHTML('main', true);
require('fs').write('main.html', fragment, 'w');

Use this for the DOM state visible to CasperJS after client-side changes. It is not the same artifact as a screenshot, and it does not automatically package external CSS, images, fonts, or scripts.

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.

Use download() only for a resource

When the goal is a PDF, image, stylesheet, or other URL-addressable file, use CasperJS’s download facility instead of DOM retrieval:

var casper = require('casper').create();

casper.start('https://example.com/');
casper.then(function() {
    this.download('https://example.com/file.pdf', 'file.pdf');
});
casper.run();

A downloaded file is the server response at that URL. It does not include changes made to the page by JavaScript. For rendered markup, use getHTML(); for a visual rendering, use capture() or page.render().

Wait for the state you intend to save

Navigation completion and application readiness are not always the same event. In a CasperJS step, wait for a selector or perform an interaction before capturing:

var casper = require('casper').create();

casper.start('https://example.com/app');
casper.waitForSelector('#report', function() {
    this.captureSelector('report.png', '#report');
});
casper.run();

If content appears only after a click, execute the click in an earlier step. If a page uses a fixed header, cookie dialog, or animation, capture after the final visual state is present. These tools do not provide a modern compatibility guarantee for current sites, frameworks, anti-bot checks, or operating systems, so validate the result in the environment you maintain.

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

Troubleshooting

The output is blank or missing content

  • Confirm the navigation callback reports success before rendering.
  • Wait for a selector that proves the dynamic content exists.
  • Check that the viewport and clip rectangle overlap the content.
  • Inspect whether the page requires browser capabilities unavailable in this legacy stack.

The selector capture is empty

  • Verify the CSS selector against the post-load DOM, not only the initial source.
  • Wait for the element before calling captureSelector().
  • Check that the element is visible and has non-zero dimensions.

HTML does not contain the data seen on screen

Call getHTML() after the application has finished updating the DOM. Do not use download() for this purpose: it fetches a resource and does not return the rendered DOM.

The file format or quality is wrong

Use a matching extension and, for CasperJS, pass explicit image options. Remember that the documented quality range is a configuration value from 1 to 100, not a promise about visual fidelity across pages.

Modern pages fail to load

PhantomJS development is suspended, and CasperJS is no longer actively maintained. The official sources do not provide a current compatibility matrix or present-day reliability results. If you must preserve an existing script, pin and document its runtime, record failures, and treat unsupported browser behavior as a likely cause rather than assuming your selector or file path is wrong.

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

Or skip the browser setup

ScreenshotNeo provides a one-request screenshot API when maintaining CasperJS or PhantomJS is unnecessary. It removes cookie and consent banners, newsletter popups, and chat widgets before capture; bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, with the response identifying the page verdict and billing status in X-Page-Verdict and X-Billed headers. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.

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

See the ScreenshotNeo documentation for all options, including full-page lazy-image loading, CSS-selector captures, device presets, custom viewports, retina scale, PDF settings, custom CSS and JavaScript, waits, request blocking, headers, cookies, user agents, timezone and geolocation, transparent backgrounds, resizing, caching, signed links, asynchronous webhooks, bulk capture, usage reporting, and OpenAPI compatibility.

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

The Free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 screenshots; every feature is available on every plan. Create a free ScreenshotNeo account to make the first request.

Choosing the right method

  • Choose CasperJS capture() when an existing CasperJS workflow needs a screenshot or clip.
  • Choose PhantomJS page.render() when you need direct control over the page object, viewport, and clip rectangle.
  • Choose CasperJS captureSelector() for one visual element.
  • Choose CasperJS getHTML() for the post-script DOM.
  • Choose download() for a remote resource, not rendered markup.
  • Choose an external screenshot service when you do not want to maintain this suspended and unmaintained browser stack.

Frequently Asked Questions

Does page.render() capture an entire long webpage automatically?

No. It renders the configured page and capture rectangle. Set the viewport and clipping deliberately; a viewport alone does not guarantee an arbitrarily long full-page image.

Can getHTML() save the CSS and images with the DOM?

No. It returns an HTML string. External stylesheets, images, fonts, and scripts remain separate resources unless you package them yourself.

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

Why is download() not suitable for a single-page application’s rendered HTML?

It fetches a remote resource response. JavaScript-rendered DOM should be obtained with getHTML() after the page reaches the required state.

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.