The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Playwright for Java is a Maven-distributed browser-automation API for Chromium, Firefox, and WebKit. Add the Maven module, install the matching browser binaries, then create an isolated BrowserContext for each test. Playwright’s locators wait for elements to become actionable, and web-first assertions retry until the page reaches the expected state.
This guide follows the current official Java documentation for installation, browser management, locators, testing, assertions, and tracing. Check the official installation page for the dependency version displayed when you build.
What Playwright for Java supports
The Java API drives Playwright’s supported browser engines:
- Chromium, the open-source engine used by the bundled Chromium browser.
- Firefox.
- WebKit, the engine used for Safari-style compatibility testing. Playwright does not install or automate the branded Safari application.
You can also target branded Google Chrome or Microsoft Edge through a channel when that browser is already installed. Enterprise policies can restrict control of branded browsers, so the bundled engines are usually the more reproducible choice in CI. See the browser guide for channel and binary details.
Requirements and Maven installation
Supported environments
The installation guide lists Java 8 or newer, Windows 11 or newer (or Windows Server 2019+ and WSL), macOS 14 (Sonoma) or newer, and Debian 12/13 or Ubuntu 22.04/24.04/26.04 on x86-64 or arm64. Confirm your exact operating-system support on the documentation page because these requirements can change.
Add the dependency
Playwright is published as Maven modules. Use a property so upgrading is a one-line change, and set it to the version currently shown in the Java installation documentation:
<properties>
<playwright.version>CURRENT_DOCUMENTED_VERSION</playwright.version>
</properties>
<dependency>
<groupId>com.microsoft.playwright</groupId>
<artifactId>playwright</artifactId>
<version>${playwright.version}</version>
</dependency>
Do not copy an old version from an unrelated tutorial. Each Playwright release expects corresponding browser binaries.
Install browser binaries
After Maven resolves the dependency, run the Java CLI from your project:
mvn exec:java -e -Dexec.mainClass=com.microsoft.playwright.CLI -Dexec.args="install"
On Linux, install operating-system dependencies as well when required:
mvn exec:java -e -Dexec.mainClass=com.microsoft.playwright.CLI -Dexec.args="install --with-deps"
Repeat browser installation after upgrading Playwright. The downloaded engines occupy hundreds of megabytes in typical examples, but actual disk use depends on the engines and platform. Browser cache locations and management instructions are in the browser guide.
Rank #2
Your first Java screenshot
The following program launches headless Chromium, navigates, and writes a PNG. Headless mode is the default; use setHeadless(false) when you need to watch the browser.
Free tools Windows power users keep installed
One-click scans. No signup required.
import com.microsoft.playwright.*;
public class FirstShot {
public static void main(String[] args) {
try (Playwright playwright = Playwright.create()) {
Browser browser = playwright.chromium().launch(
new BrowserType.LaunchOptions().setHeadless(true));
Page page = browser.newPage();
page.navigate("https://example.com");
page.screenshot(new Page.ScreenshotOptions()
.setPath(java.nio.file.Paths.get("example.png"))
.setFullPage(true));
browser.close();
}
}
}
For Firefox or WebKit, replace playwright.chromium() with playwright.firefox() or playwright.webkit(). A real test suite should create contexts explicitly rather than relying on a shared default page.
Contexts, pages, and test isolation
A Browser is the process; a BrowserContext is an isolated, in-memory browser profile containing cookies, local storage, permissions, and pages. Create a fresh context for every test so login state and storage cannot leak between tests:
try (Playwright pw = Playwright.create()) {
Browser browser = pw.chromium().launch();
BrowserContext context = browser.newContext();
Page page = context.newPage();
// test steps
context.close();
browser.close();
}
In a JUnit or TestNG fixture, close the context in teardown even when an assertion fails. Reuse one browser process for a class or worker if startup cost matters, but keep contexts per test.
Locators: the stable way to find elements
Playwright’s documentation describes locators as the central piece of auto-waiting and retryability. A locator resolves the element when an operation runs, rather than freezing a handle to an element found earlier. Prefer user-facing semantics:
Recommended Free Tools
Locator email = page.getByLabel("Email");
Locator submit = page.getByRole(AriaRole.BUTTON,
new Page.GetByRoleOptions().setName("Sign in"));
submit.click();
email.fill("[email protected]");
Choose the locator that expresses intent
getByRolefor buttons, links, headings, checkboxes, and other accessible roles.getByLabelfor form controls associated with a label.getByTextwhen visible text is the meaningful contract.getByPlaceholder,getByAltText, andgetByTitlewhen those attributes are intentional UI affordances.getByTestIdfor a stable test contract that is not otherwise visible to users.locator("...")for CSS or XPath only when semantic locators cannot express the target.
Dynamic lists and all()
Locator.all() returns the matches currently present; it does not wait for a changing list to finish loading. Wait for a meaningful condition first, then enumerate:
Locator rows = page.getByRole(AriaRole.ROW);
expect(rows).toHaveCount(4);
for (Locator row : rows.all()) {
System.out.println(row.innerText());
}
If the count is not fixed, wait for a specific row or loading indicator to disappear instead of assuming the network response and DOM update happen synchronously.
Auto-waiting and web-first assertions
Before actions such as click, fill, and check, Playwright waits for the locator to resolve and become actionable. Web-first assertions retry the condition until it passes or the timeout expires. The documented default assertion timeout is five seconds.
import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
assertThat(page.getByRole(AriaRole.HEADING,
new Page.GetByRoleOptions().setName("Dashboard"))).isVisible();
assertThat(page).hasTitle("Account dashboard");
assertThat(page.getByTestId("status")).hasText("Ready");
When a known operation needs longer, configure that assertion rather than adding arbitrary sleeps:
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →assertThat(page.getByTestId("report"))
.hasText("Complete", new LocatorAssertions.HasTextOptions()
.setTimeout(15_000));
Use a short explicit wait only for a documented external condition that cannot be represented by a locator or assertion. Fixed sleeps make tests slower and still fail when a page takes longer than the chosen delay.
A complete end-to-end test pattern
This JUnit-style example creates a new context per test, uses semantic locators, and asserts the eventual state:
import com.microsoft.playwright.*;
import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
import org.junit.jupiter.api.*;
class CheckoutTest {
static Playwright pw;
static Browser browser;
BrowserContext context;
Page page;
@BeforeAll static void start() {
pw = Playwright.create();
browser = pw.chromium().launch();
}
@BeforeEach void open() {
context = browser.newContext();
page = context.newPage();
}
@AfterEach void closeContext() { context.close(); }
@AfterAll static void stop() { browser.close(); pw.close(); }
@Test void userCanSubmitOrder() {
page.navigate("https://shop.example.test/checkout");
page.getByLabel("Email").fill("[email protected]");
page.getByRole(AriaRole.BUTTON,
new Page.GetByRoleOptions().setName("Place order")).click();
assertThat(page.getByRole(AriaRole.HEADING,
new Page.GetByRoleOptions().setName("Order confirmed")))
.isVisible();
}
}
Replace the example URL and labels with your application. Keep credentials in CI secrets, not source control, and use a dedicated test account when the flow changes server-side data.
Rank #4
Browser channels, headed mode, and CI choices
Bundled engine versus branded browser
Bundled Chromium, Firefox, and WebKit are tied to the Playwright release and are the predictable option for local and CI runs. A Chrome or Edge channel exercises the branded browser installed on the machine, which can reveal enterprise or vendor-specific behavior but introduces machine-level version and policy variables.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Headless versus headed
Use headless for normal CI execution. Switch to headed mode for visual diagnosis, and consider slow motion or an inspector during local debugging. Do not treat headed mode as a different test contract; it is a diagnostic presentation of the same browser automation.
CI prerequisites
- Cache the Playwright browser directory only when the cache key includes the Playwright version and operating system.
- Run the CLI browser installation in the image or job setup, including
--with-depson Linux when system libraries are absent. - Give browser processes enough shared memory and file descriptors for your parallelism.
- Use one context per test and avoid sharing mutable accounts across workers.
Tracing and failure diagnosis
Tracing records browser operations and network activity for a context, but it does not record test assertion calls such as expect. Treat a trace as a browser/session timeline, not a complete assertion log.
context.tracing().start(new Tracing.StartOptions()
.setScreenshots(true)
.setSnapshots(true)
.setSources(true));
try {
page.navigate("https://example.com");
// test actions
} finally {
context.tracing().stop(new Tracing.StopOptions()
.setPath(java.nio.file.Paths.get("trace.zip")));
}
Open the resulting archive with the Playwright trace viewer. For failure-heavy suites, configure tracing around the test lifecycle so teardown still writes a trace when an action or assertion throws. Save the trace as a CI artifact alongside the test log and screenshot.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Common errors and fixes
“Executable doesn’t exist” or browser launch failure
The matching browser binary is missing or was installed for another Playwright version. Run the Java CLI install command again, and on Linux use install --with-deps. Check that the CI cache was not restored across incompatible versions.
Timeout while locating an element
Inspect the locator’s role, accessible name, label association, frame, and visibility. Prefer a semantic locator over a brittle CSS path. If the UI is genuinely slower, increase the specific assertion or action timeout after identifying the underlying wait condition.
Best Value
Flaky iteration over results
Calling all() while a list is still loading reads a partial set. Assert a count, wait for a stable sentinel, or query a specific row before collecting results.
Trace has no assertion details
This is expected: context tracing omits assertion calls. Keep assertion messages and framework reports, and use the trace for the operations, DOM snapshots, screenshots, and network activity surrounding the failure.
Branded Chrome or Edge is blocked
Enterprise policies may prevent automation of a channel. Try the Playwright-managed engine for reproducibility, or have the browser administrator review the applicable policy before changing the test.
Or skip the browser setup
If your goal is a clean image or PDF rather than interactive assertions, ScreenshotNeo provides a single website-screenshot API call. It accepts cookie and consent banners like a visitor, removes more than 60 known consent platforms plus newsletter popups and chat widgets before capture, and reports whether a result was clean and billable. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed.
Read the parameter reference in the ScreenshotNeo documentation. cURL:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Java (using the standard HTTP client):
import java.net.URI;
import java.net.http.*;
import java.nio.file.*;
String url = "https://api.screenshotneo.com/v1/shot?access_key=YOUR_API_KEY&url=https%3A%2F%2Fstripe.com";
HttpResponse<byte[]> r = HttpClient.newHttpClient().send(
HttpRequest.newBuilder(URI.create(url)).GET().build(),
HttpResponse.BodyHandlers.ofByteArray());
Files.write(Path.of("shot.webp"), r.body());
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}`);
ScreenshotNeo also offers an MCP server with take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. Its options include full-page and element capture, dark mode, device presets, retina scale, PDF paper and page ranges, custom CSS/JavaScript, clicks, selector waits, network-idle waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, TTL caching, signed links, asynchronous webhooks, bulk capture of up to 100 URLs per call, usage reporting, and an OpenAPI specification. Every feature is on every plan: 1,000 screenshots per month free with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.
Cost, reliability, and maintenance decisions
- Version alignment: pin the Maven version and install its matching browsers; upgrade both together.
- Parallelism: separate contexts isolate state, while each additional browser process consumes memory and CPU. Measure your CI runner before increasing workers.
- Wait strategy: locators and web-first assertions adapt to normal UI latency; fixed sleeps hide race conditions.
- Diagnostics: retain traces, screenshots, console output, and assertion reports as separate artifacts because no single artifact contains every failure detail.
- Storage: browser binaries are large downloads, so cache them with a versioned key rather than assuming a permanent size or path.
Frequently Asked Questions
Can Playwright Java automate Safari itself?
No. It automates the WebKit engine for Safari-style coverage; the branded Safari application is not installed or controlled.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsWhat is the default Playwright Java assertion timeout?
The official assertions documentation lists a five-second default. Set a targeted longer timeout when a known operation needs it.
Do Playwright traces include expect calls?
No. Context tracing captures browser operations and network activity, but not test assertion calls; retain your test framework’s assertion report as well.
Should I share one BrowserContext across tests?
No. Create a fresh in-memory context per test to prevent cookies, local storage, and permissions from leaking between tests.
Quick Recap
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.

