Recommended Free Tools
Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
PhantomJS does not provide a selector argument to page.render(). To capture one element, locate it in the page, read its rendered rectangle, assign that rectangle’s top, left, width, and height to page.clipRect, then call page.render() after the element is visually ready.
The script below handles loading, waiting for a non-zero element, scrolling it into view, compensating for document scroll, and writing an image file.
How PhantomJS clips one element
The PhantomJS screen-capture API works with a rectangular page region. Its documented workflow is to set page.clipRect and then render the page. The rectangle has four fields:
top: the vertical page coordinate.left: the horizontal page coordinate.width: the rectangle width.height: the rectangle height.
There is no documented page.render(selector) call in the PhantomJS page-capture API. Your code must therefore convert the selected DOM element into geometry. A browser-side getBoundingClientRect() call gives coordinates relative to the viewport; adding window.pageXOffset and window.pageYOffset converts them to document coordinates suitable for a page crop.
#1 Best Overall
- CRISP CLARITY: This 23.8″ Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
- INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
- THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
- WORK SEAMLESSLY: This sleek monitor is virtually bezel-free on three sides, so the screen looks even bigger for the viewer. This minimalistic design also allows for seamless multi-monitor setups that enhance your workflow and boost productivity
- A BETTER READING EXPERIENCE: For busy office workers, EasyRead mode provides a more paper-like experience for when viewing lengthy documents
That distinction matters when the page has been scrolled. If you use viewport coordinates as though they were document coordinates, the output can be shifted up, down, left, or right. Layout can also change while fonts, images, advertisements, or JavaScript components finish loading, so measure the element only after the state you want to capture exists.
Complete PhantomJS example
Save this as element-shot.js. It accepts three command-line arguments: the URL, a CSS selector, and the output filename. Defaults are included so you can run it without arguments.
var webpage = require('webpage');
var system = require('system');
var page = webpage.create();
var url = system.args[1] || 'https://example.com/';
var selector = system.args[2] || '#target';
var output = system.args[3] || 'element.png';
page.viewportSize = { width: 1280, height: 900 };
function stopWithError(message) {
console.error(message);
phantom.exit(1);
}
function waitFor(test, callback, timeout) {
var started = Date.now();
var timer = setInterval(function () {
var ready = false;
try {
ready = test();
} catch (error) {
ready = false;
}
if (ready) {
clearInterval(timer);
callback(true);
} else if (Date.now() - started >= timeout) {
clearInterval(timer);
callback(false);
}
}, 100);
}
page.open(url, function (status) {
if (status !== 'success') {
stopWithError('Unable to load the page: ' + status);
return;
}
waitFor(function () {
return page.evaluate(function (css) {
var element = document.querySelector(css);
if (!element) {
return false;
}
var rect = element.getBoundingClientRect();
return rect.width > 0 && rect.height > 0;
}, selector);
}, function (ready) {
if (!ready) {
stopWithError('The selector was not found or has no visible size: ' + selector);
return;
}
var box = page.evaluate(function (css) {
var element = document.querySelector(css);
if (!element) {
return null;
}
element.scrollIntoView();
var rect = element.getBoundingClientRect();
return {
top: rect.top + window.pageYOffset,
left: rect.left + window.pageXOffset,
width: rect.width,
height: rect.height
};
}, selector);
if (!box || box.width <= 0 || box.height <= 0) {
stopWithError('The element has an invalid rendered rectangle.');
return;
}
page.clipRect = {
top: box.top,
left: box.left,
width: box.width,
height: box.height
};
page.render(output);
console.log('Saved ' + output);
phantom.exit(0);
}, 10000);
});
Run it with a shell command such as:
phantomjs element-shot.js https://example.com/ '.hero' hero.png
Quote selectors that contain spaces, brackets, or characters interpreted by your shell. The script uses querySelector, so the selector must be valid CSS. If it matches several elements, querySelector captures the first match; use a more specific selector when you need another instance.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →Make the crop match what you see
Use the same viewport for measurement and rendering
Set page.viewportSize before opening the page and leave it unchanged while measuring. Responsive breakpoints can move or resize the target when the viewport changes. A crop measured at one width but rendered at another is not reliable.
Wait for a visual condition, not an arbitrary delay
PhantomJS examples commonly show a short delay before rendering, but a fixed sleep does not prove that asynchronous content has settled. The example polls for the selector and a non-zero rectangle. For a page that replaces the element after an API response, extend the test to check a class, text value, or other condition that represents the final state. Only then read the rectangle.
Rank #2
- CRISP CLARITY: This 22 inch class (21.5″ viewable) Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
- 100HZ FAST REFRESH RATE: 100Hz brings your favorite movies and video games to life. Stream, binge, and play effortlessly
- SMOOTH ACTION WITH ADAPTIVE-SYNC: Adaptive-Sync technology ensures fluid action sequences and rapid response time. Every frame will be rendered smoothly with crystal clarity and without stutter
- INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
- THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
Account for scrolling
getBoundingClientRect() is viewport-relative. The example calls scrollIntoView(), then adds the current page offsets. This avoids the most common vertical-offset error. A fixed or sticky header can still overlap the element after scrolling; if that happens, scroll farther or apply page-specific JavaScript before measuring.
Understand nested scrolling and overflow
An element inside an independently scrolling container may have only a partial visible area. A rectangle around the element can include content that the container clips, or can represent only the portion currently exposed. If the target is in a carousel, modal, or scrollable panel, put that container into the intended scroll position before collecting its rectangle and verify the resulting image.
Measure after images and fonts settle
Late-loading assets can change widths and heights. If the target includes an image, wait for the page’s own ready condition or verify the image dimensions in the polling function. Do not treat a ten-second timeout as proof that every network request has completed; it is only a failure boundary for this script.
Choosing the output format
The PhantomJS capture guide lists PNG, JPEG, GIF, and PDF render outputs. Choose the extension that matches the output you need:
| Filename example | Format | Use when |
|---|---|---|
element.png |
PNG | You need lossless output, sharp text, or transparency behavior supported by the page. |
element.jpg |
JPEG | You prefer a compressed photographic image. |
element.gif |
GIF | You specifically need the GIF render format listed by PhantomJS. |
element.pdf |
You need a document render rather than a raster screenshot. |
The extension controls the format passed to page.render(). This article’s single-element examples use image files; PDF pagination and print layout are separate concerns.
Troubleshooting a wrong or empty screenshot
“Unable to load the page”
Cause: page.open returned a status other than success.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Rank #3
- Clear visuals. Fluid motion: A 144Hz refresh rate and 1ms MPRT deliver smooth, tear‑free motion across work, gaming, and streaming for clearer, more fluid viewing.
- Eye comfort: TÜV Rheinland 3‑star* certification reduces harmful blue light while preserving stunning color quality without compromise. *TÜV Rheinland 3-star eye comfort certification.
- Wide viewing angle: Get consistent views across a wide 178° /178° viewing angle.
- In-Plane Switching (IPS): See excellent color accuracy and consistency across wide viewing angles with In-plane Switching (IPS) technology.
- Ultra-thin bezels: Maximize your viewing experience with thin bezels.
Fix: confirm the URL, connectivity, redirects, and whether the site can be rendered by PhantomJS’s QtWebKit engine. Stop rather than rendering a blank page, because a successful file write does not guarantee useful page content.
Selector not found or zero size
Cause: the selector is wrong, the element is inserted later, or it is hidden with zero width or height.
Fix: test the selector in the page’s own DOM, wait for the insertion condition, and select the visible component rather than a hidden template node. The example reports this condition after ten seconds.
Crop is offset
Cause: viewport coordinates were used as page coordinates, or the document scrolled between measurement and rendering.
Fix: measure and assign clipRect in one operation, add pageXOffset and pageYOffset, and avoid triggering layout-changing code afterward.
Rank #4
- CURVED FOR ENHANCED ENGAGEMENT: An immersive viewing experience with a curved monitor that wraps more closely around your field of vision; It creates a wider view, enhancing depth perception and minimizing peripheral distraction
- SMOOTH PERFORMANCE FOR SEAMLESS CONTENT: Stay in the action when playing games, watching videos, or working on creative projects; The 100Hz refresh rate reduces lag and motion blur so you don't miss a thing in fast-paced moments¹
- MORE GAMING POWER: Gain the edge with optimizable game settings; Color and image contrast can be adjusted to see scenes more vividly and spot enemies hiding in the dark; Game Mode adjusts any game to fill the screen so you can view every detail²
- KEEP IT EASY ON THE EYES: Care for your eyes and stay comfortable, even during long sessions; Advanced eye comfort technology certified by TÜV reduces eye strain by minimizing blue light and reducing irritating screen flicker²
- INCREASED VERSATILITY: Connect to more; Plug devices straight into your monitor for increased flexibility, making your computing environment even more convenient
Only part of the element appears
Cause: the element is clipped by an ancestor, extends beyond the current layout, or changed size after measurement.
Fix: inspect ancestor overflow behavior, set the intended scroll position, wait for late content, and log the returned rectangle before calling render. Remember that clipRect is a rectangle; it cannot remove an ancestor’s visual clipping.
The screenshot contains an old state
Cause: rendering occurred before a client-side update, animation, or image load finished.
Fix: replace a blind delay with a page condition that indicates readiness. If an animation changes the target, wait for its completed class or disable it in page-specific JavaScript before measuring.
Several matching elements are possible
Cause: querySelector returns only the first match.
Fix: narrow the CSS selector, or change the browser-side code to use querySelectorAll and choose an index deliberately. Keep the same selected node for both the readiness check and rectangle measurement.
Best Value
- 【INTEGRATED SPEAKERS】Whether you're at work or in the midst of an intense gaming session, our built-in speakers provide rich and seamless audio, all while keeping your desk clutter-free.
- 【EASY ON THE EYES】 Protect your eyes and enhance your comfort with Blue-Light Shift technology. This feature reduces harmful blue light emissions from your screen, helping to alleviate eye strain during long hours of use and promoting healthier viewing habits.
- 【WIDEN YOUR PERSPECTIVE】Our sleek minimal bezel design ensures undivided attention. The nearly bezel-free display seamlessly connects in a dual monitor arrangement, delivering an unobstructed view that lets you focus on more at once, completely distraction-free.
PhantomJS status and modern alternatives
The PhantomJS project homepage currently states: “Important: PhantomJS development is suspended until further notice (more details).” The project identifies QtWebKit as its browser backend. Existing scripts can still be useful when their output is stable, but a new automation project should account for the suspended development status and the browser behavior your pages require.
Current browser automation libraries expose element-level screenshot methods directly:
Free tools Windows power users keep installed
One-click scans. No signup required.
| Tool | Element capture API | Behavior documented by the project | What you must evaluate |
|---|---|---|---|
| PhantomJS | Manual rectangle via page.clipRect and page.render() |
The cited API documents a viewport region, not selector capture. Waiting, geometry, and scrolling are your responsibility. | Legacy compatibility, QtWebKit behavior, and maintenance risk. |
| Playwright | await page.locator('.header').screenshot({ path: 'screenshot.png' }) |
The locator method clips to the matched element, scrolls it into view, performs actionability checks, and throws if the element detaches. Covered content and off-screen portions of a scrollable container have visibility limitations. | Browser/runtime installation, locator behavior, and the options in the version you deploy. |
| Puppeteer | ElementHandle.screenshot() |
The guide says it attempts to scroll a hidden element into view before capture. | Browser/runtime requirements, waiting strategy, and handle lifetime. |
For a script that must remain in PhantomJS, rectangle clipping is the documented path. For new work, compare maintenance status, locator support, wait and scroll behavior, runtime requirements, and the screenshot formats and options you need. No benchmark is implied by this comparison.
Or skip the browser setup
ScreenshotNeo is a hosted website screenshot API and MCP server. It can capture one element by CSS selector and offers 63 options, including full-page capture with lazy images loaded, viewport and device presets, custom CSS and JavaScript, click-before-capture actions, selector waits, network-idle waits, hidden selectors, request blocking, cookies and headers, geolocation, timezone, resizing, caching, signed links, asynchronous jobs, webhooks, bulk capture, and PDF output. Use the current option names in the ScreenshotNeo documentation when adding a selector or other setting.
A basic one-call capture is:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
The same request in 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)
And 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}`);
Before capture, ScreenshotNeo accepts cookie and consent banners 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 response headers identify the page verdict and billing result. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
| Plan | Price | Included shots |
|---|---|---|
| Free | $0 | 1,000 per month; no card required |
| Starter | $5 | 3,000 |
| Growth | $15 | 15,000 |
| Pro | $39 | 60,000 |
| Scale | $99 | 250,000 |
| Business | $249 | 1,000,000 |
Yearly billing gives two months free, and every feature is available on every plan. Create a free ScreenshotNeo account to start with 1,000 screenshots a month and no card.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Frequently Asked Questions
What if my CSS selector contains a quote or shell metacharacter?
Quote the entire selector for your shell, or pass the URL, selector, and filename from a wrapper script that supplies system.args safely. The selector still must follow CSS syntax.
Can I capture the second element when a selector matches several nodes?
Yes, but not with the example unchanged: querySelector deliberately chooses the first match. Change the browser-side lookup to querySelectorAll, select the required index, and use that same node for both readiness and geometry.
Does setting clipRect modify the webpage?
No. It changes the region PhantomJS sends to page.render(); the DOM and page layout remain governed by your script and the loaded document.
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.

