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.

A Selenium/Byte Buddy/PhantomJSDriver failure is usually a Maven dependency-graph conflict, not a broken web page. com.github.detro:phantomjsdriver:1.2.0 brings Selenium 2.41.0, while a modern project normally uses one Selenium 4.x line. First inspect the resolved graph, then make selenium-java your deliberate entry point, remove or isolate PhantomJSDriver, and align Byte Buddy artifacts. Only investigate Java module flags after the dependency graph is clean.

What the conflict means

Maven resolves one version of a dependency path even when several libraries request different versions. PhantomJSDriver 1.2.0 is a 2015-era artifact whose published POM declares Selenium 2.41.0 compile dependencies. Adding it to a project that also declares a current Selenium release can leave old and new Selenium artifacts in the graph, producing split APIs, linkage errors, or module-resolution failures.

Byte Buddy is a separate JVM runtime code-generation library, published as net.bytebuddy:byte-buddy. Selenium and other test libraries may also bring net.bytebuddy:byte-buddy-agent or a Java-compatibility variant such as byte-buddy-jdk5. Maven Enforcer can reject the graph when versions, classifiers, or artifact variants do not agree. Selenium issue #17355, opened April 16, 2026, describes a case where changing byte-buddy from 1.18.5 to 1.18.8-jdk5 caused a managed-version compatibility complaint.

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

1. Capture the dependency graph before changing anything

Maven

Run these commands from the module that fails:

mvn dependency:tree -Dverbose -Dincludes=org.seleniumhq.selenium,com.github.detro,net.bytebuddy
mvn help:effective-pom > effective-pom.xml
mvn clean compile

Record every occurrence of:

  • org.seleniumhq.selenium:selenium-java and individual Selenium modules, including any 2.x and 4.x versions.
  • com.github.detro:phantomjsdriver.
  • net.bytebuddy:byte-buddy and net.bytebuddy:byte-buddy-agent.
  • Classifiers or alternate artifacts such as byte-buddy-jdk5.

In the tree, omitted for conflict with identifies a version Maven discarded. That line is evidence of mediation, not proof that the surviving version is binary-compatible with the library that requested the discarded one.

Gradle equivalent

./gradlew dependencies --configuration testRuntimeClasspath
./gradlew dependencyInsight --dependency selenium --configuration testRuntimeClasspath
./gradlew dependencyInsight --dependency byte-buddy --configuration testRuntimeClasspath

Save the report before exclusions or upgrades. It gives you a way to verify that each fix removed the intended edge rather than hiding a new one.

2. Choose one Selenium release line

Selenium’s Java installation guidance uses a build tool, and its upgrade procedure changes the Maven selenium-java version before running mvn clean compile. Treat selenium-java as the intentional Selenium entry point instead of declaring several individual Selenium modules at unrelated versions.

Maven dependency

<properties>
  <selenium.version>YOUR_SELECTED_SELENIUM_4_VERSION</selenium.version>
</properties>

<dependencies>
  <dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>${selenium.version}</version>
  </dependency>
</dependencies>

Replace the property with the exact Selenium 4.x release your project supports; do not copy a version from an unrelated application. Then run:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
mvn clean compile
mvn dependency:tree -Dincludes=org.seleniumhq.selenium

The second command should show one coherent Selenium release line. If another direct dependency still requests Selenium 2.x, identify whether it is PhantomJSDriver or a different legacy library before adding exclusions.

Gradle dependency

dependencies {
    testImplementation("org.seleniumhq.selenium:selenium-java:<your-selected-4.x-version>")
}

Use a version catalog or dependency constraints if several modules consume Selenium, so all modules receive the same selected release.

3. Remove PhantomJSDriver when it is not required

Delete this dependency if no test genuinely needs PhantomJS:

<dependency>
  <groupId>com.github.detro</groupId>
  <artifactId>phantomjsdriver</artifactId>
  <version>1.2.0</version>
</dependency>

Re-run mvn clean compile and the dependency report. Removing the artifact also removes its declared Selenium 2.41.0 path, which is commonly the source of the split API. Replace PhantomJS with a supported Selenium browser driver or a RemoteWebDriver endpoint appropriate for your test infrastructure.

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

PhantomJS is a legacy headless browser. GhostDriver’s documentation describes remote-WebDriver operation and notes that the latest stable GhostDriver is embedded in PhantomJS; that does not make the old Java binding compatible with Selenium 4. Compatibility must be established from your actual resolved graph and test results.

4. Isolate PhantomJS for a genuinely legacy test

If a historical test cannot be retired, keep it out of the modern test classpath. The safest pattern is a separate Maven module or profile with its own test sources and reports.

Separate module

  • Modern module: declares only the selected selenium-java 4.x release and current browser drivers.
  • Legacy module: contains PhantomJS tests, pins the old dependencies they actually require, and is run as a separately named build job.
  • Interface boundary: exchange test data or reports, not Selenium driver objects, between modules.

Profile with exclusions

When a separate module is impractical, exclude PhantomJSDriver’s transitive Selenium dependencies and supply the versions selected for that profile. The exclusion must be deliberate and verified; it does not magically make an old driver compatible with Selenium 4.

<dependency>
  <groupId>com.github.detro</groupId>
  <artifactId>phantomjsdriver</artifactId>
  <version>1.2.0</version>
  <exclusions>
    <exclusion>
      <groupId>org.seleniumhq.selenium</groupId>
      <artifactId>selenium-java</artifactId>
    </exclusion>
    <exclusion>
      <groupId>org.seleniumhq.selenium</groupId>
      <artifactId>selenium-api</artifactId>
    </exclusion>
  </exclusions>
</dependency>

Inspect the PhantomJSDriver POM and your dependency tree for every Selenium artifact it brings; exclude each unwanted edge rather than assuming one exclusion covers all modules. Run only the legacy profile’s tests after the graph is stable.

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

5. Align Byte Buddy and its variants

First determine which artifact Maven selected. A conflict between byte-buddy, byte-buddy-agent, and byte-buddy-jdk5 is not fixed by changing Selenium blindly.

Manage one intended version

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>net.bytebuddy</groupId>
      <artifactId>byte-buddy</artifactId>
      <version>YOUR_BYTE_BUDDY_VERSION</version>
    </dependency>
  </dependencies>
</dependencyManagement>

Set the version to one that is compatible with your selected Selenium line and Java runtime. If the graph needs an agent, manage byte-buddy-agent consistently as well. Do not substitute byte-buddy-jdk5 merely because its name sounds more compatible; classifiers and variant artifacts are distinct coordinates.

Exclude an unwanted variant

If one dependency introduces a duplicate or incompatible Byte Buddy artifact, add a targeted exclusion to that dependency and keep the managed artifact. Serenity’s published POM demonstrates this style of excluding Byte Buddy artifacts from Selenium driver dependencies. Verify the result with:

mvn dependency:tree -Dverbose -Dincludes=net.bytebuddy

Address Maven Enforcer’s exact message. In the issue #17355 scenario, a classifier/version comparison treated 1.18.8-jdk5 as greater than managed 1.18.8; changing the managed version or removing the unintended variant is preferable to disabling the enforcer rule.

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.

6. Clean and validate the repaired build

  1. Delete stale output with mvn clean; remove an IDE’s cached project model only if it still shows dependencies that are absent from the effective POM.
  2. Refresh dependencies using your normal Maven or Gradle refresh mechanism. Avoid permanently deleting the local repository as a first step.
  3. Run mvn clean compile, then the project’s normal unit and browser-test commands.
  4. Generate the dependency tree again and confirm one Selenium line, one intended Byte Buddy line, and no accidental PhantomJS transitive Selenium path.
  5. Run the legacy profile separately if PhantomJS remains isolated.

Only after compilation and tests use the intended graph should you investigate a remaining Java module-access exception. Capture the first cause in the stack trace. The available evidence does not establish one universal module-info.java or --add-opens flag for this exact combination, so adding broad module opens before fixing dependencies can hide the real problem.

Which repair path fits your project?

Path Use when Main benefit Main cost
Modern Selenium only PhantomJS is not a hard requirement One supported release line and simpler builds Legacy PhantomJS tests must be replaced
Isolated legacy module/profile A historical PhantomJS test still provides required coverage Preserves the old test without contaminating modern modules Two dependency sets and separate execution
Explicit Byte Buddy management Enforcer reports version, classifier, or variant disagreement Predictable runtime and reproducible builds Requires checking compatibility with Selenium and Java
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If your objective is simply to capture a page rather than exercise Selenium code, ScreenshotNeo provides a website screenshot API and MCP server. One GET request returns PNG, JPEG, WebP, or PDF. Before capture it accepts cookie/consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing result.

cURL

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

Python

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

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

See the ScreenshotNeo documentation for the full option set: full-page and selector capture, device presets, retina scale, PDF paper and page controls, custom CSS and JavaScript, clicks, waits, request blocking, cookies and headers, geolocation, caching, signed links, asynchronous webhooks, bulk capture, usage data, and the OpenAPI specification. 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 each month without a card. Paid plans start at $5 for 3,000 screenshots; every feature is available on every plan. Create a free ScreenshotNeo account to try it.

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

Troubleshooting common errors

“Could not resolve dependencies” or an Enforcer convergence error

Cause: two paths request incompatible Selenium or Byte Buddy coordinates. Inspect the verbose tree, then choose one release line in dependency management and exclude only the unwanted transitive edge.

NoSuchMethodError or ClassNotFoundException in Selenium classes

Cause: compiled code and runtime code came from different Selenium generations. Remove PhantomJSDriver from the modern classpath or isolate it; then clean and rebuild.

Enforcer says byte-buddy-jdk5 is newer than managed byte-buddy

Cause: Maven is comparing different variants, as in Selenium issue #17355. Align the intended artifact and version, or exclude the variant that is not needed. Do not silence the rule without documenting why.

The build compiles, but PhantomJS tests fail at runtime

Cause: dependency mediation produced a graph that is syntactically valid but not binary-compatible with the legacy driver. Run the PhantomJS tests in their isolated module/profile with the exact dependencies they require, or migrate the tests to a supported browser driver.

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

A module-access exception remains after alignment

Cause may be Java runtime access rather than dependency mediation. Preserve the first stack-trace cause, check the selected Selenium and Byte Buddy compatibility for that Java runtime, and add the narrowest documented module option only after those checks. There is no single flag established for every Selenium/PhantomJSDriver combination.

FAQ

Why does PhantomJSDriver pull Selenium 2.41.0?

Version 1.2.0 declares Selenium 2.41.0 as compile dependencies in its published POM. Maven therefore introduces that old API whenever the artifact is present unless you remove or exclude the transitive path.

Can I force Selenium 4 and keep PhantomJSDriver in the same module?

You can force Maven to resolve one version, but resolution success does not prove the old driver is compatible with the newer API. Isolation is safer for a test that cannot yet be migrated.

Should I add --add-opens immediately?

No. First prove that the dependency tree contains one intended Selenium line and aligned Byte Buddy artifacts. Module flags address access checks, not a split or incompatible dependency graph.

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

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.