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.

Yes—but indirectly. Changing page.settings.userAgent changes the identity PhantomJS sends with resource requests. If the target server uses that identity to choose different HTML, CSS, images, or a mobile layout, the screenshot can change. The PhantomJS rendering engine does not change: it remains the WebKit engine compiled into your PhantomJS build.

A browser-like user-agent is therefore request customization, not full browser emulation. Results are site-specific, so a reliable comparison keeps the URL, viewport, crop, page state, and timing constant while changing only the user-agent.

What the user-agent setting actually changes

PhantomJS exposes a per-page property:

page.settings.userAgent

It defines the user-agent sent to the server when the page requests resources. The setting must be assigned before the initial page.open() call. Assigning it after navigation has started will not retroactively change the requests that loaded the document, and changing it later is not a dependable way to alter the current page.

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

The user-agent is just a request string. It can contain a browser name, operating system, device family, or any other text you choose. The server decides whether to use that string. A site may return the same response for every value, or it may select mobile markup, different stylesheets, alternate images, a consent flow, or another specialized page.

What does not change

Setting a Chrome, Safari, or iPhone user-agent does not install that browser’s engine. PhantomJS still renders through the WebKit libraries included in the particular PhantomJS build. The supported standards and layout behavior depend on those compiled libraries, not on the name written in the user-agent.

For that reason, a screenshot that looks “like mobile Chrome” may actually be a mobile response rendered by PhantomJS WebKit. It should not be described as a faithful Chrome or Safari capture.

Why a screenshot can look different

Server-selected markup

Some sites branch on the user-agent before sending a response. A desktop identity might receive a wide navigation bar, while a mobile identity receives a compact menu and different content structure. That difference is visible in the screenshot even though PhantomJS itself did not switch engines.

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

Conditional resources and styles

The server can also change which CSS, JavaScript, fonts, or images it references. A different stylesheet can alter line wrapping, element visibility, spacing, and page height. A different image variant can change the apparent composition or loading time.

Cases where nothing changes

If the site serves identical markup and resources for both user-agent strings, the rendered pixels may be identical. There is no universal rule that changing the string must change a capture, and the available documentation does not establish a percentage of sites that branch on it.

Use a controlled PhantomJS comparison

Run the same page twice and vary one input: the user-agent. Keep every other capture variable fixed. This makes a difference easier to attribute to the server response instead of to a moving viewport, crop, animation, or ad.

Complete PhantomJS script

Save this as compare.js. It writes two PNG files with the same viewport and clip rectangle.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
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
var page = require('webpage').create();
var system = require('system');

var target = system.args[1] || 'https://example.com';
var mode = system.args[2] || 'desktop';

var userAgents = {
  desktop: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36',
  mobile: 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1'
};

if (!userAgents[mode]) {
  console.log('Mode must be desktop or mobile');
  phantom.exit(2);
}

// Must be set before page.open().
page.settings.userAgent = userAgents[mode];
page.viewportSize = { width: 1280, height: 800 };

page.open(target, function (status) {
  if (status !== 'success') {
    console.log('Open failed: ' + status);
    phantom.exit(1);
  }

  // Keep the capture timing identical in both runs.
  window.setTimeout(function () {
    page.clipRect = { top: 0, left: 0, width: 1280, height: 800 };
    page.render(mode + '.png');
    console.log(mode + ': ' + page.title);
    phantom.exit();
  }, 1500);
});

Run it with the same URL for each identity:

phantomjs compare.js https://example.com desktop
phantomjs compare.js https://example.com mobile

The script fixes a 1,280×800 viewport and an identical 1,280×800 crop. Change those values to match your test, but do not change them between runs.

Inspect the page, not just the pixels

When the images differ, check the loaded title, visible navigation, text, and major resources. A changed screenshot is evidence that something in the response or page state differed; it is not proof that PhantomJS emulated the named browser. If possible, log the final URL and inspect resource requests to see whether the server returned alternate assets.

Viewport, crop, and timing are separate controls

page.viewportSize controls the browser viewport available to the page. page.clipRect controls the rectangle copied into the output. page.render() writes the image. A mobile user-agent with a desktop-sized viewport may receive mobile markup but still lay it out in a wide viewport. Conversely, a narrow viewport can trigger responsive CSS even when the user-agent is unchanged.

  • Keep viewport width and height identical for every user-agent run.
  • Keep page.clipRect identical, or omit it consistently when comparing full output.
  • Use the same wait strategy and delay. Dynamic content, animations, and advertising can otherwise create differences unrelated to the user-agent.
  • Use the same cookies, local storage, URL parameters, and authentication state.

For a full-page experiment, use a consistent full-page capture approach and verify that lazy content has finished loading. A fixed crop is usually easier to compare because it removes page-height changes from the first diagnostic pass.

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

Common mistakes and their fixes

Setting the property after navigation

Symptom: The output still reflects the original identity.

Cause: page.open() already initiated requests.

Fix: Assign page.settings.userAgent immediately after creating the page and before opening the URL. Start a new PhantomJS page for each identity when comparing runs.

Assuming the string changes the browser engine

Symptom: A page still lacks a feature supported by modern Chrome, or layout behavior resembles PhantomJS.

Cause: The user-agent does not replace WebKit or add browser APIs.

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

Fix: Treat the result as PhantomJS WebKit rendering of a response selected by the server. If you require actual Chrome, Safari, or a current mobile browser, use that browser’s automation stack instead.

Changing viewport and user-agent together

Symptom: You cannot tell whether the difference came from responsive CSS or server-side detection.

Fix: First hold the viewport constant and change only the user-agent. Then run a second experiment that changes only the viewport. Document both results.

Capturing too early

Symptom: Two runs show different ads, missing images, or different text.

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

Cause: The page is dynamic, resources have different latency, or an animation is at a different point.

Fix: Wait for a deterministic condition when possible, such as a known selector, and use the same delay or readiness check in both runs. Disable or account for animations in test CSS if the page permits it.

Rank #4
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

Relying on a browser version token

Symptom: You expect a newer standards implementation because the string says “Chrome/120.”

Fix: Check the WebKit capabilities of the PhantomJS build you actually run. The build’s linked libraries determine behavior; the token is only sent to the server.

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

Choosing user-agent strings responsibly

Use a string that represents the response you need to investigate, and record it with your capture metadata. A desktop string is useful for desktop-serving logic; a mobile string can reveal mobile templates. Avoid presenting an arbitrary custom string as a tested real device unless you have verified the site’s behavior.

Do not infer universal support from one site. User-agent parsing is implemented by each target, sometimes in application code and sometimes in a CDN or device-detection service. A site can also ignore the value completely or combine it with viewport width, cookies, headers, and feature detection.

Reliability and cost considerations

PhantomJS documentation is legacy, and its WebKit version varies by build. Pin the executable and operating environment in repeatable jobs, record the user-agent and viewport alongside each image, and compare page content as well as pixels. There is no general measurement showing how often a user-agent change alters screenshots, so treat every conclusion as specific to the tested site and build.

For production capture, decide whether you need a historical PhantomJS response or a modern browser. PhantomJS can be appropriate for reproducing an existing pipeline, but a browser-like user-agent cannot compensate for an older engine’s missing standards or APIs.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

ScreenshotNeo provides a website screenshot API and MCP server when you want a clean capture without maintaining PhantomJS. Its request can accept a URL and return PNG, JPEG, WebP, or PDF. Before capture it can accept cookie or consent banners and remove more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be turned off.

Only clean shots are billed. 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. An MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.

The simplest call is shown in the ScreenshotNeo 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(`${res.status} ${res.statusText}`);
const bytes = await res.arrayBuffer();
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', Buffer.from(bytes)));

ScreenshotNeo also supports full-page captures with lazy images loaded, CSS-selector element captures, dark mode, 12 device presets or any viewport, retina scale, PDF paper size and page ranges, HTML/CSS-to-image, custom CSS and JavaScript, clicks before capture, selector waits, delays, network-idle waits, request and resource blocking, custom 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, an OpenAPI specification, and familiar parameter names for easier migration.

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.

Plans include 1,000 screenshots per month free with no card. Paid plans start at $5 for 3,000 shots; yearly billing provides two months free, and every feature is available on every plan. Create a free ScreenshotNeo account to try the 1,000 monthly screenshots.

Frequently Asked Questions

Does a mobile user-agent force a mobile viewport in PhantomJS?

No. The user-agent can influence which response the server sends, while page.viewportSize independently controls the layout viewport. Set both explicitly when testing.

Can I change the user-agent without reopening the page?

For a dependable comparison, create or reload a page with the new value set before page.open(). Existing requests and document state will not be rewritten by changing the property afterward.

Why do two captures differ when the HTML appears identical?

Fonts, images, ads, animations, asynchronous requests, cookies, and timing can change pixels. Hold those conditions steady and inspect resource requests before attributing the difference to user-agent handling.

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

Is PhantomJS suitable for testing current browser compatibility?

It is a legacy WebKit-based environment. A browser-like user-agent does not add modern browser features, so use a current browser engine when compatibility with present-day Chrome, Safari, or Firefox is the requirement.

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.