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

Change a PhantomJS page’s browser viewport by assigning a positive, integer-dimension object to page.viewportSize. Set it before page.open() when the initial responsive layout must use the new dimensions, then render after the page has loaded:

var page = require('webpage').create();
page.viewportSize = { width: 1280, height: 800 };

page.open('https://example.com/', function (status) {
  if (status !== 'success') {
    console.error('Unable to load the page.');
    phantom.exit(1);
    return;
  }

  page.render('capture.png');
  phantom.exit();
});

viewportSize controls the browser’s layout viewport. It is different from page.clipRect, which only crops the rectangle included in the output image. PhantomJS is legacy software: its repository is archived and read-only, and the project wiki describes the 2.x branch as deprecated and no longer maintained. Use the technique below for an existing script, but treat compatibility with modern sites as uncertain.

What page.viewportSize changes

The WebPage object exposes viewportSize as an object with width and height properties. The automation reference shows the form { width: 1024, height: 768 }. These values are CSS-pixel dimensions used for layout: media queries, responsive breakpoints, element positioning and the visible browser area all see this viewport.

A viewport is not the same thing as the final bitmap dimensions in every workflow. A device pixel ratio or rendering scale can affect the physical image, while clipRect can crop the area that is saved.

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

Viewport versus clipRect

Set viewportSize when you want the page to lay itself out as a particular screen size. Set clipRect when you want to capture only a sub-rectangle of that laid-out page. Changing the crop does not activate a different responsive breakpoint.

page.viewportSize = { width: 1440, height: 900 };
page.clipRect = { top: 0, left: 0, width: 600, height: 400 };

This renders a 1440×900 layout but saves only the 600×400 rectangle beginning at the top-left corner. The official screen-capture guidance demonstrates configuring the viewport before navigation and rendering after the page opens. Screen capture example and the viewportSize API reference document the properties and sequence.

Set a dynamic size from script data

There is nothing special about a literal. Assign a variable whenever your dimensions come from a command-line argument, a configuration file, a test case or a loop.

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

Validate external values before assigning them. PhantomJS 2.1.1 converts supplied width and height values to integers and applies the size only when both converted values are greater than zero. Relying on that conversion can silently produce an unchanged viewport for zero, negative, fractional or malformed input, so reject those values yourself.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
function readPositiveInteger(value, name) {
  var number = Number(value);
  if (!isFinite(number) || Math.floor(number) !== number || number <= 0) {
    throw new Error(name + ' must be a positive integer');
  }
  return number;
}

var width = readPositiveInteger(phantom.args[0] || 1280, 'width');
var height = readPositiveInteger(phantom.args[1] || 800, 'height');
var page = require('webpage').create();
page.viewportSize = { width: width, height: height };

page.open('https://example.com/', function (status) {
  if (status !== 'success') {
    console.error('Unable to load the page.');
    phantom.exit(1);
    return;
  }
  page.render('dynamic-' + width + 'x' + height + '.png');
  phantom.exit();
});

Run it with, for example, phantomjs capture.js 375 812. The script keeps the controller-side API outside the page and fails early for invalid dimensions.

Rank #2
Sale
HTML and CSS: Design and Build Websites
  • HTML CSS Design and Build Web Sites
  • Comes with secure packaging
  • It can be a gift option

Change sizes for several captures

For a set of responsive snapshots, assign the next size before each capture. When the page’s JavaScript reacts to a resize, allow that work and any layout repaint to finish before rendering. The official examples establish the property and navigation order, but do not prescribe a universal repaint delay; choose a wait condition appropriate to the page.

var webpage = require('webpage');
var page = webpage.create();
var cases = [
  { name: 'phone', width: 375, height: 812 },
  { name: 'tablet', width: 768, height: 1024 },
  { name: 'desktop', width: 1440, height: 900 }
];
var index = 0;

function captureNext() {
  if (index === cases.length) {
    phantom.exit();
    return;
  }

  var item = cases[index++];
  page.viewportSize = { width: item.width, height: item.height };
  window.setTimeout(function () {
    page.render('capture-' + item.name + '.png');
    captureNext();
  }, 100);
}

page.open('https://example.com/', function (status) {
  if (status !== 'success') {
    console.error('Unable to load the page.');
    phantom.exit(1);
    return;
  }
  captureNext();
});

A fixed delay is only a simple example. If the page exposes a reliable “ready” element, poll for it or use a page-specific signal instead. For pages that rebuild content on resize, capture only after the rebuilt DOM is present. Changing the viewport after a page has loaded may work in the particular legacy runtime, but behavior should be verified in that runtime rather than assumed from modern browsers.

Configure the viewport before navigation

Set the property before page.open() whenever the first layout matters. This ensures that responsive code runs against the intended dimensions during initial navigation and that screenshots do not begin with a desktop layout and switch later.

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.
  1. Create the page with require('webpage').create().
  2. Validate and assign page.viewportSize = { width, height }.
  3. Call page.open().
  4. Check the callback status.
  5. Wait for any page-specific readiness condition, then call page.render().
  6. Exit with a non-zero status on failure.

The Page Automation documentation describes the browser-size property, while the official capture guide shows it configured before opening a URL.

Keep evaluate in the page context

page.evaluate() executes JavaScript inside the loaded webpage. It cannot access the PhantomJS phantom object, and its arguments and return values must be simple JSON-serializable values. Therefore, do not try to set page.viewportSize from inside the callback. Set the viewport in the outer PhantomJS script and use evaluate for DOM work, such as checking whether a selector has appeared.

Rank #3
Sale
Web Design with HTML, CSS, JavaScript and jQuery Set
  • Brand: Wiley
  • Set of 2 Volumes
  • A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers
page.viewportSize = { width: 1024, height: 768 };

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

  var hasMain = page.evaluate(function () {
    return !!document.querySelector('main');
  });

  if (!hasMain) {
    console.error('The expected content did not appear.');
    phantom.exit(1);
    return;
  }

  page.render('with-main.png');
  phantom.exit();
});

Common failures and fixes

The screenshot still uses the old layout

  • Assign the viewport before page.open() and before the render call.
  • Check that both keys are spelled exactly width and height.
  • After a post-load change, wait for the page’s resize handler and content update before rendering.
  • Confirm that you are not mistaking a clipRect crop for a viewport change.

The assignment appears to do nothing

PhantomJS 2.1.1 ignores the change when either converted dimension is not positive. Convert input to finite positive integers and log the values before assignment. A string containing non-numeric characters, zero, a negative number or a fractional value is unsafe input.

page.open reports failure

Do not render when the callback status is not success. Log the URL and exit with an error so an automation job can detect the failure. A valid viewport cannot make an unreachable or failed page load succeed.

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

DOM checks fail inside evaluate

Remember that the callback runs in the webpage sandbox. Pass only JSON-compatible data and return only JSON-compatible values; keep phantom, page and other controller objects in the outer script.

Modern sites render incorrectly

PhantomJS is no longer maintained. The project repository is archived read-only, and the project wiki marks PhantomJS 2.x deprecated. Modern TLS, JavaScript, browser APIs, bot checks and continuously changing site code may therefore fail or behave differently. The available project material does not establish an official successor or a final release date, so choose a maintained browser automation tool independently if you are starting a new workflow.

Reliability and performance considerations

Choose dimensions deliberately

Use the smallest viewport that represents the target breakpoint when testing responsive behavior, and use a larger height when the test depends on below-the-fold layout. Width usually controls responsive breakpoints; height mainly changes the visible area and the amount captured in a viewport-sized render.

Avoid unnecessary navigations

If the same page can be reused, open it once and capture several sizes. Reassign the viewport, wait for resize-driven work, and render each variant. This reduces repeated network and startup cost, but only if the page correctly responds to a runtime resize.

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

Make output names and failures observable

Include the dimensions in each filename and treat a failed page.open or missing readiness selector as an error. That makes a batch run auditable instead of leaving ambiguous images that look like successful captures.

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

Or skip the browser setup

If your goal is a dependable URL screenshot rather than maintaining PhantomJS, ScreenshotNeo provides a single HTTP request. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups and chat widgets; bot checks, blank pages, timeouts, failed loads and cache hits are not billed, and response headers identify the page verdict and billing result. Its MCP server exposes take_screenshot, get_page_info and capture_pdf to Claude, Cursor and other MCP clients.

Every plan includes the same features: full-page captures with lazy images loaded, CSS-selector element capture, dark mode, 12 device presets or a custom viewport, retina scale, PDF paper and margin controls, custom CSS and JavaScript, clicks, selector or network-idle waits, request and resource blocking, headers, cookies, user-agent and authorization controls, timezone and geolocation, transparent backgrounds, resizing, configurable-TTL caching, signed image links, asynchronous jobs with signed webhooks, batches of up to 100 URLs, a usage API and an OpenAPI specification. Existing integrations can use the parameter names used by other screenshot APIs.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the ScreenshotNeo documentation for authentication, output formats and all options. The same request in Python is:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
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}`);

The Free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots; annual billing provides two months free. Create a free ScreenshotNeo account to try the 1,000 monthly screenshots without entering a card.

Frequently Asked Questions

What is the default PhantomJS viewport size?

The Page Automation documentation gives { width: 1024, height: 768 } as the documented form and example. Set your own values explicitly when the size matters.

Can I set viewport dimensions inside page.evaluate()?

No. evaluate runs in the webpage context and cannot access the PhantomJS controller. Assign page.viewportSize in the outer script.

Does changing clipRect change responsive breakpoints?

No. clipRect crops the rendered area; only viewportSize changes the browser layout dimensions.

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

Is PhantomJS suitable for a new screenshot service?

It is legacy software: the repository is archived and the 2.x line is described as deprecated and unmaintained. Modern-site compatibility is therefore uncertain; a maintained browser or a screenshot API is a safer starting point.

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.