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

A PhantomJS process usually “hangs” for one of three reasons: the script never calls phantom.exit(), a page or individual request never reaches a completion callback, or errors are occurring silently. Confirm the executable and version, add explicit shutdown on every terminal path, instrument page and resource callbacks, then investigate HTTPS, proxy, SELinux, and page JavaScript issues. PhantomJS 2.1.1 documentation is legacy, and the upstream project is archived, so migrate when ongoing browser compatibility matters.

First, identify which kind of hang you have

Run the same command with a known script and note whether the terminal remains occupied after the intended work is complete, or whether the page itself never reports completion. These are different failures:

  • Process-lifecycle hang: rendering or inspection finished, but no code terminated PhantomJS.
  • Page-lifecycle hang: page.open has not produced a final status because navigation or a callback path is still pending.
  • Request hang: one image, script, font, API call, or other resource is slow or unreachable.
  • Script-error hang: a page or PhantomJS exception stopped the expected flow, while logging remained silent.
  • Transport or host problem: HTTPS libraries, a Windows proxy, or SELinux interferes with loading.

Keep the target URL, operating system, PhantomJS version, command line, and terminal output together while troubleshooting. The exact cause cannot be inferred without those details.

1. Confirm the binary and invocation

Check which executable your shell resolves and record its version:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
CanaKit Raspberry Pi 5 Starter Kit PRO - Turbine Black (128GB Edition) (8GB RAM)
  • Includes Raspberry Pi 5 with 2.4Ghz 64-bit quad-core CPU (8GB RAM)
  • Includes 128GB Micro SD Card pre-loaded with 64-bit Raspberry Pi OS, USB MicroSD Card Reader
  • CanaKit Turbine Black Case for the Raspberry Pi 5
  • CanaKit Low Noise Bearing System Fan
  • Mega Heat Sink - Black Anodized
phantomjs --version
which phantomjs   # macOS/Linux
where phantomjs   # Windows

Conflicting installations can make the terminal run a different binary from the one you tested. The documented invocation is phantomjs [options] somescript.js [arg1 ...]; PhantomJS runs headlessly. Add --debug=true when you need more CLI diagnostics. See the command-line reference.

2. Guarantee an explicit exit

PhantomJS does not terminate merely because a callback has returned. The official quick start warns that you must call phantom.exit, otherwise the process is not terminated. Put termination in both success and failure paths, but only after asynchronous work such as rendering has completed.

var page = require('webpage').create();
var address = system.args[1] || 'https://example.com';

page.open(address, function (status) {
  if (status === 'success') {
    page.render('page.png');
    phantom.exit(0);
  } else {
    console.log('Open failed: ' + status);
    phantom.exit(1);
  }
});

Do not call phantom.exit() immediately after page.open(); that can stop the browser before the callback or render operation runs. If your script has several asynchronous branches, route each intended terminal outcome through one completion function so that exactly one exit occurs.

References: Quick Start and render().

3. Instrument navigation and every requested resource

Log the navigation result and the requests around it. Configure resourceTimeout before the initial page.open; its unit is milliseconds and it applies to an individual requested resource, not to the whole script or JavaScript execution.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
var system = require('system');
var page = require('webpage').create();
var address = system.args[1] || 'https://example.com';

page.settings.resourceTimeout = 10000; // per-resource limit, milliseconds

page.onResourceRequested = function (request) {
  console.log('Request: ' + request.url);
};

page.onResourceTimeout = function (request) {
  console.log('Resource timeout: ' + request.url +
              ' (' + request.errorString + ')');
};

page.onResourceError = function (error) {
  console.log('Resource error: ' + error.url +
              ' (' + error.errorString + ')');
};

page.onError = function (message, trace) {
  console.log('Page JavaScript error: ' + message);
  if (trace && trace.length) {
    console.log(trace.map(function (t) {
      return '  ' + t.file + ':' + t.line;
    }).join('n'));
  }
};

page.onConsoleMessage = function (message) {
  console.log('Page console: ' + message);
};

page.open(address, function (status) {
  console.log('Page status: ' + status);
  phantom.exit(status === 'success' ? 0 : 1);
});

onLoadFinished reports success or fail; the callback supplied to page.open follows that lifecycle. A timeout callback identifies the request and error details, while onResourceError records failed resources. These hooks are documented at open(), onLoadFinished, onResourceRequested, onResourceTimeout, and onResourceError.

Rank #2
CanaKit Raspberry Pi 4 4GB Starter PRO Kit - 4GB RAM
  • Includes Raspberry Pi 4 4GB Model B with 1.5GHz 64-bit quad-core CPU (4GB RAM)
  • Includes Pre-Loaded 32GB EVO+ Micro SD Card (Class 10), USB MicroSD Card Reader
  • CanaKit Premium High-Gloss Raspberry Pi 4 Case with Integrated Fan Mount, CanaKit Low Noise Bearing System Fan
  • CanaKit 3.5A USB-C Raspberry Pi 4 Power Supply (US Plug) with Noise Filter, Set of Heat Sinks, Display Cable - 6 foot (Supports up to 4K60p)
  • CanaKit USB-C PiSwitch (On/Off Power Switch for Raspberry Pi 4)

A resource timeout does not stop an infinite loop in your own PhantomJS code, impose a universal wall-clock deadline, or retroactively change an already-started initial navigation. If you need a job-level deadline, enforce it outside PhantomJS with your process supervisor and terminate the process deliberately.

4. Expose exceptions that otherwise look like a freeze

Page JavaScript

page.onError reports exceptions thrown by scripts inside the loaded site. Add page.onConsoleMessage when you need the site’s own console output; page console messages are not printed by default.

PhantomJS execution errors

Use a global handler for errors in your PhantomJS script itself:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
phantom.onError = function (message, trace) {
  console.log('PhantomJS error: ' + message);
  if (trace) {
    trace.forEach(function (t) {
      console.log('  at ' + t.file + ':' + t.line);
    });
  }
  phantom.exit(1);
};

Install this handler early, before opening the page, so a syntax or runtime failure cannot leave the process waiting with no explanation. The official troubleshooting guide describes remote debugging with --remote-debugger-port=9000; connect with a WebKit-based browser such as Chrome, Chromium, or Safari to inspect execution interactively.

5. Check HTTPS, proxy, and host security

HTTPS fails but HTTP works

The troubleshooting guidance points first to the SSL libraries, usually OpenSSL. Verify that the libraries required by your PhantomJS build are installed and discoverable by the operating system, then retest the same URL. A successful HTTP request does not prove that the HTTPS trust and TLS stack is functional.

Windows is extremely slow

The default Windows proxy can introduce massive latency. If request logs show delays rather than immediate failures, test a run with:

phantomjs --proxy-type=none script.js https://example.com

Use this only when bypassing the configured proxy is appropriate for your network; corporate environments may require the proxy for access.

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

SELinux blocks the process

SELinux is another environment-specific possibility. Inspect denial logs first and compare a failing run with the policy context. The PhantomJS troubleshooting page references a custom-policy workaround, but changing enforcement rules without examining your system’s denials can create a security problem.

6. Use logs to locate the layer that stalls

Observed evidence Likely layer Next action
No “Page status” line and one URL repeats or remains open Navigation or resource Inspect request, timeout, and resource-error logs; set a per-resource timeout before page.open.
“Page status: success” appears, then the process remains Process lifecycle Find the missing terminal phantom.exit() or an outstanding asynchronous branch.
Status is fail Navigation/transport Check the failed URL, HTTPS libraries, proxy settings, and host access.
Page error appears Site JavaScript Fix or work around the offending page code; determine whether the requested output is still valid.
Nothing is logged Wrong binary, early crash, or missing handlers Verify phantomjs --version, use --debug=true, and install handlers before navigation.

7. Decide whether to keep patching PhantomJS

The upstream repository is archived and read-only (archived May 30, 2023). Its README says development is suspended, and the wiki describes the 2.x branch as deprecated and unmaintained. Existing jobs can often be stabilized with explicit exits and diagnostics, but no ongoing browser-compatibility fixes should be expected. Migration is the safer long-term choice when the target site changes, modern TLS is required, or failures must be supported in production. The best replacement depends on your language, rendering features, and deployment constraints; the available evidence does not establish one universal successor.

Or skip the browser setup:

For a maintained screenshot endpoint, ScreenshotNeo accepts one GET request and returns PNG, JPEG, WebP, or PDF. Before capture it accepts cookie/consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be disabled. Bot checks, 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 for Claude, Cursor, and other MCP clients.

See the complete parameter reference in the ScreenshotNeo documentation. A direct call looks like this:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #4
Raspberry SC15184 Pi 4 Model B 2019 Quad Core 64 Bit WiFi Bluetooth (2GB)
  • Broadcom BCM2711, quad-core Cortex-A72 (ARM v8) 64-bit SoC @ 1. 5GHz
  • 2. 4 GHz and 5. 0 GHz IEEE 802. 11b/g/n/ac wireless LAN, Bluetooth 5. 0, BLE
  • 2 × USB 3. 0 ports, 2 x USB 2. 0 Ports
  • 2 × micro HDMI ports supproting up to 4Kp60 video resolution
  • Micro SD card slot for loading operating system and data storage
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Equivalent 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)

Equivalent 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}`);

ScreenshotNeo includes full-page and element capture, device presets or custom viewports, retina scale, dark mode, PDF controls, custom CSS and JavaScript, selector waits, delays or network-idle waits, request blocking, headers, cookies, user agents, authorization, timezone and geolocation, transparent backgrounds, resizing, chosen-TTL caching, signed links, asynchronous webhooks, bulk capture of up to 100 URLs per call, usage reporting, and an OpenAPI specification. Parameter names used by other screenshot APIs also work, easing migration.

The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. Create a free ScreenshotNeo account.

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

Common errors and recovery steps

“It works manually but hangs in automation”

Compare the exact binary path, environment variables, proxy, and user permissions. Log the version and run with --debug=true; multiple installations are a frequent source of contradictory results.

A single third-party asset never finishes

Use onResourceRequested to identify it, then onResourceTimeout and onResourceError to capture the failure. Decide whether the asset is necessary; blocking or ignoring a nonessential tracker may let the page complete, while a required API call needs a network or application fix.

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.

The callback says fail immediately

Check the URL, DNS, certificate/TLS libraries, proxy, and firewall from the same host. Test HTTP versus HTTPS to separate transport problems from page behavior.

Best Value
CanaKit Raspberry Pi 5 16GB Starter Kit PRO - Turbine Black (128GB Edition) (16GB RAM)
  • Includes Raspberry Pi 5 16GB with 2.4Ghz 64-bit quad-core CPU (16GB RAM)
  • Includes 128GB Micro SD Card pre-loaded with 64-bit Raspberry Pi OS, USB MicroSD Card Reader
  • CanaKit Turbine Black Case for the Raspberry Pi 5
  • CanaKit Low Noise Bearing System Fan
  • Mega Heat Sink - Black Anodized

The process exits too early

Move phantom.exit() into the final callback after rendering or data extraction. An exit placed immediately after an asynchronous call can produce an incomplete file or no output.

Logs stop after a page exception

Keep both page.onError and phantom.onError installed. Print stack information and return a nonzero exit code so a scheduler marks the job failed instead of waiting indefinitely.

FAQ

Does resourceTimeout limit total runtime?

No. It limits each requested resource and must be set before the initial page.open. It is not a whole-process deadline.

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.

Why can a successful page still leave PhantomJS running?

A successful load only reports navigation status. The script still needs an explicit phantom.exit() after all intended asynchronous work.

Is PhantomJS officially maintained?

No. The repository is archived, development is suspended, and the 2.x branch is deprecated and unmaintained. Stabilize legacy jobs if necessary, but plan a migration for continued compatibility.

Frequently Asked Questions

Can I diagnose a hang without changing the target website?

Yes. Add lifecycle and resource callbacks, enable CLI debug output, and compare HTTP and HTTPS from the same host. These steps observe the run without modifying the page.

What should a nonzero exit code mean in a scheduled job?

Return zero only after the required capture or extraction succeeds; return one (or another documented nonzero code) for navigation failure, uncaught errors, or an intentionally timed-out required resource.

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

Quick Recap

Bestseller No. 1
CanaKit Raspberry Pi 5 Starter Kit PRO - Turbine Black (128GB Edition) (8GB RAM)
CanaKit Raspberry Pi 5 Starter Kit PRO - Turbine Black (128GB Edition) (8GB RAM)
Includes Raspberry Pi 5 with 2.4Ghz 64-bit quad-core CPU (8GB RAM); CanaKit Turbine Black Case for the Raspberry Pi 5
$259.95
Bestseller No. 2
CanaKit Raspberry Pi 4 4GB Starter PRO Kit - 4GB RAM
CanaKit Raspberry Pi 4 4GB Starter PRO Kit - 4GB RAM
Includes Raspberry Pi 4 4GB Model B with 1.5GHz 64-bit quad-core CPU (4GB RAM); Includes Pre-Loaded 32GB EVO+ Micro SD Card (Class 10), USB MicroSD Card Reader
$159.99
Bestseller No. 4
Raspberry SC15184 Pi 4 Model B 2019 Quad Core 64 Bit WiFi Bluetooth (2GB)
Raspberry SC15184 Pi 4 Model B 2019 Quad Core 64 Bit WiFi Bluetooth (2GB)
Broadcom BCM2711, quad-core Cortex-A72 (ARM v8) 64-bit SoC @ 1. 5GHz; 2. 4 GHz and 5. 0 GHz IEEE 802. 11b/g/n/ac wireless LAN, Bluetooth 5. 0, BLE
$87.98
Bestseller No. 5
CanaKit Raspberry Pi 5 16GB Starter Kit PRO - Turbine Black (128GB Edition) (16GB RAM)
CanaKit Raspberry Pi 5 16GB Starter Kit PRO - Turbine Black (128GB Edition) (16GB RAM)
Includes Raspberry Pi 5 16GB with 2.4Ghz 64-bit quad-core CPU (16GB RAM); CanaKit Turbine Black Case for the Raspberry Pi 5
$419.99

Why does ScreenshotNeo avoid some PhantomJS setup problems?

It performs the capture remotely, removes supported consent banners, popups, and chat widgets before the shot, and does not bill bot checks, blank pages, timeouts, failed loads, or cache hits.

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.