Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →There are two different jobs people call “using an external script with PhantomJS Node.” To run a standalone PhantomJS file, Node.js starts the PhantomJS executable as a child process and passes the script path and arguments. To add code to a page that PhantomJS already controls, use page.includeJs() for a remote URL or page.injectJs() for a local file. The examples below show both paths, how to pass data safely, how to detect failures, and when to stop using this legacy stack.
First choose the operation you actually need
Keep the execution contexts separate. A Node child process runs PhantomJS as a second program; the JavaScript in that file executes in PhantomJS. By contrast, includeJs and injectJs put code into the web page context, where it can access that page’s DOM and browser APIs. Neither mechanism turns Node source into page code.
| Need | Use | Where code runs | Completion signal |
|---|---|---|---|
| Run a PhantomJS file from a Node application | Node child_process.execFile() with the PhantomJS binary |
Separate PhantomJS process | Node callback, stdout/stderr, and process exit |
| Load a hosted script into a page | page.includeJs(url, callback) |
Page context | Callback after the load attempt |
| Load a local file into a page | page.injectJs(filename) |
Page context | Boolean return value (true or false) |
The command-line documentation covered here is for PhantomJS 2.1.1. PhantomJS 2.1 is described as the latest stable release, and project development is suspended. The old phantomjs-node repository is archived (December 4, 2019) and says development was suspended because PhantomJS support was lacking. Current Node releases, operating systems, TLS stacks, and modern sites are not established by those documents, so treat every example as a legacy pattern and validate it in your own environment.
Run a standalone PhantomJS script from Node.js
1. Install or locate a PhantomJS binary
The phantomjs-prebuilt npm wrapper exposes the installed executable through its path property. Its README demonstrates passing that path to Node’s process API. Because the wrapper and PhantomJS are old, check that installation succeeds on the Node version and operating system you intend to deploy.
#1 Best Overall
2. Create the PhantomJS script
Save this as phantom-script.js. PhantomJS receives command-line values through its system arguments API. The first user value is at index 1 (index 0 is the script name). Always end a standalone script with phantom.exit(); otherwise PhantomJS can remain running.
var system = require('system');
if (system.args.length < 2) {
console.error('Usage: phantomjs phantom-script.js URL');
phantom.exit(2);
}
var targetUrl = system.args[1];
var page = require('webpage').create();
page.open(targetUrl, function (status) {
if (status !== 'success') {
console.error('Could not open ' + targetUrl);
phantom.exit(1);
return;
}
console.log(JSON.stringify({
title: page.title,
url: targetUrl
}));
phantom.exit(0);
});
Use a simple, serializable argument such as a URL. If you need several values, pass each as its own process argument rather than concatenating a shell command.
3. Launch it with execFile
Put this Node file beside the PhantomJS script. execFile avoids shell parsing, so spaces and shell metacharacters in arguments are not interpreted as command syntax.
const path = require('path');
const { execFile } = require('child_process');
const phantomjs = require('phantomjs-prebuilt');
const script = path.join(__dirname, 'phantom-script.js');
const targetUrl = process.argv[2] || 'https://example.com';
execFile(
phantomjs.path,
[script, targetUrl],
{ maxBuffer: 1024 * 1024 },
(err, stdout, stderr) => {
if (stdout) process.stdout.write(stdout);
if (stderr) process.stderr.write(stderr);
if (err) {
console.error('PhantomJS failed:', err.message);
if (typeof err.code !== 'undefined') {
console.error('Exit code:', err.code);
}
process.exitCode = 1;
return;
}
console.log('PhantomJS completed successfully.');
}
);
Run it with node run-phantom.js https://example.com. The callback receives an error for a failure to start or a non-zero exit, while captured output is available in stdout and stderr. Set maxBuffer high enough for the output your page can generate; otherwise Node can terminate the child when the buffer is exceeded.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Streaming output and explicit exit handling
For long-running scripts or verbose logs, the wrapper also documents a convenience phantomjs.exec(...) interface that exposes output streams and an exit event. With raw Node APIs, use spawn when you need incremental output:
const path = require('path');
const { spawn } = require('child_process');
const phantomjs = require('phantomjs-prebuilt');
const child = spawn(phantomjs.path, [
path.join(__dirname, 'phantom-script.js'),
'https://example.com'
]);
child.stdout.on('data', data => process.stdout.write(data));
child.stderr.on('data', data => process.stderr.write(data));
child.on('error', error => console.error('Could not start PhantomJS:', error));
child.on('close', code => {
if (code !== 0) process.exitCode = code || 1;
});
Pass arguments reliably between Node and PhantomJS
Use one argument per value
Build an array such as [script, url, outputFile, mode]. Do not assemble a string like phantomjs script.js "..." and send it to a shell. Separate arguments preserve spaces and reduce quoting and injection mistakes.
Rank #2
Validate at the PhantomJS boundary
Check system.args.length, reject missing values, and return a non-zero exit code with phantom.exit(number) when input is invalid. Keep secrets out of command-line arguments when possible: process listings and CI logs can expose them.
Remember the process boundary
Node objects, functions, and closures do not automatically cross into PhantomJS. Serialize data to text (for example, JSON) and parse it inside the PhantomJS script. The same rule applies to page evaluation: values crossing page.evaluate must be simple serializable values; functions, closures, and DOM nodes cannot cross that boundary.
Load an external script into a PhantomJS page
Remote URL: page.includeJs(url, callback)
Use this when the script is hosted at a URL. PhantomJS loads and executes it in the page, then invokes your callback after the load attempt.
var webpage = require('webpage');
var page = webpage.create();
page.open('https://example.com', function (status) {
if (status !== 'success') {
console.error('Page failed to open');
phantom.exit(1);
return;
}
page.includeJs('https://cdn.example.com/library.js', function () {
var result = page.evaluate(function () {
return typeof window.LibraryName !== 'undefined';
});
console.log('Library available:', result);
phantom.exit(result ? 0 : 1);
});
});
The callback is the point at which you should interact with the loaded library. A callback does not prove that every function in the library behaved correctly; add page-side checks and an explicit exit status.
Local file: page.injectJs(filename)
Use this when the code is on the machine running PhantomJS. The file does not have to be reachable by the hosted page. If it is not in the current directory, PhantomJS also searches its libraryPath. The method returns true when injection succeeds and false otherwise.
var webpage = require('webpage');
var page = webpage.create();
page.open('https://example.com', function (status) {
if (status !== 'success') {
phantom.exit(1);
return;
}
var loaded = page.injectJs('/absolute/path/to/page-helper.js');
if (!loaded) {
console.error('Local script injection failed');
phantom.exit(1);
return;
}
var answer = page.evaluate(function () {
return window.pageHelper ? window.pageHelper() : null;
});
console.log(JSON.stringify(answer));
phantom.exit(0);
});
When to choose each page API
- Choose
includeJsfor a script that is intentionally served by a remote host and should load as page content. - Choose
injectJsfor a local helper, test harness, or script that must not be published at a URL. - Choose Node’s child process API when the “external script” is actually a complete PhantomJS program, not page code.
These APIs are not interchangeable: execFile starts another operating-system process, while includeJs and injectJs modify the page controlled by an already-running PhantomJS process.
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallCrashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteRank #3
Common failures and fixes
“phantomjs: command not found” or a missing binary
Use the wrapper’s phantomjs.path instead of assuming a global executable. Log that path and verify the file is executable. On a deployment host, confirm the downloaded binary is permitted by its OS and architecture.
Node reports an ENOENT error
The executable or script path is wrong. Resolve the script with path.join(__dirname, ...), print both paths, and check the working directory. A relative path based on the caller’s current directory can fail under a process manager.
The child exits immediately with code 1
Read stderr. Typical causes are a syntax error, missing argument, page-open failure, or a PhantomJS-side exception. Return explicit non-zero codes for those branches so Node can distinguish failure from success.
The process never exits
Ensure every asynchronous branch reaches phantom.exit(), including page-open and script-load failures. A pending timer, request, or event handler can also keep the process alive; remove it or close the page before exiting.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
includeJs callback runs but the library is absent
Check the URL, network access, TLS compatibility, redirects, and the page’s console output. Test for the expected global inside page.evaluate rather than assuming a callback means the library initialized successfully.
injectJs returns false
Use an absolute filename or configure libraryPath. Confirm read permissions and that the file exists on the machine running PhantomJS, not merely on the Node development machine.
Modern sites render blank or incorrectly
PhantomJS uses an old browser engine. Its project development is suspended, and the cited material does not establish compatibility with current JavaScript, certificates, or websites. If a site requires modern browser features, migrate to a maintained browser automation tool rather than adding fragile patches.
Operational guidance for a legacy integration
Reliability
- Set a Node-side timeout and terminate a child that exceeds your service’s deadline.
- Capture both stdout and stderr, and include the exit code in logs.
- Make scripts idempotent: a retry should not duplicate an upload or other side effect.
- Pin the wrapper and binary version in deployment, then test the exact target OS.
Security
- Pass arguments as an array to
execFileorspawn; do not interpolate untrusted input into a shell command. - Validate allowed URL schemes and hosts before opening user-supplied URLs.
- Do not print cookies, authorization headers, or API keys to captured output.
Performance and cost
Each child process has startup and memory overhead. Reuse is not straightforward with standalone PhantomJS scripts, so measure queueing and concurrency on your own host. The supplied PhantomJS documentation provides no current performance benchmark or compatibility matrix; avoid promising throughput based on the examples alone.
Or skip the browser setup
If your goal is simply to obtain a clean screenshot or PDF rather than maintain a PhantomJS runtime, ScreenshotNeo provides a one-request API and an MCP server for AI agents. Before capture it accepts cookie/consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the page and billing result with X-Page-Verdict and X-Billed headers.
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}`);
const body = Buffer.from(await res.arrayBuffer());
require('fs').writeFileSync('shot.webp', body);
cURL
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)
open("shot.webp", "wb").write(r.content)
See the ScreenshotNeo API documentation for the full option set: full-page and element captures, lazy-image loading, dark mode, device presets and custom viewports, retina scale, PDF paper and page controls, custom CSS and JavaScript, clicks, waits, request blocking, headers, cookies, user agents, authorization, timezone and geolocation, transparent backgrounds, resizing, chosen cache TTLs, signed image links, asynchronous webhooks, bulk capture of up to 100 URLs per call, usage reporting, and the OpenAPI specification. Existing parameter names used by other screenshot APIs also work, which can simplify migration.
An MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients. Every plan includes every feature: 1,000 screenshots per month are free with no card; paid plans start at $5 for 3,000 screenshots. Create a free ScreenshotNeo account to get the 1,000 monthly screenshots.
Frequently asked questions
Can Node require a PhantomJS script directly?
No. The established pattern is to launch the PhantomJS executable as a child process and pass the script filename as an argument.
Does includeJs load a local file?
Use injectJs for a local file. includeJs is for a URL.
Why is this guidance labeled legacy?
PhantomJS development is suspended, and the related Node repository is archived. Current runtime and website compatibility must be verified by you.
What crosses a page.evaluate boundary?
Simple serializable values cross reliably; functions, closures, and DOM nodes do not.
Frequently Asked Questions
Can Node require a PhantomJS script directly?
No. Launch the PhantomJS executable as a child process and pass the script filename as an argument.
Free tools Windows power users keep installed
One-click scans. No signup required.
Does includeJs load a local file?
No. Use injectJs for local files; includeJs accepts a URL.
Why is PhantomJS guidance considered legacy?
PhantomJS development is suspended and the related Node repository is archived, so current compatibility is not established.
What values can cross page.evaluate?
Simple serializable values; functions, closures, and DOM nodes do not cross the boundary.
Quick Recap
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.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Clear out junk files and repair common Windows errors3Scan for outdated or missing drivers - takes under a minute

