Crashes, 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 minutePC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Use page.injectJs() for a JavaScript file stored on the PhantomJS machine. page.includeJs(url, callback) is the asynchronous loader for a script available at a URL that the page can reach. Open the page first, inject the local file, check the Boolean result, and only then run page.evaluate(). Keep phantom.exit() inside an includeJs() callback when you load a remote library.
The short answer: includeJs is for URLs, injectJs is for local files
page.includeJs() and page.injectJs() both put JavaScript into the page context, but they read from different places:
| Method | Source | Completion signal | When to use it |
|---|---|---|---|
page.includeJs(url, callback) |
A URL that the loaded page can reach, normally an HTTP(S) location | The callback runs after the load attempt completes | A CDN or other remotely hosted library |
page.injectJs(filename) |
A file on the PhantomJS host | A synchronous Boolean: true or false |
A script bundled with your PhantomJS program or present on the machine |
Therefore, this commonly failing call is using the wrong API for its source:
page.includeJs('assets/javascript/jquery.min.js', callback);
The relative path is a filesystem path on the host, not a URL automatically readable by the remote page. Replace it with page.injectJs(), preferably with an absolute filename when the launch directory is not fixed.
#1 Best Overall
Load a local file with injectJs()
This complete script opens a page, injects a local library, verifies the Boolean result, calls page code, and exits only after that work is finished.
var page = require('webpage').create();
page.open('https://example.com', function (status) {
if (status !== 'success') {
console.log('Unable to access network');
phantom.exit();
return;
}
// Use an absolute path if the process may start in different directories.
var loaded = page.injectJs('/opt/my-app/assets/javascript/jquery.min.js');
if (!loaded) {
console.log('Local script could not be injected');
phantom.exit();
return;
}
var result = page.evaluate(function () {
return typeof window.jQuery;
});
console.log(result);
phantom.exit();
});
When successful, the example prints function (assuming that file defines window.jQuery). The function passed to evaluate() runs in the page, not in PhantomJS’s outer script, so access browser globals such as window there.
Use a deliberate relative-path setup
injectJs() resolves a relative filename from the current directory and then from phantom.libraryPath. A path that works from an interactive shell can fail when a scheduler, service, or different wrapper starts PhantomJS elsewhere. You have two reliable choices:
- Build or pass an absolute path, as in the example.
- Put the file where the current directory or configured
phantom.libraryPathlookup will find it, and set that library path deliberately when the launch directory varies.
Do not treat a relative path as relative to the JavaScript file itself unless your launch setup makes those directories identical.
Rank #2
Check the Boolean before using the library
The documented return value is true when injection succeeds and false when it does not. A true result confirms that PhantomJS injected the file; it does not prove that the file exposed the global name you expected. Verify the API you need inside page.evaluate(), and stop instead of continuing with a missing dependency.
Use includeJs() when the library is remote
If the file is hosted at a URL reachable by the page, use the URL-oriented API and wait for its callback:
var page = require('webpage').create();
page.open('https://example.com', function (status) {
if (status !== 'success') {
console.log('Unable to access network');
phantom.exit();
return;
}
page.includeJs('https://cdn.example.com/library.min.js', function () {
var value = page.evaluate(function () {
return typeof window.Library;
});
console.log(value);
phantom.exit();
});
});
The callback is the boundary at which your code should use the remotely loaded library. Calling phantom.exit() immediately after starting includeJs() can terminate PhantomJS before the request and script execution finish. Keep the exit call inside that callback, after any evaluation or output.
How path resolution and page context differ
Host filesystem versus hosted page
PhantomJS has a host filesystem, while the page has a browser-like origin and network access. A file such as assets/javascript/jquery.min.js exists on the host. includeJs() asks the page to load a URL; it does not reinterpret that host path as a file to read. injectJs() is specifically documented as the file-based counterpart whose file does not need to be accessible from the hosted page.
Free tools Windows power users keep installed
One-click scans. No signup required.
Current directory is part of the result
For injectJs('assets/javascript/jquery.min.js'), first establish the process working directory and then check the file’s spelling and permissions. If a launcher changes directories, the same command can resolve a different location. An absolute filename removes that ambiguity; otherwise configure phantom.libraryPath intentionally.
Evaluation runs after injection
Put DOM and library calls in page.evaluate() after a successful injection. That function crosses into the page context and returns simple serializable values. Return a string, number, Boolean, or plain data structure rather than a DOM node, function, or complex browser object.
A repeatable local-script procedure
- Open the target. Call
page.open()and inspect its status. Do not inject into a page that failed to load. - Select the source-specific API. Use
injectJs(filename)for a host-local file; reserveincludeJs(url, callback)for a URL. - Make the path deterministic. Prefer an absolute filename when the launch directory can change, or set
phantom.libraryPathand place the file accordingly. - Check completion. Test the Boolean returned by
injectJs(). ForincludeJs(), put dependent code in its callback. - Verify the expected global. Use
page.evaluate()to check the library symbol or run the required browser operation. - Exit last. Call
phantom.exit()after injection, evaluation, logging, and any callback work.
Troubleshoot the usual failures
| Symptom | Likely cause | Fix |
|---|---|---|
injectJs() returns false |
The file is not at the resolved path, the working directory differs, or the process cannot read it. | Print or establish the absolute path, check the file exists and is readable, or configure phantom.libraryPath. Stop before calling the library. |
includeJs('assets/...') cannot load a local file |
A filesystem path was supplied to a URL-oriented loader. | Use page.injectJs() for the host file, or publish the script at a page-reachable URL and pass that URL to includeJs(). |
| The script appears to load, but the global is undefined | The wrong file was selected, the expected symbol differs, or page code ran before the load completed. | Check the Boolean or wait for the include callback, then return typeof window.ExpectedName from page.evaluate() to identify the actual result. |
| The program exits before a remote library is usable | phantom.exit() was called immediately after includeJs(). |
Move phantom.exit() into the includeJs() callback after evaluation and output. |
DOM code throws outside evaluate() |
Host-side PhantomJS code and page-side JavaScript were mixed. | Wrap browser globals, selectors, and library calls in page.evaluate(), and return only serializable data. |
| A relative path works manually but not in automation | The launcher starts PhantomJS with another current directory. | Use an absolute filename or set phantom.libraryPath as part of the launch configuration. |
| The page never reaches the injection step | page.open() returned a status other than success. |
Handle the failed status, report the network problem, exit, and investigate the target URL separately. |
Reliability and maintainability considerations
Keep local dependencies with the script
A local file avoids a second network request and makes the dependency available even when a CDN is unavailable. It also means deployment must copy the file to the expected host path. Treat that path as configuration, not as an assumption about whoever launches PhantomJS.
Keep remote dependencies asynchronous
A remote include depends on the page being able to reach the URL and on the callback being allowed to run. Put all dependent work in that callback and preserve a failure path for the initial page open. This makes the order explicit and prevents premature process termination.
Rank #4
Verify behavior, not just loading
A successful file read is not the same as a successful integration. Check the symbol, call a small library operation, or return a targeted DOM value. Since evaluate() serializes its result, design the check around simple values that can be logged and inspected.
Or skip the browser setup
If your actual goal is to obtain a clean screenshot rather than execute a local PhantomJS library, ScreenshotNeo provides a website screenshot API and MCP server. It accepts one GET request and returns PNG, JPEG, WebP, or PDF. Before capture it accepts cookie and consent banners like a visitor 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 response headers identify the page verdict and billing status.
Here is the one-call cURL form (the ScreenshotNeo documentation has the complete option reference):
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
The same request in 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)
And in 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}`);
- An MCP server exposes
take_screenshot,get_page_info, andcapture_pdfto Claude, Cursor, and other MCP clients. - There are 63 options, including full-page lazy-image loading, CSS-selector element capture, dark mode, device presets, arbitrary viewports, retina scale, PDF paper and page-range controls, custom CSS and JavaScript, clicks, selector waits, network-idle waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparency, resizing, chosen cache TTLs, signed image links, asynchronous webhooks, bulk capture for 100 URLs per call, usage data, and an OpenAPI specification.
- Every plan includes every feature. The Free plan provides 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. Yearly billing gives two months free.
Create a free ScreenshotNeo account to use the 1,000 monthly screenshots without a card.
FAQ
Does a true result from injectJs() mean the library API is ready?
It means PhantomJS injected the file successfully. Still verify the expected global or a small operation in page.evaluate(); the filename may contain different code from the symbol your page expects.
Best Value
Why should my evaluation return simple values?
page.evaluate() crosses from the page context back to PhantomJS and returns serializable data. Return text, numbers, Booleans, or plain objects designed for serialization rather than DOM nodes or functions.
Where should phantom.exit() go with includeJs()?
Put it inside the includeJs() callback, after the library-dependent evaluation and logging. Exiting earlier can stop the asynchronous load before it completes.
Frequently Asked Questions
Can injectJs() load a file from a URL?
No. Use injectJs() for a file on the PhantomJS host and includeJs(url, callback) for a page-reachable URL.
What is the safest path choice in a scheduled job?
Use an absolute filename, or set phantom.libraryPath explicitly so the result does not depend on the scheduler’s working directory.
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.




