PhantomJS screenshot timeout error: how to increase the wait time
Fix PhantomJS screenshot timeouts by identifying what expired: a resource, the wrapper request, or the wait before capture.
To increase PhantomJS’s wait time, first identify which timeout expired. Set page.settings.resourceTimeout in milliseconds before the first page.open() to give each requested resource more time. If the page loads but JavaScript-driven content is not ready, add a separate wait before page.render(). If a wrapper or caller aborts the job, change that tool’s own request timeout. These controls have different units and effects.
The native resource timeout does not extend a wrapper’s overall deadline or guarantee that asynchronously rendered content is ready. Check the exact error and logs before increasing a value.
1. Identify which timeout expired
| Timeout | What it limits | Unit and start | What happens at expiry |
|---|---|---|---|
page.settings.resourceTimeout |
An individual requested resource | Milliseconds; starts for a resource request | That resource stops trying and the page proceeds with other work |
| Post-load wait | Time before the screenshot is rendered | Chosen delay after page load; commonly milliseconds in wrapper examples | The capture happens later; this does not extend a resource request |
| Wrapper or caller timeout | The complete screenshot job or request | Depends on the wrapper; may be seconds | The wrapper or caller aborts the job |
The option name timeout is not consistent across wrappers. For example, the documented screenshot-stream option is a request timeout in seconds with a 60-second default, while url-to-screenshot documents a post-load delay in milliseconds with a default of 0 ms. Verify the package and version you use before copying a setting. See the PhantomJS WebPage API and the wrapper documentation for screenshot-stream and url-to-screenshot.
2. Increase the native PhantomJS resource timeout
Set page.settings.resourceTimeout before the initial page.open(). Its value is in milliseconds. Attach page.onResourceTimeout to learn which request hit the limit.
var page = require('webpage').create();
// Per-resource timeout, in milliseconds. Set before page.open().
page.settings.resourceTimeout = 30000;
page.onResourceTimeout = function (request) {
console.log('Resource timed out: ' + JSON.stringify(request));
};
page.open('https://example.com/', function (status) {
if (status !== 'success') {
console.log('Page open failed: ' + status);
phantom.exit(1);
return;
}
page.render('screenshot.png');
phantom.exit();
});
This gives each resource up to 30 seconds; it does not promise the entire page will finish in 30 seconds. A page can request many resources, and a wrapper may enforce its own overall deadline. The official PhantomJS screen capture example follows the basic open, render, exit pattern.
3. Wait for asynchronous page content before rendering
A successful page.open() callback does not mean every application-specific visual update is complete. For a known, bounded delay, wait after load and before page.render(). The example below uses two seconds only to illustrate the separate wait; choose a value based on the page and your own capture requirements.
var page = require('webpage').create();
page.settings.resourceTimeout = 30000;
page.onResourceTimeout = function (request) {
console.log('Resource timed out: ' + JSON.stringify(request));
};
page.open('https://example.com/', function (status) {
if (status !== 'success') {
console.log('Page open failed: ' + status);
phantom.exit(1);
return;
}
// Separate post-load delay for asynchronous visual content.
window.setTimeout(function () {
page.render('screenshot.png');
phantom.exit();
}, 2000);
});
When the page has a clear readiness condition, waiting for that condition is usually more reliable than guessing a fixed delay. Keep the resource timeout and capture wait conceptually separate: one limits a resource request; the other postpones rendering.
4. Check wrapper and caller limits
- Find the exact package or service that invokes PhantomJS and check its version-specific documentation.
- Look up the option’s unit, default, when its timer starts, and what it aborts or delays.
- Check whether your shell, job runner, HTTP client, or hosting platform also has a deadline.
- Make sure the combined resource and post-load waits can finish before any outer request deadline.
Changing PhantomJS’s resource timeout cannot override an outer process timeout. Likewise, a wrapper’s post-load delay does not change the timeout for a slow image, script, or stylesheet.
5. Diagnose the failure with logs
Use PhantomJS callbacks to tell a slow resource from a JavaScript exception or a page-open failure.
var page = require('webpage').create();
page.settings.resourceTimeout = 30000;
page.onResourceRequested = function (request) {
console.log('Request: ' + request.url);
};
page.onResourceTimeout = function (request) {
console.log('Resource timeout: ' + JSON.stringify(request));
};
page.onError = function (message, trace) {
console.log('Page JavaScript error: ' + message);
trace.forEach(function (frame) {
console.log(' ' + frame.file + ':' + frame.line);
});
};
page.open('https://example.com/', function (status) {
console.log('Open status: ' + status);
if (status === 'success') {
page.render('screenshot.png');
}
phantom.exit(status === 'success' ? 0 : 1);
});
page.onResourceRequested shows which URLs are requested, page.onResourceTimeout identifies requests that exceeded the limit, and page.onError reports page JavaScript errors. Consult the official network monitoring and JavaScript errors guidance.
6. Troubleshooting common PhantomJS screenshot timeouts
| Symptom | Likely cause | What to check or change |
|---|---|---|
| A resource timeout callback names a URL | That individual request is slow, stuck, or unreachable | Inspect the URL and request logs; increase resourceTimeout before page.open() only if a longer resource wait is appropriate. |
| Page opens successfully but the screenshot misses content | Content appears after the open callback | Add a separate post-load wait or wait for the page’s actual readiness condition before rendering. |
| The process exits or request is aborted at a fixed duration | A wrapper, caller, or job runner deadline expired | Check that layer’s timeout, unit, and default. Its deadline may be unrelated to PhantomJS’s setting. |
| Only HTTPS pages fail | The PhantomJS build may lack usable SSL libraries or have an SSL issue | Check the build’s SSL support and the official troubleshooting guide. |
| JavaScript errors appear in the page | A page script exception, rather than a resource timeout | Capture page.onError output and inspect the message and stack trace. |
| Requests are unexpectedly slow on Windows | The default proxy configuration may add latency | As a diagnostic, try PhantomJS with --proxy-type=none and compare the request behavior. |
| Changing the setting has no effect | It was set after the initial open, or a different PhantomJS binary is running | Set it before page.open(); run phantomjs --version and verify the invoked binary and wrapper. |
PhantomJS’s CLI documentation covers version 2.1.1. Check your installed version and the official command-line options before relying on version-specific behavior.
7. Performance, reliability, and cost considerations
- Performance: Larger per-resource limits and longer post-load waits can increase the time a capture occupies a process. Use the smallest values that reliably cover the page’s actual needs.
- Reliability: A fixed delay can still be too short when a page is slow and waste time when it is fast. Prefer an application-specific readiness condition when supported. Log timed-out URLs and JavaScript errors so you can distinguish failure types.
- Outer deadlines: Ensure the wrapper or caller allows enough time for resource loading and any post-load wait, or it may abort first.
- Cost: Longer jobs consume more runtime in environments that charge for execution time. The dossier gives no PhantomJS runtime price or benchmark, so calculate against your own hosting or job-runner billing.
- Maintenance: PhantomJS’s official CLI documentation covers version 2.1.1 and its documentation is dated. Confirm compatibility with your current pages, dependencies, and runtime before building new capture infrastructure around it.
Or skip the browser setup
ScreenshotNeo provides a screenshot API: send one GET request with a URL and receive an image or PDF. For example, this cURL request saves a WebP capture:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo API documentation for the request options. ScreenshotNeo accepts cookie and consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers say which outcome occurred. Its MCP server gives AI agents tools to take screenshots, get page information, and capture PDFs. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots.
Sign up free for 1,000 screenshots a month, with no card required.
FAQ
Does resourceTimeout include the whole page?
No. It applies to an individual requested resource. A wrapper or caller may impose a separate overall deadline.
Should I set the timeout before or after page.open()?
Before the initial call. Changing it afterward does not affect that open.
Why does the same timeout option mean different things?
Each wrapper defines its own option semantics. Check whether it limits a request or adds a delay before capture, and confirm the unit and default in that wrapper’s documentation.
What if PhantomJS reports no failed resource, but the screenshot is still incomplete?
The page may have rendered content asynchronously after the open callback. Add a separate wait or use a readiness condition before rendering.


