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

Direct answer: PhantomJS can be run and debugged without Selenium. Put the proxy on the PhantomJS process with --proxy, --proxy-type, and (when required) --proxy-auth. Use page.onError for JavaScript failures, resource callbacks for network evidence, and --remote-debugger-port for the built-in WebKit inspector. Start every investigation with --proxy-type=none as a control, then add the proxy and compare the logs.

Know which PhantomJS you are debugging

PhantomJS is a JavaScript-scriptable headless browser built on QtWebKit. Version 2.1 was released on January 23, 2016, and the project is archived; the project notice identifies 2.1.1 as the last known stable release. Its TLS stack, JavaScript engine, and WebKit features are therefore legacy. Record the exact binary and operating system for every reproduction instead of assuming that two installations behave alike.

Verify the executable before changing code

phantomjs --version

Multiple PhantomJS binaries on a PATH are a common source of contradictory results. Run the version command from the same shell, container, service account, or scheduled job that runs the failing script.

Run PhantomJS directly, with no Selenium

Proxy options are process-level settings. They are read when PhantomJS starts and do not require a WebDriver or Selenium session.

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.
Purpose Command-line form Notes
HTTP proxy --proxy=address:port --proxy-type=http HTTP is the default proxy type, but specifying it makes a test unambiguous.
SOCKS5 proxy --proxy=address:port --proxy-type=socks5 Use the address and listening port exposed by the SOCKS5 service.
No proxy --proxy-type=none Control run for separating inherited or misconfigured proxy settings from target-site failures.
Proxy credentials --proxy-auth=username:password The documented syntax puts credentials on the command line; protect process listings and shell history.

HTTP, SOCKS5, and authenticated examples

phantomjs --proxy=192.168.1.42:8080 --proxy-type=http script.js
phantomjs --proxy=127.0.0.1:9050 --proxy-type=socks5 script.js
phantomjs --proxy=proxy.example:8080 --proxy-auth=username:password script.js

Do not confuse an HTTP proxy with an HTTPS destination. An HTTP proxy can carry HTTPS through CONNECT when it supports it; the destination URL and the proxy protocol are separate settings.

Use a JSON configuration for repeatable runs

The command-line reference maps most flags to camel-cased JSON keys. One documented naming difference is that the command-line debug option is represented as printDebugMessages in configuration.

{
  "proxy": "192.168.1.42:8080",
  "proxyType": "http",
  "proxyAuth": "username:password",
  "printDebugMessages": true,
  "remoteDebuggerPort": 9000
}
phantomjs --config=/path/to/config.json script.js

Keep the file readable only by the account that needs it, and avoid committing it when it contains a password. The configuration file is convenient for CI and bug reports because the effective settings are explicit.

Build a diagnostic script that produces evidence

Start with a small script that records JavaScript errors, requests, responses, and timeouts. Set page settings before the first page.open; the documented settings apply during that initial navigation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
var page = require('webpage').create();
var system = require('system');

page.settings.resourceTimeout = 30000;
page.settings.userAgent = 'PhantomJS-debug/2.1.1';

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

page.onResourceRequested = function (request) {
  console.log('[request] ' + JSON.stringify(request));
};

page.onResourceReceived = function (response) {
  if (response.stage === 'end') {
    console.log('[response] ' + response.status + ' ' + response.url);
  }
};

page.onResourceTimeout = function (request) {
  console.log('[timeout] ' + JSON.stringify(request));
};

page.open('https://example.com', function (status) {
  console.log('[open] ' + status);
  phantom.exit(status === 'success' ? 0 : 1);
});

onError exposes the message and file/line stack for page JavaScript. The request callback shows what PhantomJS attempted to fetch; the response callback supplies status information when a response completes; and the timeout callback identifies a resource that exceeded resourceTimeout, which is measured in milliseconds. Keep the URL, timeout, user agent, proxy mode, and PhantomJS version with the captured output.

Turn on PhantomJS’s own diagnostics

phantomjs --debug=true script.js
phantomjs --debug=yes script.js

Use these switches for a first pass, then narrow the output with the callbacks above. Very verbose logging can obscure ordering in parallel requests, so disable it for a normal run once the failure is understood.

A repeatable proxy-debugging workflow

  1. Confirm the binary. Run phantomjs --version and note the full path and platform.
  2. Run without a proxy. Use --proxy-type=none. If the page now works, the proxy path or inherited proxy settings are implicated.
  3. Run through the intended proxy. Add the address, type, and authentication one at a time. Compare request, response, timeout, and page-error output with the control run.
  4. Separate navigation from page code. A successful page.open followed by a page error points to JavaScript; a timeout or failed status points to loading, DNS, TLS, or proxy handling.
  5. Check the target outside PhantomJS. Use a modern browser or an independent HTTP client from the same host and proxy. This shows whether the endpoint itself is reachable without relying on PhantomJS’s old WebKit stack.
  6. Capture the environment. Save the PhantomJS version, operating system, command line or JSON configuration, URL, user agent, timeout, and relevant callback logs.

Use the built-in remote debugger

PhantomJS includes a WebKit inspector. Start a script with a listening port:

phantomjs --remote-debugger-port=9000 script.js

Open http://127.0.0.1:9000/ in Safari, Chrome, or Chromium, select the script/page entry, and run __run() in the console. To begin execution as soon as the inspector attaches, add:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
phantomjs --remote-debugger-port=9000 --remote-debugger-autorun=yes script.js

Inspect code inside the target page

There are two execution contexts: the outer PhantomJS script and the page loaded by page.open. To stop inside page JavaScript, put debugger; in the outer script, pause it in the first inspector, and call:

page.evaluateAsync(function () {
  debugger;
});

Continue from the first inspector, then select the page context in the second inspector window. This two-inspector procedure prevents you from mistaking a breakpoint in your PhantomJS controller for a breakpoint in the loaded site.

Why HTTPS fails when HTTP works

When an HTTP URL succeeds but an HTTPS URL fails, do not assume that the proxy password is wrong. PhantomJS’s SSL behavior depends on the system OpenSSL library and its supported protocol set. The command-line controls relevant to this investigation are:

  • --ssl-protocol, whose accepted values depend on the OpenSSL build;
  • --ssl-certificates-path, for pointing PhantomJS at a certificate bundle when trust configuration is the issue.

Run the same URL with --proxy-type=none and with the proxy. If both modes fail identically, investigate certificate trust, protocol support, hostname validation, or the destination. If only the proxied run fails, inspect proxy CONNECT handling and the proxy’s certificate substitution.

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

Inspect encrypted traffic in a controlled test

The PhantomJS IPC documentation describes routing traffic through an HTTPS interception proxy such as mitmproxy or Fiddler. Install an interception certificate only in an isolated test environment, never on a production workstation by default. When the proxy presents a trusted test certificate, verify that the certificate bundle supplied through --ssl-certificates-path is the one PhantomJS is actually using.

Do not misdiagnose cross-domain restrictions

PhantomJS scripts commonly begin in file:// scope. Cross-domain requests are restricted by default, so a blocked XHR can look like a proxy outage even when the proxy is healthy. Check the page’s CORS response headers and record these settings:

  • webSecurityEnabled, which affects WebKit security checks;
  • localToRemoteUrlAccessEnabled, which affects access from local files to remote URLs;
  • userAgent, which can change server-side routing and bot responses.

Change one setting at a time, document the change, and avoid weakening web security in a production workflow merely to make a test pass.

Direct PhantomJS versus Selenium-managed execution

Diagnostic concern Direct PhantomJS Selenium-managed run
Where the proxy is applied Process flags or the PhantomJS JSON configuration. Driver capabilities or Selenium-specific configuration; exact behavior depends on the driver and version.
Raw network evidence Page request, response, timeout, and error callbacks are in the script. Availability and shape of network logs depend on the Selenium driver and integration.
Inspector access --remote-debugger-port exposes the built-in WebKit inspector. Inspector forwarding and debugging controls depend on the Selenium stack.
Credential exposure --proxy-auth places credentials in process configuration; protect them. Credential handling depends on the driver, capability transport, and deployment.
Modern web compatibility Constrained by the archived PhantomJS 2.1.1-era engine and SSL libraries. Depends on the browser and driver selected, so verify the exact versions.

Direct execution is usually the shortest path when the question is “what did PhantomJS request, and which proxy did it use?” Selenium is an orchestration layer, not a prerequisite for these PhantomJS controls.

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.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshooting matrix

Symptom Likely cause Fix or next test
Every request is unexpectedly slow on Windows. Default or inherited proxy settings. Run with --proxy-type=none. If latency disappears, configure the intended proxy explicitly or remove the inherited setting.
HTTP succeeds; HTTPS times out or reports a handshake error. Legacy OpenSSL protocol support, certificate trust, or proxy CONNECT handling. Compare direct and proxied runs, inspect SSL settings, and test with a controlled interception proxy and the correct certificate path.
Authentication fails immediately. Incorrect address:port, unsupported proxy authentication flow, or credentials exposed with shell quoting issues. Verify the endpoint independently, pass --proxy-auth=username:password exactly as documented, and protect the command from shell history.
page.open returns success but the page is incomplete. Late resources, JavaScript errors, or a resource timeout. Use onError, request/response callbacks, and onResourceTimeout; increase resourceTimeout only after identifying the slow resource.
No network request appears for an XHR. Cross-domain restrictions or page code never issuing the request. Check CORS headers, webSecurityEnabled, localToRemoteUrlAccessEnabled, and page JavaScript errors.
The remote inspector page is empty. The process is not listening on the expected interface/port, or the script exited before attachment. Keep the process alive, verify --remote-debugger-port=9000, browse to http://127.0.0.1:9000/, and use --remote-debugger-autorun=yes when appropriate.
Two machines show different results. Different PhantomJS binaries, OpenSSL libraries, certificates, user agents, or proxy paths. Compare version, platform, settings, certificate path, command line, and callback logs before changing application code.

Or skip the browser setup

If your actual requirement is a dependable screenshot or PDF of a URL rather than diagnosing a legacy PhantomJS session, ScreenshotNeo makes one GET request and returns a PNG, JPEG, WebP, or PDF. It accepts consent banners as a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture. Only clean shots are billed: bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and each response identifies the result with X-Page-Verdict and X-Billed headers.

See the complete parameter reference in the ScreenshotNeo documentation. A minimal request is:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
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)
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 also provides an MCP server with take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. Every plan includes features such as full-page and element capture, device and retina settings, custom CSS and JavaScript, waits, request blocking, cookies and headers, geolocation, PDF controls, caching, signed links, asynchronous webhooks, bulk capture, and a usage API. The Free plan includes 1,000 screenshots each month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account to try it.

Frequently Asked Questions

Can a remote debugger session replace request callbacks?

No. The inspector is useful for interactive breakpoints and console inspection, while request, response, timeout, and page-error callbacks provide repeatable evidence suitable for logs and bug reports.

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

Why should the PhantomJS version be included in every ticket?

PhantomJS is archived and its behavior depends on the exact binary, platform, and linked SSL libraries. A version number lets another person reproduce the same legacy runtime instead of silently testing a different build.

Is changing web security a proxy fix?

Not by itself. Security settings affect cross-domain access from page code; they do not repair a failed proxy connection, TLS handshake, or certificate trust chain.

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.