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.

If PhantomJS reports that a page loaded but your Selenium test cannot find AJAX content, the most common issue is a timing mismatch: navigation finished, but the page’s JavaScript has not yet rendered the result your test needs. Wait for the specific result element, then inspect resource requests, JavaScript errors, and load status if it never appears. A longer fixed sleep is rarely the right first fix.

First separate page loading from AJAX completion

Selenium’s navigation wait concerns the document’s readiness, not every change an application makes afterward. A page can reach its configured ready state while JavaScript is still requesting data, processing a response, or inserting result elements into the DOM. The page-open callback in PhantomJS similarly reports the navigation/load outcome; it does not promise that later application-level asynchronous work is finished.

So a test that navigates and immediately searches for a dynamically rendered result may race the page. Selenium’s “Waiting Strategies” guidance makes this distinction explicitly: readiness covers assets defined in the HTML, while loaded JavaScript can subsequently alter the page. Choose the condition based on what the test actually needs: for example, a result container becomes present, a loading indicator disappears, or a particular status changes.

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

Prefer a condition-based wait to a fixed delay

A fixed sleep waits the same amount whether the response arrives quickly or slowly. Too short and the test remains flaky; too long and every successful run is unnecessarily slow. An explicit wait polls for a meaningful condition and proceeds as soon as it is true, up to a timeout. Set a sensible limit for your application, and make a timeout fail with enough context to diagnose the missing result.

#1 Best Overall
Sale

In Selenium JavaScript bindings that provide the familiar until conditions, the core pattern is:

const { By, until } = require('selenium-webdriver');

// Run after navigation, using the driver already created for your test.
const results = await driver.wait(
  until.elementsLocated(By.css('.search-result')),
  10000,
  'Search results did not appear within 10 seconds'
);

Replace .search-result with the selector for the rendered output, and adjust the timeout to your application’s expected response range. If the test needs visibility rather than mere presence, wait for visibility; if it needs a specific value, poll for that value. The snippet is the wait pattern, not a prescription for constructing a PhantomJS driver: the Selenium JavaScript binding’s PhantomJS support was removed, so whether an existing legacy setup can run it depends on its exact binding and versions.

Check versions before changing an old PhantomJS setup

Record the exact PhantomJS binary version, GhostDriver version or bundled implementation, Selenium version, language binding, and runtime version. GhostDriver implements the WebDriver protocol connection to PhantomJS. A command copied from an old setup guide does not establish compatibility with an arbitrary newer Selenium release.

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.

The Selenium JavaScript changelog says native support for PhantomJS was removed because its WebDriver implementation was no longer under active development. That statement applies to the JavaScript bindings described by that changelog; it does not prove that every other Selenium language binding dropped support at the same time or behaves identically. Check the documentation and compatibility information for the binding and versions your test actually uses. If that combination cannot start a session reliably, an explicit wait cannot repair the underlying driver incompatibility.

Instrument PhantomJS to see what failed

If the expected element never appears, gather evidence instead of increasing the timeout blindly. PhantomJS exposes resource callbacks, page errors, a navigation completion callback, and a resource timeout setting. The following standalone PhantomJS script logs requested resources and page errors, reports the page.open status, and polls for a selector after navigation.

// diagnose.js — run with: phantomjs diagnose.js https://example.com .search-result
var page = require('webpage').create();
var system = require('system');

if (system.args.length < 3) {
  console.log('Usage: phantomjs diagnose.js URL CSS_SELECTOR');
  phantom.exit(2);
}

var url = system.args[1];
var selector = system.args[2];
var deadline;
var finished = false;

page.settings.javascriptEnabled = true;
page.settings.resourceTimeout = 15000;

page.onResourceRequested = function (request) {
  console.log('REQUEST ' + request.method + ' ' + request.url);
};

page.onResourceReceived = function (response) {
  if (response.stage === 'end') {
    console.log('RESPONSE ' + response.status + ' ' + response.url);
  }
};

page.onResourceTimeout = function (request) {
  console.log('RESOURCE TIMEOUT ' + request.url);
};

page.onError = function (message, trace) {
  console.log('PAGE ERROR ' + message);
  trace.forEach(function (frame) {
    console.log('  ' + frame.file + ':' + frame.line);
  });
};

function finish(code, message) {
  if (finished) return;
  finished = true;
  if (message) console.log(message);
  phantom.exit(code);
}

page.open(url, function (status) {
  console.log('PAGE OPEN ' + status);
  if (status !== 'success') {
    finish(1, 'Navigation did not succeed');
    return;
  }

  deadline = Date.now() + 10000;
  var poll = setInterval(function () {
    var found = page.evaluate(function (css) {
      return document.querySelector(css) !== null;
    }, selector);

    if (found) {
      clearInterval(poll);
      finish(0, 'FOUND ' + selector);
    } else if (Date.now() >= deadline) {
      clearInterval(poll);
      finish(1, 'NOT FOUND ' + selector);
    }
  }, 100);
});

Run it with the URL and a selector that should exist only once the relevant content has rendered. The ten-second selector deadline is an example diagnostic limit, not a universal application setting. The resource timeout is separate: it limits an individual resource request, and PhantomJS invokes the timeout callback if that limit is reached. The script intentionally reports request URLs and response statuses, which can be useful but may expose sensitive query parameters in logs; protect or redact logs accordingly.

Interpret the output in order

  • PAGE OPEN success, then NOT FOUND: navigation completed but the selector did not appear before the diagnostic deadline. Check the data request, page errors, selector, and rendering logic.
  • PAGE OPEN fail: the navigation did not complete successfully. Investigate URL reachability, network behavior, TLS/certificate issues, and the PhantomJS environment before debugging the selector.
  • A request is missing: check whether the page reached the code that issues it, whether the expected script loaded, and whether network or application conditions prevent the request.
  • A request appears but the element does not: a request log alone does not establish that the application accepted the response or rendered it. Check response status, JavaScript errors, response parsing, selector accuracy, and application-specific state.
  • A timeout is logged: identify the particular resource and determine whether it is required for the target content. A timed-out image or analytics call may be unrelated; a timed-out data endpoint may explain the missing result.

This script is for diagnosis, not a substitute for the Selenium test’s own condition-based wait. It demonstrates PhantomJS WebPage callbacks and polling; it does not show that a given Selenium/GhostDriver combination is supported.

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.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Check JavaScript, resource timeouts, TLS, and the runtime

PhantomJS documentation describes JavaScript as enabled by default, but that does not rule out a JavaScript exception, an unavailable script, or an application error. Inspect onError output and the relevant stack trace. If an exception occurs before the AJAX logic runs, waiting longer will not make the missing element appear.

Review page.settings.resourceTimeout when resource callbacks show requests being stopped. It controls how long a resource request may continue before PhantomJS stops it and invokes the timeout callback. Set it with the site’s real response behavior in mind; raising it can help distinguish a slow response from a broken path, but it will not fix an unreachable endpoint or application error.

If failures are limited to HTTPS pages, investigate TLS support and certificate behavior in the PhantomJS build and runtime environment. PhantomJS troubleshooting guidance also identifies network behavior and multiple installed PhantomJS binaries as possible sources of confusion. Confirm which executable your test launches rather than assuming that the first binary on one shell’s PATH is the one used by Selenium or CI.

Use page-load strategy only for navigation, not AJAX synchronization

Selenium documents normal, eager, and none page-load strategies. They change how navigation waits for document readiness or initial download. None means “wait for all application AJAX work to finish.” If you change a strategy to make navigation return sooner, keep an explicit wait for the result your test consumes; otherwise, the race can become more frequent.

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

When an old PhantomJS test should be preserved or replaced

Keep a legacy setup only after checking its exact language binding and version compatibility, whether PhantomJS can execute the target site’s JavaScript and meet its network requirements, and whether explicit waits plus diagnostics make the test dependable. A wait can solve synchronization when the response and rendering succeed. It cannot make an unsupported driver work, repair an incompatible TLS environment, or correct a site-specific JavaScript failure. The available project guidance does not establish compatibility for every binding/version combination, so verify the stack you actually run.

Or skip the browser setup

If your goal is a website screenshot rather than exercising a Selenium interaction or fixing a test, ScreenshotNeo offers a screenshot API and MCP server. It is not a replacement for a Selenium test that must verify AJAX behavior; it is an alternative when you need an image or PDF of a page without managing a PhantomJS browser session. For a one-call image request, see the ScreenshotNeo API documentation:

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

For websites where consent overlays or other obstructions interfere with the image, ScreenshotNeo removes cookie/consent banners, newsletter popups, and chat widgets before capture; each of those cleanup steps can be turned off. Bot checks/CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and responses identify the page verdict and billing status in headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for 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 shots.

Python equivalent:

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

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

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

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

Quick Recap

SaleBestseller No. 1
The Phantom Tollbooth
The Phantom Tollbooth
Great product!
$7.64
SaleBestseller No. 2

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.