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.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Use CasperJS captureSelector() when the desired screenshot is a known CSS element, or use PhantomJS page.clipRect when you need a fixed coordinate crop. If you need the selected markup rather than an image, use CasperJS getHTML(selector, outer); PhantomJS page.content returns the whole main-frame document, not one selector.

The examples below cover selector screenshots, rectangle crops, rendered HTML extraction, asynchronous pages, output formats, and the compatibility limits of this legacy toolchain.

Choose the operation before writing code

“Partial page content” can mean an image crop or a fragment of HTML. These are different operations and use different APIs.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Goal Best API Targeting method Result
Screenshot one DOM element CasperJS captureSelector() CSS selector Raster image of the selector’s area
Screenshot a fixed region PhantomJS clipRect or CasperJS capture() top, left, width, height Raster image of that rectangle
Extract one element’s markup CasperJS getHTML() CSS selector Inner HTML by default, or outer HTML
Read the complete response body CasperJS getPageContent() Current response String, including non-HTML responses such as JSON

Set the viewport before measuring or capturing. Responsive layout, font wrapping, and lazy content can otherwise move the target between runs.

Capture one element with CasperJS

When the element itself defines the region, selector capture is less brittle than hand-written coordinates. The documented signature is captureSelector(String targetFile, String selector [, Object imgOptions]).

Minimal selector screenshot

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

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

casper.run();

captureSelector() finds the element in the rendered page and writes only its area to article.png. Replace #article with a stable selector such as .invoice or [data-testid="report"]. Prefer an ID or a dedicated data attribute over a deeply nested selector that can change when the page is redesigned.

Wait for client-rendered content

A successful navigation does not guarantee that a framework has inserted the target node or finished painting it. Keep the capture inside waitForSelector(), and add a visibility or delay check when the element appears before its final state. CasperJS supplies waiting and visibility helpers for this purpose.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
var casper = require('casper').create();

casper.start('https://example.com/dashboard');
casper.waitForSelector('#chart', function () {
  this.captureSelector('chart.png', '#chart');
}, function () {
  this.die('The chart did not appear before the wait expired.');
});
casper.run();

For content that is present but still changing, place a short wait() or a second condition after the selector appears. Do not assume that the network load event represents application readiness.

Pass image options

The optional image-options object is forwarded by CasperJS to the underlying render operation. Use it for the output format and quality supported by your PhantomJS build. JPEG quality is documented on a scale from 1 to 100.

this.captureSelector('article.jpg', '#article', {
  format: 'jpg',
  quality: 85
});

Use PNG when text edges and transparency matter; use JPEG when a smaller photographic file is more important. Confirm the exact format spelling accepted by the runtime you deploy.

Crop a rectangle with PhantomJS

PhantomJS exposes two separate geometry settings: viewportSize controls the browser viewport, while clipRect specifies the rectangle included in the rendered image. Set the viewport first, open the page, assign the clip rectangle, and call render().

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
var page = require('webpage').create();

page.viewportSize = { width: 1280, height: 900 };
page.open('https://example.com', function (status) {
  if (status !== 'success') {
    phantom.exit(1);
    return;
  }

  page.clipRect = {
    top: 120,
    left: 80,
    width: 640,
    height: 420
  };
  page.render('partial.png');
  phantom.exit();
});

The coordinates are in the rendered page’s coordinate system. A fixed rectangle is useful for a chart viewport, a known dashboard panel, or a crop that must remain exactly 640 by 420 pixels. It is less suitable for a responsive card whose position changes with the viewport.

Use CasperJS as a rectangle wrapper

CasperJS capture() is a proxy for PhantomJS WebPage#render and temporarily applies a rectangle:

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

casper.start('https://example.com', function () {
  this.capture('partial.png', {
    top: 100,
    left: 100,
    width: 500,
    height: 400
  });
});

casper.run();

Use this form when you already have coordinates and want CasperJS’s navigation and waiting flow. The same optional image format and quality settings can be supplied with the capture call.

Measure a moving element

For a responsive target, measure its bounding rectangle in the page context rather than guessing coordinates. CasperJS requires evaluate() or thenEvaluate() for code that runs inside the page.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
var casper = require('casper').create();

casper.start('https://example.com', function () {
  this.waitForSelector('#article', function () {
    var box = this.evaluate(function () {
      var el = document.querySelector('#article');
      if (!el) { return null; }
      var r = el.getBoundingClientRect();
      return {
        top: r.top,
        left: r.left,
        width: r.width,
        height: r.height
      };
    });

    if (!box) {
      this.die('The element could not be measured.');
    }
    this.capture('article.png', box);
  });
});

casper.run();

If your page has been scrolled, account for the runtime’s coordinate origin and verify whether the rectangle is viewport-relative or page-relative before deploying. A quick diagnostic capture with visible borders can reveal an offset immediately.

Extract selected HTML instead of an image

CasperJS’s getHTML() returns the matching element’s inner HTML by default. Pass true as the second argument to include the element’s own start and end tags.

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

casper.start('https://example.com', function () {
  this.waitForSelector('#article', function () {
    this.echo(this.getHTML('#article'));       // inner HTML
    this.echo(this.getHTML('#article', true)); // outer HTML
  });
});

casper.run();

Use this when you need the rendered DOM fragment for storage or further parsing. It is not the same as the original server response: scripts may have inserted nodes, and client-side changes may be reflected in the returned markup.

Read a non-HTML response

If the current page is an API response or another non-HTML document, use getPageContent() and parse the returned string. Selector extraction is meaningful only when a DOM element exists.

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.
var casper = require('casper').create();

casper.start('https://example.com/data.json', function () {
  var body = this.getPageContent();
  this.echo(body);
});

casper.run();

Make asynchronous pages deterministic

  • Choose a fixed viewport. Set page.viewportSize or the corresponding CasperJS viewport setting before navigation so responsive breakpoints remain stable.
  • Wait for the actual target. A selector wait is stronger than a fixed sleep because it follows the condition you need.
  • Wait for visibility or final content. A node can exist while hidden, empty, or still being populated by a client-side framework.
  • Measure in the page context. Use evaluate()/thenEvaluate() for bounding boxes, text, computed state, and DOM transformations.
  • Control lazy assets. Scroll or trigger the page’s loading behavior before capture when the target contains images that are loaded only after entering the viewport.

For a repeatable pipeline, log the URL, viewport, selector or rectangle, wait condition, output format, and exit status for every run. That information makes a shifted crop distinguishable from a failed navigation.

Output formats and rendering limits

PhantomJS render() documents PDF, PNG, JPEG, BMP, PPM, and GIF output; GIF availability depends on the Qt build. PNG and JPEG quality options are available, and CasperJS passes format and quality settings through its capture methods.

Format Use when Caveat
PNG Text, UI screenshots, sharp edges, or transparency Usually larger than JPEG for photographic content
JPEG Photos or smaller lossy files Quality is adjustable; compression can soften text
PDF Print-oriented output or document delivery Page layout and paper settings must be validated for the target
BMP/PPM Toolchains that explicitly require an uncompressed or portable bitmap Often produces large files
GIF Only when your Qt build provides GIF support Support is build-dependent

Troubleshoot common failures

The file is blank or shows the wrong area

Check that the page opened successfully, the viewport was set before navigation, and the rectangle uses the intended coordinate origin. For a selector capture, confirm that the selector identifies the visible element rather than a hidden template copy.

The selector never appears

The page may need a longer application wait, may render the content only after an interaction, or may have failed to load its scripts. Add logging around navigation and the wait callback, verify the selector in the page context, and fail with a non-zero exit status instead of writing a misleading image.

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

The crop is shifted after a redesign

Replace fixed coordinates with captureSelector(), or measure the element with getBoundingClientRect() immediately before capture. Keep the viewport constant so responsive breakpoints do not move the target.

HTML extraction returns nothing useful

Use getHTML(selector, true) when you need the wrapper element, and use getPageContent() for JSON or other non-HTML responses. DOM inspection and transformations must run through evaluate() or thenEvaluate().

The script works locally but fails in production

Compare PhantomJS and CasperJS versions, Qt capabilities, viewport settings, fonts, network access, and wait conditions. These legacy tools can render differently across builds, so pin the exact runtime and keep a known-good diagnostic URL.

Maintenance and compatibility warning

CasperJS’s repository states that it is no longer actively maintained and recommends it mainly when old PhantomJS 1.9 production tests must continue running. Releases through 1.1-beta3 do not support PhantomJS 2.0 and newer. Treat this workflow as legacy maintenance guidance: verify the exact PhantomJS/CasperJS pair before adopting it for a new service, and plan a migration if you need a maintained browser engine or modern web-platform behavior.

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

Performance, reliability, and operating cost

  • Performance: Capturing a selector avoids producing an entire-page bitmap, but navigation, JavaScript execution, fonts, and images still dominate runtime. Reuse a predictable viewport and avoid unnecessary waits.
  • Reliability: Selector-based targeting usually survives layout shifts better than hard-coded coordinates. Coordinate crops remain appropriate when the rectangle itself is the specification.
  • Failure handling: Check navigation status, selector readiness, and output-file existence. Return a failing process status when any prerequisite is missing.
  • Resource use: Large viewports, high-resolution assets, and PDF rendering consume more memory and disk. Clean up temporary files and cap concurrent jobs according to the limits of your PhantomJS build.
  • Cost: PhantomJS and CasperJS are self-managed software; no universal hosting or runtime price is published. Your actual cost comes from the machine, maintenance, and time required to keep this legacy stack working.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

For a hosted screenshot API, ScreenshotNeo is the first option to try when you want a clean element or page capture without maintaining PhantomJS: it removes cookie banners, newsletter popups, and chat widgets before capture, and bills only clean shots.

It supports full-page captures with lazy images loaded, a single element by CSS selector, custom viewports and 12 device presets, dark mode, retina scale, custom CSS and JavaScript, click-before-capture, selector hiding, waits for a selector, delay or network idle, request and resource blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, configurable-TTL caching, signed image links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, a usage API, and an OpenAPI specification. Its parameter names are compatible with those used by other screenshot APIs, which helps when switching.

Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed; each response reports the result in X-Page-Verdict and X-Billed headers. ScreenshotNeo also provides an MCP server with take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.

Use the ScreenshotNeo API documentation for the full option list. A selector capture can be as simple as this cURL request:

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://example.com 
  --data-urlencode selector=#article 
  -o article.webp

The same endpoint can be called from Python:

import requests

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

And from Node.js:

const q = new URLSearchParams({
  access_key: 'YOUR_API_KEY',
  url: 'https://example.com',
  selector: '#article'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('article.webp', Buffer.from(await res.arrayBuffer()));

The Free plan includes 1,000 screenshots a month with no card. Paid plans start at $5 for 3,000 shots; yearly billing gives two months free, and every feature is available on every plan. Sign up for the free ScreenshotNeo plan to try the selector capture without installing a browser.

Frequently Asked Questions

Should a rectangle include browser chrome or scrollbars?

No. PhantomJS clip rectangles apply to the rendered page, not the operating system’s browser window. Set the viewport explicitly and validate the crop inside the page content.

Is CasperJS suitable for a new long-lived capture service?

It is primarily a legacy-maintenance choice because the project is no longer actively maintained. Verify the exact runtime pair and migration requirements before committing to it.

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.