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

Set page.settings.resourceTimeout before page.open(), then handle page.onResourceTimeout to simulate a network-resource timeout. Use the page.open callback for the overall navigation result, and add an outer watchdog when you need to stop a script that never returns. A local endpoint that deliberately delays its response makes the test repeatable.

Choose the timeout you actually need to test

PhantomJS exposes several different failure boundaries. They produce different signals and require different cleanup, so do not use a resource timeout when your test is really about a JavaScript loop.

Scenario Control Observable result Typical cleanup
One HTTP resource takes too long page.settings.resourceTimeout onResourceTimeout receives request metadata The timed-out request stops; other page activity may continue
Navigation does not complete successfully page.open() callback Status is success or fail Record the status and exit or continue with your harness
Page JavaScript or the harness hangs Outer setTimeout watchdog Your watchdog expires Optionally stop page JavaScript, then call phantom.exit()

The official WebPage settings reference defines resourceTimeout in milliseconds. When the limit is reached, PhantomJS stops trying that resource and invokes onResourceTimeout. Settings must be in place for the initial page.open call; changing them afterward does not retroactively change that navigation.

Simulate a network-resource timeout

1. Create a deliberately slow fixture

Run a local test endpoint such as http://127.0.0.1:8080/delay that waits longer than the threshold before sending its response. For example, configure the fixture to delay for five seconds and test with a one-second limit. The path is your own fixture, not a URL supplied by PhantomJS. Keeping it local avoids an external site changing behavior while your test runs.

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

2. Configure the page before navigation

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

page.settings.resourceTimeout = 1000; // milliseconds

page.onResourceTimeout = function (request) {
  console.log('Timed out: ' + JSON.stringify(request));
};

page.open('http://127.0.0.1:8080/delay', function (status) {
  console.log('Page status: ' + status); // success or fail
  phantom.exit();
});

Save this as timeout.js and run it with the PhantomJS executable used by your project:

phantomjs timeout.js

When the delayed request crosses 1,000 milliseconds, the handler should print a JSON object and the open callback should eventually report the page-level outcome. The request object documented by PhantomJS includes an id, HTTP method, URL, request time, headers, error code, and error string. Log those fields in automated tests so a failure identifies the exact resource, rather than merely saying that navigation failed.

3. Assert both signals

A robust test records a boolean when onResourceTimeout runs and separately records the page.open status. The first assertion proves that a resource exceeded the configured threshold; the second captures what the page load as a whole reported. Do not treat a successful page status as proof that no resource timed out, or a failed page status as proof of which request was slow.

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

page.settings.resourceTimeout = 1000;
page.onResourceTimeout = function (request) {
  resourceTimedOut = true;
  console.log('timeout url=' + request.url);
  console.log('error code=' + request.errorCode + ' message=' + request.errorString);
};

page.open('http://127.0.0.1:8080/delay', function (status) {
  console.log('status=' + status);
  if (!resourceTimedOut) {
    console.log('Expected a resource timeout but none occurred');
  }
  phantom.exit();
});

Understand the page-level result

The callback passed to page.open receives a status string, documented as success or fail, after the load attempt. This is a navigation outcome, not a millisecond timer that you can use to interrupt arbitrary JavaScript. A page can contain several resources; one may time out while the browser continues processing others, and the final status reflects the load attempt as a whole.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #2
Sale
HTML and CSS: Design and Build Websites
  • HTML CSS Design and Build Web Sites
  • Comes with secure packaging
  • It can be a gift option

If your test needs a deterministic pass/fail decision, define it explicitly: require the expected request URL to appear in the timeout handler, then check whether the final status is the one your fixture is intended to produce. Include the configured timeout and fixture delay in test output so a future maintainer can tell whether a change altered the test conditions.

Stop a script that never finishes

Use an outer watchdog

A resource timeout does not guarantee that page JavaScript will return. Wrap the operation in a harness timer and always arrange an exit path.

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

page.open('http://127.0.0.1:8080/hang', function (status) {
  finished = true;
  console.log('status=' + status);
});

setTimeout(function () {
  if (!finished) {
    console.log('Harness timeout');
    // If your PhantomJS build supports it, stop the page script here.
    // page.stopJavaScript();
  }
  phantom.exit();
}, 3000);

The watchdog measures three seconds from scheduling, not “three seconds after the network timeout.” Choose a value that allows the expected callbacks to run but still bounds a runaway test. Calling phantom.exit() is essential; without it, open timers or page activity can keep the PhantomJS process alive.

About page.stopJavaScript()

Some PhantomJS builds expose page.stopJavaScript(), and a historical PhantomJS issue demonstrates using it from a watchdog around long-running page code. Because that behavior is discussed as an issue rather than guaranteed as a modern compatibility contract, validate it against the exact PhantomJS build in your project. Keep the watchdog and explicit process exit even when the method is available.

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

Build repeatable timeout tests

  • Control the delay: Make the fixture delay comfortably longer than the configured threshold. There is no universal timeout value recommended by the official references.
  • Set settings per navigation: Assign resourceTimeout before every page.open whose behavior you are testing.
  • Capture evidence: Save URL, method, request time, error code, and error string from the timeout object.
  • Separate scopes: Use a resource test for network behavior, an open callback assertion for navigation, and a watchdog test for script hangs.
  • Clean up on every branch: Call phantom.exit() after success, failure, or watchdog expiry.
  • Use local networking: Bind the fixture to loopback and choose a unique path for each scenario, such as /delay and /hang.

Troubleshoot common failures

The timeout handler never fires

Check that the setting is assigned before page.open, that the delayed endpoint really exceeds the threshold, and that the request is a network resource rather than a JavaScript loop. Also verify that the URL is reachable from the machine running PhantomJS and that the fixture is not returning a cached response.

The callback says fail, but no request details appear

fail is only the page-level status. It does not identify a timed-out resource. Add onResourceTimeout and log the request object; investigate other load errors separately.

The process stays alive

Look for missing phantom.exit(), repeating timers, or a watchdog that only logs a message. Put the exit call in the final callback and in the watchdog branch. If you call page.stopJavaScript(), still exit the process afterward.

The watchdog exits too early

Increase the watchdog interval enough for the fixture and expected callbacks, and print elapsed time with Date.now(). The official quick-start guidance uses elapsed-time measurement to make timing visible; it does not prescribe a universal duration.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #4
Sale
Web Design with HTML, CSS, JavaScript and jQuery Set
  • Brand: Wiley
  • Set of 2 Volumes
  • A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers

page.stopJavaScript() has no effect

Treat it as build-dependent. Confirm the PhantomJS version and test the method with a minimal fixture. Keep the outer process watchdog as the reliable last line of defense.

Or skip the browser setup

If your goal is a clean image or PDF rather than testing PhantomJS’s timeout callbacks, ScreenshotNeo provides a single screenshot API request. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; bot checks, blank pages, timeouts, failed loads, and cache hits are not billed. Its MCP server lets Claude, Cursor, and other MCP clients call take_screenshot, get_page_info, and capture_pdf. The Free plan includes 1,000 shots per month without a card, and paid plans start at $5 for 3,000 shots.

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)

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

See the ScreenshotNeo API documentation for options such as full-page capture, device and viewport settings, waiting rules, custom headers, cookies, blocking, PDF output, caching TTLs, async webhooks, and bulk capture. Start with 1,000 free screenshots per month with no card.

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

Performance, reliability, and cost considerations

Short resource thresholds make tests fail quickly but can classify a legitimately slow local service as a timeout. Longer thresholds reduce false positives but make a hung test consume more time, which is why the watchdog should be independent. Run fixtures on the same host or controlled network when you are testing PhantomJS behavior, and report the exact millisecond values in test logs.

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

PhantomJS’s timeout controls are legacy WebPage APIs. The official references document the callbacks and settings, but they do not promise compatibility with a modern browser engine. Validate every snippet against the PhantomJS build you deploy, especially watchdog behavior and page.stopJavaScript().

Frequently Asked Questions

Can I trigger onResourceTimeout without waiting on a public website?

Yes. Use a local endpoint you control, such as 127.0.0.1:8080/delay, and delay its response beyond the configured millisecond threshold.

Does resourceTimeout stop all page activity?

It stops trying the timed-out resource. The page may continue processing other resources, so use the navigation callback and an outer watchdog when you need a complete operation boundary.

What should a timeout test assert?

Assert that the expected request appears in onResourceTimeout, then separately record the page.open status and ensure the harness exits.

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.

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.