The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Yes. A loaded PhantomJS page has a browser window object. Code passed to page.evaluate() runs inside that webpage context, where normal DOM and browser scripting are available. To scroll the document, call page-side JavaScript such as window.scrollTo(); to read the resulting position from PhantomJS, inspect page.scrollPosition, an object with left and top values. PhantomJS keeps that page context separate from the host-side phantom API.
The two contexts you must keep separate
PhantomJS automation involves two JavaScript environments. Confusing them is the source of most questions about whether window exists.
The webpage context
The function supplied to page.evaluate() is evaluated in the context of the loaded web page. It can use objects that page JavaScript normally sees, including window, document, elements, styles and page-defined functions. PhantomJS’s official evaluate documentation describes this directly: it “Evaluates the given function in the context of the web page.”
That means this is page code:
page.evaluate(function () {
window.scrollTo(0, 800);
});
The function is not running in your PhantomJS script’s top-level environment. Values crossing the boundary must be serializable; return a number, string, boolean, array or plain object rather than a page DOM node or a PhantomJS object.
#1 Best Overall
The PhantomJS host context
Your outer script runs in PhantomJS and controls the WebPage object. Properties such as page.scrollPosition and page.viewportSize belong here. The host context also exposes the phantom object and APIs for opening pages, rendering, event delivery and exiting.
The page’s JavaScript cannot use the host-side phantom object. Conversely, host code should not treat window as a global PhantomJS variable. Use page.evaluate() whenever the operation depends on the document, and use page.* properties when you need PhantomJS to report or configure browser state.
How PhantomJS represents scrolling
page.scrollPosition: read the current offset
The WebPage API documents page.scrollPosition as the current scroll position:
{ left: horizontalOffset, top: verticalOffset }
top is the document’s vertical offset and left is its horizontal offset. Read it after a page-side scroll to verify what PhantomJS reports.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
page.viewportSize: define the visible viewport
page.viewportSize describes the viewport’s width and height. It does not represent the full document; it represents the visible browser area used for layout and rendering. Set it before opening the page when a particular responsive layout matters:
Rank #2
page.viewportSize = {
width: 1280,
height: 800
};
A different viewport can change responsive breakpoints, which in turn can change the document’s layout and the amount that can be scrolled.
Direct document scrolling with page.evaluate()
For ordinary document scrolling, execute browser code in the page context. window.scrollTo(x, y) expresses the desired horizontal and vertical coordinates:
page.evaluate(function () {
window.scrollTo(0, 1200);
});
console.log(JSON.stringify(page.scrollPosition));
To move relative to the current position, use the page’s normal scrolling methods:
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problemspage.evaluate(function () {
window.scrollBy(0, 600);
});
To request the bottom of the document, calculate a target from the document dimensions inside the page:
page.evaluate(function () {
var height = Math.max(
document.body.scrollHeight,
document.documentElement.scrollHeight
);
window.scrollTo(0, height);
});
The general DOM scripting model is supported in the page context. However, the cited API documentation does not guarantee identical behavior for every nested overflow container, dynamically updated application, or event-driven interface. If the content is inside an element with its own overflow scrolling, select that element and change its page-side scrollTop instead of assuming the document itself will move:
Rank #3
page.evaluate(function () {
var panel = document.querySelector('.results-panel');
if (panel) {
panel.scrollTop = panel.scrollHeight;
}
});
This example depends on the page actually having an element with that selector; it is not a replacement for document scrolling on pages that use the window scroll position.
A complete PhantomJS example
The following script sets a viewport, opens a URL, scrolls the document in the webpage context, reads the PhantomJS-side position and renders the page. Save it as scroll.js and run it with your installed PhantomJS executable.
var webpage = require('webpage');
var system = require('system');
var page = webpage.create();
var url = system.args[1] || 'https://example.com';
page.viewportSize = {
width: 1280,
height: 800
};
page.open(url, function (status) {
if (status !== 'success') {
console.log('Could not load ' + url + ' (status: ' + status + ')');
phantom.exit(1);
return;
}
page.evaluate(function () {
window.scrollTo(0, 1200);
});
console.log('scrollPosition=' + JSON.stringify(page.scrollPosition));
console.log('viewportSize=' + JSON.stringify(page.viewportSize));
page.render('scrolled.png');
phantom.exit();
});
Run it with a URL argument:
phantomjs scroll.js https://example.com
The output should include a JSON object containing left and top. The exact top value can be lower than the requested 1,200 pixels when the document is shorter than that target. A screenshot is only a visual check; page.scrollPosition is the API value to log in an automated test.
When to use page JavaScript, a property, or an input event
| Goal | Use | What it gives you |
|---|---|---|
| Change the document’s scroll location | page.evaluate(function () { window.scrollTo(...); }) |
Browser-side DOM behavior in the loaded page |
| Move relative to the current document position | page.evaluate(function () { window.scrollBy(...); }) |
A page-context scroll operation |
| Inspect where the document is now | page.scrollPosition |
An object with left and top |
| Set the visible browser area | page.viewportSize |
Viewport width and height used by the page |
| Cause a site-specific interaction | page.sendEvent(...) |
Mouse or keyboard input delivered as user interaction |
page.sendEvent is different from directly running page JavaScript. PhantomJS documents these events as being sent as if they came from user interaction and distinguishes them from synthetic DOM events. Use an input event when the site’s behavior is specifically attached to a key press, wheel gesture or mouse action. The API documentation does not promise that an arbitrary event call will scroll the document, so do not use event delivery as a generic substitute for window.scrollTo().
Timing, dynamic pages and lazy content
Scroll only after page.open reports a successful load. A page can still change after that callback: scripts may insert content, replace a list or restore a saved position. If your target depends on content that appears later, perform the scroll after the page’s own readiness condition rather than immediately after navigation. In PhantomJS, that commonly means polling a page-side condition with a timer and then calling page.evaluate().
var tries = 0;
var timer = setInterval(function () {
var ready = page.evaluate(function () {
return !!document.querySelector('.results-panel');
});
if (ready || ++tries === 20) {
clearInterval(timer);
page.evaluate(function () {
window.scrollTo(0, 1200);
});
console.log(JSON.stringify(page.scrollPosition));
phantom.exit();
}
}, 250);
This is a polling pattern, not a guarantee that a particular framework has finished all work. Record the condition you waited for so a future failure is diagnosable.
Free tools Windows power users keep installed
One-click scans. No signup required.
Troubleshooting PhantomJS scrolling
The position remains at top: 0
- Confirm that the call is inside
page.evaluate();windowis a page variable, not a host global. - Check the
page.openstatus before running the scroll. - Log
page.scrollPositionimmediately after the call and again after a short delay if page code may restore the position. - Check whether the page scrolls a nested element rather than the document. Set that element’s
scrollTopin the evaluated function.
The requested offset is larger than the reported offset
A short document cannot scroll beyond its maximum. Compare the requested coordinate with the document’s available height in page JavaScript, and treat the reported top as the authoritative result.
The page scrolls, then jumps back
A script may restore its preferred position, replace the document, or insert content after your call. Wait for the relevant selector or application state, then scroll; if the page continues to change, capture and log the position over time.
A wheel or key event does nothing
sendEvent delivers input, but the documentation does not guarantee that every event causes document scrolling. Use direct page scripting for a known coordinate, or send the exact interaction the page listens for and verify the result through page.scrollPosition.
The screenshot does not show the expected section
- Verify
page.viewportSize; a responsive breakpoint can change layout. - Make sure the scroll happened before
page.render(). - Check for a nested scrolling panel, fixed overlay or page script that changed the position after your call.
- Log both
page.scrollPositionandpage.viewportSizewith the screenshot so the rendering conditions are reproducible.
Reliability and maintenance considerations
PhantomJS’s API reference is a legacy reference. It establishes the page/host context distinction, the scroll and viewport properties, DOM scripting and event APIs, but it is not a promise that a current, complex web application will behave like a modern browser. Pin the PhantomJS version used by your automation, keep a small test page for document and nested scrolling, and treat changes in a target site as possible causes of failures rather than assuming the scroll API changed.
For repeatable captures, keep these inputs explicit:
- the URL and navigation success status;
- the viewport width and height;
- the selector or readiness condition used before scrolling;
- the requested coordinates and the resulting
page.scrollPosition; - the time between readiness, scrolling and rendering.
Or skip the browser setup
If your goal is a clean screenshot rather than maintaining a PhantomJS script, ScreenshotNeo provides a website screenshot API. One GET request returns a PNG, JPEG, WebP or PDF, so you do not need to install or operate a browser runtime.
Here is the one-call cURL form (the ScreenshotNeo documentation lists the parameters and response headers):
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
Python:
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://example.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
ScreenshotNeo accepts cookie and consent banners as a visitor and removes more than 60 known consent platforms, newsletter popups and chat widgets before capture; each cleanup step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and each response identifies the page verdict and billing result with X-Page-Verdict and X-Billed headers. Its MCP server exposes take_screenshot, get_page_info and capture_pdf to Claude, Cursor and other MCP clients. The Free plan includes 1,000 screenshots per month without a card; paid plans start at $5 for 3,000 screenshots. Create a free ScreenshotNeo account to try the API.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →Practical decision guide
| If you need… | Prefer… | Reason |
|---|---|---|
| A precise, script-controlled scroll inside an existing PhantomJS workflow | page.evaluate() plus page.scrollPosition |
You control the page operation and can verify the resulting coordinates. |
| A site-specific keyboard or mouse interaction | page.sendEvent(), followed by position verification |
The page may respond to user-like input, but the event API does not guarantee scrolling. |
| A screenshot or PDF without browser installation and cleanup code | ScreenshotNeo | It removes common consent UI before capture, bills only clean shots, and offers API and MCP access. |
Frequently Asked Questions
Can code in page.evaluate() control PhantomJS’s browser chrome or host process?
No. The evaluated function is confined to the loaded webpage context. Use the outer PhantomJS script for navigation, viewport configuration, rendering and process control.
What information should a scrolling regression test save?
Save the URL, viewport dimensions, readiness condition, requested coordinates, reported left/top values and the resulting image. Those values distinguish a short document, a nested scroller and a timing-related reset.
Does a successful scroll prove that every dynamic section finished loading?
No. A scroll position only reports document movement. If content is inserted later, wait for an application-specific selector or state and capture again after that condition.
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.
Recommended Free Tools

