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

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.

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

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.

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

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
Sale
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:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
page.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:

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
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.

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

Troubleshooting PhantomJS scrolling

The position remains at top: 0

  • Confirm that the call is inside page.evaluate(); window is a page variable, not a host global.
  • Check the page.open status before running the scroll.
  • Log page.scrollPosition immediately 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 scrollTop in 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.scrollPosition and page.viewportSize with the screenshot so the rendering conditions are reproducible.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

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.

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

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.

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

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.

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.

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