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.

To run Selenium tests with HtmlUnit, add the current org.seleniumhq.selenium:htmlunit3-driver artifact, create an HtmlUnitDriver, and choose a constructor that matches your JavaScript and browser-simulation needs. The no-argument constructor disables JavaScript; new HtmlUnitDriver(true) enables it.

The setup is small, but compatibility matters. The driver, Selenium, HtmlUnit and your JDK must match the versions listed in the HtmlUnitDriver project’s compatibility table. The example below uses the project README’s 4.48.0 coordinate (release metadata dated September 2, 2026); confirm that version is available and compatible before pinning it.

What HtmlUnitDriver is—and what it is not

HtmlUnit describes itself as a “GUI-less browser for Java programs.” It can request HTTP and HTTPS pages, manage cookies and headers, submit forms, click links, expose the DOM, use proxies and authentication, and execute JavaScript. Selenium’s HtmlUnitDriver adapts that engine to the WebDriver API, so a Java test can call familiar methods such as get, findElement and quit without launching a visible desktop browser.

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

It is a headless browser simulator, not an installed Chrome, Firefox or Edge process. HtmlUnit can simulate those browser families through a selected BrowserVersion, but that setting does not provide pixel-level or complete behavioral parity with the real browser. Use HtmlUnit for logic, navigation, forms and DOM-oriented checks; run your critical user-facing flows in the actual target browsers when rendering, media, Web APIs or browser-specific behavior matters.

Check Selenium 4, HtmlUnit and Java compatibility first

The current project direction uses org.seleniumhq.selenium:htmlunit3-driver. An older coordinate, org.seleniumhq.selenium:htmlunit-driver, still appears in artifact indexes, but copying it into a new project can leave you on legacy code. Consult the HtmlUnitDriver release history and compatibility table for the exact Selenium and HtmlUnit combination you intend to use.

Item What is established What to verify before pinning
Driver artifact htmlunit3-driver; the README example shows version 4.48.0, dated September 2, 2026. Whether that release is present in your repository and which Selenium/HtmlUnit versions its compatibility table supports.
Java baseline HtmlUnit 5.0.0 and later require JDK 17 or newer. The current driver build metadata also uses Java release/source/target 17. Your actual JDK and the requirements of the selected artifact; older projects may need an older, explicitly supported stack.
Legacy coordinate org.seleniumhq.selenium:htmlunit-driver is an older artifact. Do not substitute it for the current coordinate unless you have a deliberate, compatibility-tested reason.

Do not assume Selenium’s version, HtmlUnit’s version and the driver’s version should be numerically identical. Resolve the three-way combination from the project’s table, then run your test suite on the same JDK used by CI.

Add the Maven dependency

In pom.xml, add the driver dependency shown by the current README. Replace the example version if the compatibility table identifies another release for your Selenium line.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>htmlunit3-driver</artifactId>
    <version>4.48.0</version>
</dependency>

Let Maven resolve the transitive Selenium and HtmlUnit components, then inspect the dependency tree if another library forces an incompatible version. A clean build on the same JDK as your test runner catches Java-release problems early.

Add the Gradle dependency

For Gradle, use the equivalent declaration:

implementation group: 'org.seleniumhq.selenium', name: 'htmlunit3-driver', version: '4.48.0'

Use the version confirmed for your Selenium line rather than treating 4.48.0 as a timeless value. If dependency resolution selects multiple Selenium or HtmlUnit versions, align them explicitly after consulting the project’s compatibility information.

Create your first HtmlUnitDriver

JavaScript disabled by default

The no-argument constructor creates a driver with JavaScript disabled. This is appropriate for pages whose required behavior is server-rendered HTML and for tests that should fail when they accidentally depend on client-side code.

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;

public class HtmlUnitSmokeTest {
    public static void main(String[] args) {
        WebDriver driver = new HtmlUnitDriver();
        try {
            driver.get("https://example.com");
            System.out.println(driver.getTitle());
        } finally {
            driver.quit();
        }
    }
}

Enable JavaScript explicitly

Pass true when the application needs JavaScript:

WebDriver driver = new HtmlUnitDriver(true);

The boolean constructor is the clearest choice when JavaScript is the only option you need to change. Keep the quit() call in a finally block so failed assertions do not leave resources behind.

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

Select a simulated browser version

Import HtmlUnit’s BrowserVersion and select the profile your page expects. The browser profile changes HtmlUnit’s simulated user-agent and browser behavior; it does not start a full Firefox, Chrome or Edge binary.

import com.gargoylesoftware.htmlunit.BrowserVersion;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;

WebDriver firefoxProfile = new HtmlUnitDriver(BrowserVersion.FIREFOX);
WebDriver firefoxWithJs = new HtmlUnitDriver(BrowserVersion.FIREFOX, true);

The one-argument browser constructor leaves JavaScript disabled. Use the browser-version-plus-boolean constructor when you need both a profile and JavaScript. Choose the profile deliberately and document it in the test, because changing it can alter user-agent checks and script branches.

Use HtmlUnitDriverOptions for controlled behavior

For settings beyond the constructor, create HtmlUnitDriverOptions. The project README demonstrates options customization, including optThrowExceptionOnScriptError. Enabling that option turns otherwise reported script errors into test failures, which is useful when JavaScript correctness is part of the assertion.

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;
import org.openqa.selenium.htmlunit.HtmlUnitDriverOptions;

HtmlUnitDriverOptions options = new HtmlUnitDriverOptions();
options.optThrowExceptionOnScriptError(true);

WebDriver driver = new HtmlUnitDriver(options);
try {
    driver.get("https://example.com");
    System.out.println(driver.getPageSource());
} finally {
    driver.quit();
}

Keep options close to the test fixture that needs them. A global “throw on every script warning” policy can make an otherwise unrelated page fail, while a targeted fixture can expose defects earlier.

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.

A complete Selenium Java test example

The following JUnit 5 test uses JavaScript, waits for a title, checks a link and always closes the driver. It is intentionally DOM-oriented; it does not claim that HtmlUnit renders the page like a desktop browser.

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;

class HtmlUnitExampleTest {
    private WebDriver driver;

    @BeforeEach
    void setUp() {
        driver = new HtmlUnitDriver(true);
    }

    @AfterEach
    void tearDown() {
        if (driver != null) {
            driver.quit();
        }
    }

    @Test
    void readsExamplePage() {
        driver.get("https://example.com");

        assertEquals("Example Domain", driver.getTitle());
        assertTrue(driver.findElement(By.cssSelector("h1")).isDisplayed());
    }
}

For a real application, replace the URL and selectors with stable test hooks. HtmlUnit’s JavaScript support is described as continually improving, not as complete browser parity, so a script-heavy single-page application may require a real-browser run as a second test layer.

Waits, navigation and page state

HtmlUnit often completes simple navigation synchronously, but application state can still depend on scripts, redirects or asynchronous requests. Prefer an explicit Selenium wait over arbitrary sleeps when a condition is observable:

import java.time.Duration;
import org.openqa.selenium.support.ui.WebDriverWait;

WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
wait.until(d -> d.findElement(By.id("ready")).isDisplayed());

If the condition never becomes true, determine whether JavaScript is disabled, the selector is wrong, the page requires an unsupported Web API, or the navigation failed. A longer timeout cannot repair an engine incompatibility.

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

Or skip the browser setup

If your goal is a clean page image or PDF rather than interactive Selenium assertions, ScreenshotNeo provides a single HTTP request. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups and chat widgets; each cleanup step can be disabled. Only clean shots are billed: bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits cost nothing, and the response identifies the result with X-Page-Verdict and X-Billed headers.

See the ScreenshotNeo API documentation for all options.

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

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://example.com"},
    timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const image = Buffer.from(await res.arrayBuffer());
await Bun.write('shot.webp', image);

ScreenshotNeo also offers an MCP server with take_screenshot, get_page_info and capture_pdf tools for Claude, Cursor and other MCP clients. Every plan includes every feature; 1,000 screenshots per month are free with no card, and paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account to try it.

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

Troubleshoot common failures

Dependency cannot be resolved

Confirm that the coordinate is htmlunit3-driver, not the older htmlunit-driver, and that the selected version exists in your configured repository. Then inspect Maven’s or Gradle’s dependency tree for an exclusion or forced version.

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.

Unsupported class-file or Java-release error

Run the build with the JDK required by the artifact. HtmlUnit 5.0.0 and later require JDK 17 or newer, and current driver build metadata targets release 17. If your project must remain on an older JDK, select a release whose compatibility table explicitly supports it rather than suppressing the compiler error.

Elements are missing

First check whether you constructed the driver with JavaScript disabled. If scripts are enabled, verify the selector after redirects and wait for the element’s actual condition. If the page relies on a browser API HtmlUnit does not implement, validate that flow in a real target browser.

Script errors are hidden

Configure HtmlUnitDriverOptions with optThrowExceptionOnScriptError(true) when script failures should fail the test. Otherwise, capture page source and browser logs available through your chosen Selenium version to identify the failing code path.

Behavior differs from Chrome or Firefox

That difference is expected for a simulator. Check the selected BrowserVersion, user-agent-dependent branches and unsupported APIs, then run the same scenario in the real browser engines your users operate.

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

Driver processes remain after a failure

Always call quit() in teardown or a finally block. Do not rely on garbage collection to close a test session.

Performance, reliability and test strategy

The sources do not establish a universal speed or resource benchmark for HtmlUnitDriver, so measure startup time, suite duration and memory in your own CI environment before making a performance claim. Its practical advantage is that it avoids managing a visible desktop browser; its trade-off is simulator-specific behavior.

  • Use HtmlUnit for fast feedback on HTTP, DOM, forms, cookies, navigation and selected JavaScript paths.
  • Keep a real-browser suite for layout, graphics, browser APIs, media, accessibility integration and high-fidelity user journeys.
  • Pin versions together and review the compatibility table whenever Selenium, HtmlUnit, the driver or the JDK changes.
  • Record the browser profile, JavaScript setting and options in the fixture so a failure is reproducible.

FAQ

Frequently Asked Questions

Can HtmlUnitDriver run in a Selenium Grid session?

A Grid deployment requires a node and driver combination that supports this HtmlUnit implementation. Verify the selected release’s documented remote-execution support and test the exact Grid topology; do not assume a local constructor automatically maps to a remote session.

Should I enable JavaScript for every test?

No. Leave it disabled when server-rendered HTML is the subject of the test, and enable it only for flows that require client-side execution. This keeps the fixture’s assumptions explicit.

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

How can I prove a failure is caused by HtmlUnit rather than my application?

Reproduce the same URL and assertions with the selected real browser, compare the DOM and network-dependent steps, and check the HtmlUnit script-error setting. A passing real-browser run does not establish simulator parity, but the comparison usually identifies unsupported browser behavior.

The Bottom Line

Use the current htmlunit3-driver coordinate, match it to Selenium, HtmlUnit and JDK versions in the project compatibility table, and choose JavaScript and BrowserVersion deliberately. HtmlUnitDriver is valuable for headless DOM and workflow tests, but real browsers remain necessary wherever exact user-facing behavior matters.

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.