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

Use PhantomJS’s page.render() after setting viewportSize before page.open(). Add clipRect when you need a crop, and use paperSize only for PDF page dimensions, margins, and orientation. The complete example below checks the load result, waits for page-specific readiness, and then writes a PNG. PhantomJS can produce a useful, repeatable capture, but its project is legacy software and its output is not guaranteed to match a current browser.

What PhantomJS actually controls

A screenshot is the result of several independent decisions:

  • Layout viewport: viewportSize determines the browser viewport in which the page lays out.
  • Rendered region: clipRect limits rasterization to a rectangle. Without it, PhantomJS renders the whole page.
  • Output format: page.render() can write PNG, JPEG, GIF, or PDF.
  • PDF paper: paperSize controls the PDF page, including dimensions, margins, and orientation; it is not a replacement for the browser viewport.

These controls improve predictability, not automatically image quality. Fonts, CSS, asynchronous content, animation, and the older QtWebKit engine all affect the final file.

Prerequisites and a safe capture sequence

Install and invoke PhantomJS

Use a PhantomJS 2.1 installation that you can reproduce in your build or deployment environment. Verify the executable first:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
Sale
phantomjs --version

Keep the URL and output path explicit. In automation, run the command from a directory where the process can write the destination file and where logs can be collected.

Set the viewport before navigation

Assign both width and height to page.viewportSize before calling page.open(). The viewport controls responsive breakpoints and the amount of content visible in the initial layout; it does not set a pixel-density or high-DPI mode.

Wait for the page’s actual readiness condition

The page-open callback tells you whether the initial navigation succeeded. It does not prove that client-side data, web fonts, lazy images, or animations have finished. Use a condition that belongs to the page: poll for a selector, expose a completion flag from application code, or wait for a known network-driven state. A fixed delay can be useful for a controlled page, but the guide’s sample 200 ms pause is not a universal solution.

Minimal PNG screenshot script

Save this as capture.js and run it with phantomjs capture.js. It sets the viewport before opening the page, handles a failed navigation, and renders only after a page-specific readiness check (the example looks for a selector).

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 webpage = require('webpage');
var system = require('system');

var page = webpage.create();
var target = system.args[1] || 'https://example.com/';
var output = system.args[2] || 'screenshot.png';

page.viewportSize = { width: 1440, height: 900 };

page.open(target, function (status) {
  if (status !== 'success') {
    console.log('Unable to load the address: ' + target);
    phantom.exit(1);
    return;
  }

  // Replace this with a selector or application flag that means
  // the target page is ready to capture.
  var ready = page.evaluate(function () {
    return document.querySelector('[data-screenshot-ready]') !== null;
  });

  if (!ready) {
    console.log('The page loaded, but its ready marker was not found.');
    phantom.exit(1);
    return;
  }

  page.render(output);
  console.log('Wrote ' + output);
  phantom.exit(0);
});

If the site has no readiness marker, replace the check with a bounded polling loop or a deliberately chosen delay. Do not leave PhantomJS running indefinitely: every branch should call phantom.exit().

Controlling screenshot dimensions and crops

Full viewport or full page

viewportSize sets the layout viewport. It does not mean “capture only this rectangle.” With no clipRect, the render operation processes the whole page according to PhantomJS’s rendering behavior. For a long document, inspect the resulting image rather than assuming the viewport height is the output height.

Capture a rectangular region with clipRect

Set top, left, width, and height before calling render():

page.clipRect = {
  top: 0,
  left: 0,
  width: 800,
  height: 600
};
page.render('hero.png');

The coordinates describe the rectangle to rasterize. A crop is not a scale factor, retina setting, or quality enhancement. If the rectangle extends beyond useful page content, the output can contain blank space; choose coordinates after checking the page’s actual layout.

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

Capture an element by measuring it

PhantomJS does not provide a dedicated “render this CSS selector” command in the documented API, but you can obtain an element’s bounding rectangle in the page context and assign those values to clipRect:

var box = page.evaluate(function () {
  var node = document.querySelector('.invoice');
  if (!node) { return null; }
  var r = node.getBoundingClientRect();
  return {
    left: r.left + window.pageXOffset,
    top: r.top + window.pageYOffset,
    width: r.width,
    height: r.height
  };
});

if (!box || box.width <= 0 || box.height <= 0) {
  console.log('Element was not found or has no area.');
  phantom.exit(1);
} else {
  page.clipRect = box;
  page.render('invoice.png');
  phantom.exit(0);
}

Measure after the element is visible and after fonts or data that change its dimensions have settled. Fixed headers, scrolling containers, and CSS transforms can make visual coordinates differ from the simple document rectangle, so verify a sample output.

Choosing PNG, JPEG, GIF, or PDF

Raster images

The documented page.render() formats are PNG, JPEG, and GIF in addition to PDF. PNG is generally convenient for interfaces, text, and transparency; JPEG can be smaller for photographic content; GIF is limited and mainly useful where its legacy constraints are acceptable. These are format trade-offs, not a PhantomJS quality ranking. Select the format required by the consuming system and inspect files at their intended display size.

Base64 output

page.renderBase64(format) returns a base64-encoded string and documents PNG, GIF, and JPEG formats. This is useful when the next step expects data in memory rather than a file:

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.
var encoded = page.renderBase64('PNG');
console.log(encoded);

Base64 increases transport size compared with binary output. Decode it at the boundary where your API or storage system expects an image.

PDF output and paperSize

For a PDF, configure paperSize separately from the viewport:

page.paperSize = {
  format: 'A4',
  orientation: 'portrait',
  margin: {
    top: '12mm',
    right: '12mm',
    bottom: '12mm',
    left: '12mm'
  }
};
page.render('report.pdf');

The documented presets are A3, A4, A5, Legal, Letter, and Tabloid. You can instead provide explicit width and height; supported units include millimetres, centimetres, inches, and pixels. Orientation can be portrait or landscape, and headers and footers are also documented. A paper width changes PDF pagination and margins; it does not emulate a different responsive browser viewport. Set both when you need a particular web layout on a particular paper size.

Making captures more consistent

Stabilize page state

  • Use a fixed viewport that represents the consumer’s layout, and record it with the output.
  • Wait for a selector, data flag, or other page-specific condition rather than relying on an arbitrary pause.
  • Disable or account for rotating banners, carousels, blinking cursors, and time-dependent content when deterministic pixels matter.
  • Ensure the required fonts and images are reachable from the PhantomJS process; a successful navigation can still leave missing resources.
  • Use a clip rectangle only after confirming the coordinates at the selected viewport.

Know what the documentation does not promise

The official references describe capture controls and examples, but they do not publish a universal image-quality score, recommended resolution, speed benchmark, or guarantee of modern-browser fidelity. Treat “high-quality” as a requirement you define for a particular page and output use. Compare the generated file with a current-browser reference if visual compatibility is important.

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

PhantomJS maintenance and security implications

The PhantomJS project website states: “Important: PhantomJS development is suspended until further notice (more details).” Its GitHub repository is archived and read-only; the repository page identifies 2.1 as the latest stable release and records an archive date of May 30, 2023.

That status matters when the target page uses newer JavaScript, TLS behavior, CSS, or browser security assumptions. Keep a pinned runtime, test representative URLs after every page change, and isolate the renderer from untrusted input where possible. The jsreport PhantomJS PDF documentation warns that an archived project may develop security issues and recommends migration to Chrome-based PDF printing for that recipe. That is a recommendation for jsreport’s PDF workflow, not proof that Chrome is best for every screenshot job.

Troubleshooting PhantomJS captures

“Unable to load the address”

Check the URL, DNS and TLS access from the machine running PhantomJS. Log the status and exit nonzero. If the page requires authentication, redirects, modern TLS, or JavaScript features unavailable to the legacy engine, a successful result may require a different renderer rather than a longer delay.

The screenshot is blank or incomplete

Confirm that rendering occurs inside the successful page.open() callback. Then wait for the page’s data and assets, verify that the expected selector exists, and inspect console or resource errors. Lazy content may require scrolling or an application-specific completion signal before rendering.

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

Text or fonts differ from the browser

Check that the font files are accessible and that the page has finished applying its styles. PhantomJS’s older engine can calculate layout differently from current browsers; if the difference is unacceptable, reproduce the workflow with a maintained browser renderer.

The crop is shifted

Recalculate the element rectangle at the same viewport used for capture. Account for document scroll offsets, fixed positioning, transforms, and borders. A clipRect value is a coordinate rectangle, not a selector or a device-pixel-ratio setting.

The PDF breaks at unexpected places

Review paperSize, margins, orientation, and explicit dimensions. Remember that PDF paper controls and the web layout viewport solve different problems. Test long tables, images, and page breaks with the exact paper preset used in production.

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

Performance, reliability, and operating cost

Rendering one page per PhantomJS process is simple but adds startup overhead. Reuse a controlled process only if you can reset cookies, page state, timers, and memory between jobs. Bound navigation and readiness waits, record output size and status, and retry only failures that are plausibly transient; repeated retries will not fix unsupported browser features. Cache inputs when the page is unchanged, but invalidate the cache when content, credentials, viewport, or paper settings change.

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

PhantomJS itself has no service-plan billing in this procedure. Your real costs are runtime maintenance, test coverage, compute, storage, and the engineering time required to handle pages that no longer work in an archived engine.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. It accepts a URL in one request and can return PNG, JPEG, WebP, or PDF. Before capture it accepts cookie or consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers.

For a direct request, see the ScreenshotNeo API documentation:

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,
)
r.raise_for_status()
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}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));

ScreenshotNeo also supports full-page capture with lazy images loaded, CSS-selector element capture, dark mode, 12 device presets or any viewport, retina scale, PDF paper size/margins/orientation/page ranges, HTML/CSS-to-image, custom CSS and JavaScript, pre-capture clicks, hidden selectors, waits for selectors, delays or network idle, blocking ads, trackers, requests or resource types, custom headers/cookies/user agents/Authorization, timezone and geolocation, transparent backgrounds, resizing, configurable-TTL caching, signed links for public image tags, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, a usage API, an OpenAPI specification, and compatible parameter names used by other screenshot APIs.

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

Its MCP server exposes take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. Every feature is available on every plan:

Plan Included shots Price
Free 1,000 per month No card required
Starter 3,000 $5
Growth 15,000 $15
Pro 60,000 $39
Scale 250,000 $99
Business 1,000,000 $249

Yearly billing gives two months free. If you want clean shots without maintaining a legacy browser, failed loads and bot checks that are never billed, and an MCP path for AI agents, sign up for ScreenshotNeo with 1,000 screenshots a month free and no card.

Quick Recap

SaleBestseller No. 1
The Phantom Tollbooth
The Phantom Tollbooth
Great product!
$7.64
SaleBestseller No. 2

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.