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

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Pass values after the function: page.evaluate(function (value) { /* use value in the page */ }, value). PhantomJS supplies each trailing argument to the corresponding parameter in the function running inside the page. The documented form has been available since PhantomJS 1.6. Pass serializable data, not outer-scope variables, functions, or DOM nodes.

Pass each value after the evaluated function

The WebPage.evaluate signature is evaluate(function, arg1, arg2, ...). The first argument is the function PhantomJS will run in the webpage context. Any following arguments are passed to that function in order.

var text = page.evaluate(function (selector) {
  var element = document.querySelector(selector);
  return element ? element.textContent : null;
}, 'h1');

Here, 'h1' is the first trailing argument, so it becomes the value of selector inside the evaluated function. The function looks for a matching element and returns its text, or null if there is no match. That null check is a useful defensive choice in this example; it is not a special behavior of evaluate().

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

This argument-passing capability is documented as available as of PhantomJS 1.6. If an older installation is involved, check its version rather than assuming it supports the same interface. PhantomJS is legacy software, so this guidance is for maintaining or working with existing PhantomJS code.

Use arguments instead of outer-scope variables

The evaluated function runs in the page context, not as a closure over the surrounding PhantomJS script. A variable defined in the outer script is therefore not automatically available inside the callback.

var selector = 'h1';
var text = page.evaluate(function () {
  return document.querySelector(selector).textContent;
});

This is an outer-scope capture attempt: selector is not supplied to the page-context function. Pass it explicitly instead:

var selector = 'h1';
var text = page.evaluate(function (s) {
  var element = document.querySelector(s);
  return element ? element.textContent : null;
}, selector);

The outer variable is read by PhantomJS as the argument value; the function receives that value as s. The same approach applies to values such as a search term, an attribute name, a numeric limit, or a plain options object, provided the data crossing the boundary is serializable.

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

Pass multiple values in parameter order

For multiple inputs, put each value after the function in the same order as the function parameters. Names do not connect the two sides; position does.

var result = page.evaluate(function (selector, attributeName) {
  var element = document.querySelector(selector);
  return element ? element.getAttribute(attributeName) : null;
}, 'a.primary', 'href');

In this example, 'a.primary' becomes selector and 'href' becomes attributeName. If the values are supplied in the opposite order, the function receives the wrong values for those parameters. Keep the function’s parameter list and the trailing argument list aligned when changing either one.

Arguments may also be grouped in a plain data object when that makes a call easier to maintain. The PhantomJS API recommends simple primitive objects and gives JSON serialization as a rule of thumb; it does not mean arbitrary JavaScript values can cross into the page.

var options = { selector: 'h1', attributeName: 'class' };
var value = page.evaluate(function (settings) {
  var element = document.querySelector(settings.selector);
  return element ? element.getAttribute(settings.attributeName) : null;
}, options);

Use plain data for the object’s contents. Do not put callbacks, functions, or DOM elements inside it and expect them to become usable in the page context.

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

Return a simple value to the PhantomJS script

The value returned by the evaluated function crosses the same context boundary in the other direction. Return simple data that can be represented through JSON-style serialization, such as a string, number, boolean, null, or a simple object or array made from such values. The PhantomJS quick start also warns that return values cannot contain functions or closures.

var pageInfo = page.evaluate(function () {
  return {
    title: document.title,
    url: window.location.href
  };
});

console.log(pageInfo.title);
console.log(pageInfo.url);

This keeps DOM work inside the browser page while returning only the data the outer script needs. Do not return a DOM node expecting to manipulate that node as a PhantomJS-side object; DOM nodes are explicitly among the unsupported values across this boundary.

Complete example with page loading and an argument

The following example opens a page, checks the load status, passes a selector into evaluate(), handles a missing match, and prints the resulting text. It uses the documented callback-based page.open() flow.

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

page.open('https://example.com', function (status) {
  if (status !== 'success') {
    console.log('Unable to load page');
    phantom.exit();
    return;
  }

  var heading = page.evaluate(function (selector) {
    var element = document.querySelector(selector);
    return element ? element.textContent : null;
  }, 'h1');

  if (heading === null) {
    console.log('No matching heading');
  } else {
    console.log(heading);
  }

  phantom.exit();
});

Checking status before reading page content is important: a failed open is not a useful situation in which to interpret a selector result. The selector itself is passed explicitly as the trailing argument; the evaluated function does not rely on a variable from the callback’s surrounding PhantomJS scope.

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

Do not confuse evaluate() with evaluateJavaScript()

page.evaluate(function, ...args) accepts a function followed by argument values. The related evaluateJavaScript(str) entry point is documented as taking a string containing a function declaration and invoking it immediately. Its reference illustrates setting and reading a page global in separate calls; it does not document the same trailing-argument form.

For ordinary argument passing, use page.evaluate() with a function and explicit trailing values. Choose evaluateJavaScript() only when the string-based interface is specifically what the existing code requires; do not assume that its string parameter accepts the same argument list.

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

Forward page console messages explicitly

A console.log() call made inside the page context is not automatically printed in the PhantomJS terminal. The page’s console message must be forwarded through page.onConsoleMessage if terminal output is needed.

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

page.onConsoleMessage = function (message) {
  console.log('PAGE: ' + message);
};

page.evaluate(function () {
  console.log('Message from the page context');
});

When the goal is to get a value back into the PhantomJS script, returning it from evaluate() is usually clearer than logging it from inside the page. Use console forwarding for page-side diagnostic messages that are genuinely useful as logs.

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

Troubleshoot common argument-passing failures

  • The page function cannot see a variable. A callback’s outer variables are not implicitly captured. Add a parameter to the evaluated function and pass the outer value after the function.
  • The function receives an unexpected value. Compare argument positions with parameter positions. The first trailing value goes to the first parameter, the second to the second, and so on.
  • A function or DOM node is missing or unusable. Functions, closures, and DOM nodes are unsupported across the boundary. Pass serializable data such as a selector string, then locate and use the DOM element inside the evaluated function.
  • The outer script cannot use the returned result as expected. Return simple serializable data, not a function, closure, or DOM node. Convert page-side work into a string, number, boolean, null, or simple data structure before returning it.
  • Page-side console.log() produces no terminal output. This is not forwarded by default. Register page.onConsoleMessage, or return the value that the outer script needs.
  • No useful page result appears after opening a URL. Check the page.open() status before evaluating page content. A failed load should be handled as a load failure, not mistaken for a selector or argument problem.
  • The call form does not work in an old environment. Argument passing is documented as available as of PhantomJS 1.6. Verify the installed version when maintaining an older setup.

Or skip the browser setup

If the actual task is to get a screenshot or PDF of a page rather than run custom JavaScript in its DOM, ScreenshotNeo is a website screenshot API and MCP server for developers. It is not a replacement for arbitrary page.evaluate() logic, but it can return a screenshot from one request:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp

See the ScreenshotNeo API documentation for request options. Before capture it can accept cookie or consent banners and remove more than 60 known consent platforms, newsletter popups, and chat widgets; each of those steps can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies page verdict and billing status in headers. Its MCP server provides screenshot, page-info, and PDF tools for AI agents. The free plan includes 1,000 shots a month without a card; paid plans start at $5 for 3,000 shots. See ScreenshotNeo for details.

Sign up for ScreenshotNeo’s free plan: 1,000 screenshots a month, no card required.

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.