ScreenshotNeo

BlogHow-to

PhantomJS page.open Returns False: Screenshot Troubleshooting

PhantomJS documents page.open’s callback status as 'success' or 'fail,' not a boolean. Trace the callback, executable, network, page errors, and capture settings.

By the ScreenshotNeo team4 October 20266 min read

If your PhantomJS screenshot script says page.open returned false, first check what your code is actually logging: PhantomJS documents the page.open callback status as the string 'success' or 'fail', not as a boolean return value. The normal flow is to inspect that callback status and call page.render only after 'success'. If you see the literal false, it likely came from a wrapper, another expression, or your own status handling. See the official page.open reference and quick-start example.

1. Check the callback status first

Use a callback, log its value, and compare it to the documented strings. Keep rendering inside the callback so it happens after navigation completes. This diagnostic example also prints page JavaScript exceptions:

var page = require('webpage').create();

page.onError = function (msg, trace) {
  console.log('Page error: ' + msg);
  trace.forEach(function (item) {
    console.log('  ' + item.file + ':' + item.line);
  });
};

page.open('https://example.com/', function (status) {
  console.log('page.open callback status: ' + status);

  if (status === 'success') {
    page.render('capture.png');
    console.log('Saved capture.png');
  } else {
    console.log('Navigation failed; no screenshot rendered.');
  }

  phantom.exit();
});

Save it as capture.js and run it with the PhantomJS executable you intend to diagnose: phantomjs capture.js. The callback check and render sequence follow the official quick start; the onError handler follows the troubleshooting guide. This is a diagnostic template, not a claim that every website or PhantomJS build behaves identically.

Interpret what you see

  • success: Navigation completed according to the callback. If the image is still wrong, inspect page errors, readiness, output format, viewport, and clipping.
  • fail: Investigate the requested URL, connectivity, TLS libraries, proxy settings, and which PhantomJS binary ran.
  • false: The documented callback does not use this boolean. Find the exact expression or wrapper producing it and log the callback argument directly.
  • No callback output: Check whether the script starts, whether the expected executable is running, and whether the process exits or hangs before the callback.

2. Diagnose navigation failures

  1. Confirm the executable and version. Check the command path and version output for the binary actually invoked. The legacy troubleshooting guide warns that multiple installations can result in running a different version than expected. Compare the version in your shell, service, CI job, or container rather than assuming they share a PATH.
  2. Check the URL and network requests. Confirm the URL is reachable from the machine running PhantomJS, including DNS, firewall, proxy, and redirect behavior. Inspect network traffic when possible; a page JavaScript error is not proof of a transport failure.
  3. For HTTPS-only failures, inspect SSL dependencies. PhantomJS’s troubleshooting guidance calls out correctly installed SSL libraries, usually OpenSSL. Verify the runtime environment and libraries available to the actual PhantomJS process.
  4. On Windows, check proxy behavior. The legacy guide describes the default proxy as a possible source of latency and documents --proxy-type=none as a workaround when a proxy should not be used. For example: phantomjs --proxy-type=none capture.js. Use this only when bypassing the proxy is appropriate for your environment.
  5. Separate page errors from navigation status. Use page.onError to print JavaScript exceptions and stack locations. This can explain broken page logic, but it does not by itself identify why a network or TLS request failed.

3. If navigation succeeds but the screenshot is wrong

A successful callback does not guarantee that every application-specific asynchronous update has finished. The reviewed PhantomJS documentation does not promise a universal wait duration or that all dynamically added content is ready at the load callback. If a page populates content after load, wait for a condition specific to that page before rendering. Avoid choosing an arbitrary delay as a general fix: it can be too short on a slow run and waste time on a fast one.

Also verify the capture itself:

  • Output extension and format: page.render selects the format from the filename extension. The reference lists PDF, PNG, JPEG, BMP, PPM, and GIF where supported by the build. Use a matching extension and account for build-dependent format support. See the render reference.
  • Viewport: viewportSize controls the viewport dimensions used for the page layout and capture.
  • Clipping: clipRect limits the captured region. An unexpected rectangle can make a valid render look blank or incomplete.

The screen capture guide documents viewport and clipping settings. Change one setting at a time and compare the resulting file when diagnosing a crop or layout problem.

4. Common errors and fixes

Symptom Likely cause What to do
Code expects true or false from the callback It treats the documented status string as a boolean Log the callback argument and compare with 'success'; handle 'fail' explicitly.
Callback reports fail only for HTTPS SSL library or runtime dependency problem Check the SSL libraries, usually OpenSSL, in the environment that launches PhantomJS.
It works locally but fails in a service or CI A different executable, version, PATH, or dependency set is used Log the executable path and version in that environment, then compare its network and library setup.
Windows navigation is slow or stalls The default proxy may be involved Inspect proxy configuration; if bypass is intended, try the documented --proxy-type=none option.
Status is success, but content is missing Content may be added asynchronously after the load callback Wait for an application-specific readiness condition before rendering.
Capture is blank, cropped, or in an unexpected format Filename extension, Qt/build format support, viewport, or clip rectangle Check the extension and supported format; review viewportSize and clipRect.
Console shows a page exception Page JavaScript failed Use page.onError and its stack trace to locate the exception; diagnose it separately from navigation transport.

5. Reliability and maintenance notes

PhantomJS is a legacy tool: its GitHub repository is archived and read-only. Treat its documentation as version-specific guidance, identify the installed build, and verify behavior in the environment that runs captures. The cited sources do not establish current compatibility across operating systems, builds, or websites, nor do they provide a general success rate. See the archived repository issue for an example of an older report, not as evidence of a universal failure mode.

For a reliable diagnostic record, capture the PhantomJS version and executable path, URL, callback status, relevant network/TLS or proxy errors, page error stack, output filename, and viewport or clip settings. This lets you distinguish navigation failure from page execution and rendering configuration without treating them as the same problem.

6. Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. A GET request with a URL returns an image or PDF; the API options and parameter reference are in the ScreenshotNeo documentation.

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

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://example.com/"},
    timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({
  access_key: 'YOUR_API_KEY',
  url: 'https://example.com/'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await Bun.write('shot.webp', res);

ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before the shot; bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000. Sign up for 1,000 free screenshots a month, with no card.

7. FAQ

Does page.open return a boolean?

The documented completion callback receives the status string 'success' or 'fail'. If your code sees a boolean, trace the surrounding wrapper or expression.

Does page.onError explain every failed load?

No. It reports page JavaScript exceptions and stack traces. Network, TLS, proxy, and navigation failures need their own diagnosis.

Will the callback wait for every dynamic widget or image?

The cited documentation does not promise that. Wait for a page-specific readiness condition when content is added after load.