Free tools Windows power users keep installed
One-click scans. No signup required.
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.
| 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.
#1 Best Overall
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.
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.
Rank #2
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().
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.
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.
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.viewportSizeor 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 |
| 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.
Rank #4
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.
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallThe 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.
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.
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.
Best Value
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:
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Clear out junk files and repair common Windows errors3Fix the driver behind crashes, sound loss and screen glitchescurl -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.
Quick Recap
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.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →

