A complete Playwright Java cheat sheet: everything from launching a browser to network mocking and API testing, with the Java method names and options objects you'll actually type. It ends with a one-page quick reference card you can print. For the TypeScript version, see the Playwright cheat sheet.

PLAYWRIGHT (JAVA)

Complete API Reference & Cheat-Sheet

Every locator, action, assertion, option & command in one place

Playwright 1.63 | Java 17 | JUnit 5 & TestNG | Maven & Gradle

How to use this reference

This is a lookup document, not a tutorial — keep it open while you code. Everything is grouped by object (Locator, Page, assertions, network, options). The last page is a one-glance cheat-sheet. For the "why" and worked examples, use the Phase notes; for interview practice, use the Question Bank.

Java Bindings vs the TypeScript Test Runner — Read This First

Most Playwright content online uses the TypeScript "Playwright Test" runner. The Java binding is the SAME browser-automation library but does NOT include that runner — you use JUnit 5 or TestNG instead. Knowing this prevents a lot of confusion and is a common interview trap.

FeatureTypeScript (Playwright Test)Java
Browser automation APIYesYes — identical (Page, Locator, etc.)
Locators / auto-wait / assertionsYesYes — identical
Tracing / video / network mockingYesYes — identical
Built-in test runnerplaywright.config.tsNo — use JUnit 5 / TestNG
Fixtures (test.use, worker fixtures)YesNo — use @BeforeEach / factory
Projects (config matrix)YesNo — use params / testng.xml
Built-in parallelism & shardingYesVia JUnit/TestNG + Surefire
UI Mode / test.step / expect.pollYesNo — use trace viewer / helpers
Codegen, Inspector, Trace ViewerYesYes — via CLI
Web-first assertionsexpect(locator)assertThat(locator) (PlaywrightAssertions)
One-line summary

In Java: Playwright gives you the browser engine + locators + assertions; JUnit 5 or TestNG gives you the test lifecycle, parameterization, parallelism and reporting. When a tutorial mentions config files, projects or fixtures, that is the TS runner — the Java equivalent is your JUnit/TestNG base class and factory.

Advertisement

Setup & CLI Commands

CommandPurpose
mvn compileCompile before running the CLI
...CLI -Dexec.args="install"Download Chromium, Firefox, WebKit
...CLI -Dexec.args="install --with-deps"Also install OS dependencies (CI/Linux)
...CLI -Dexec.args="install chromium"Install one browser only
...CLI -Dexec.args="codegen <url>"Record actions → generate Java code
...CLI -Dexec.args="open <url>"Open a page with the Inspector
npx playwright show-trace trace.zipOpen the Trace Viewer
PWDEBUG=1 mvn testRun with the Inspector (step through)

CLI mainClass is com.microsoft.playwright.CLI — full form:

mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="install"

Core Objects — Key Methods

Playwright / BrowserType / Browser

MethodReturns / Purpose
Playwright.create()Entry point (close in try-with-resources)
playwright.chromium() / firefox() / webkit()A BrowserType
playwright.request()APIRequest (for API testing)
playwright.selectors()Custom/testId selector config
browserType.launch(LaunchOptions)Launch a Browser
browserType.launchPersistentContext(dir, opts)Reuse a real profile dir
browserType.connect(wsEndpoint)Connect to a remote/cloud browser
browser.newContext(NewContextOptions)Create an isolated context
browser.newPage()Shortcut: context + page
browser.close()Close the browser

BrowserContext

MethodPurpose
context.newPage()Open a new tab/page
context.storageState(opts)Save cookies+localStorage to JSON
context.addCookies(list)Inject cookies
context.clearCookies()Clear cookies
context.grantPermissions(list)e.g. geolocation, clipboard
context.route(url, handler)Intercept network for all pages
context.routeFromHAR(path, opts)Replay recorded network
context.tracing()Start/stop tracing
context.setDefaultTimeout(ms)Default action timeout
context.setDefaultNavigationTimeout(ms)Default navigation timeout
context.close()Close context (saves video)

Locators — Creation

All of these exist on both Page (page.getBy...) and Locator (for scoping inside another locator).

LocatorFinds byExample
getByRole(role, opts)ARIA role + accessible namegetByRole(BUTTON, name("Save"))
getByText(text/regex)Visible text (substring)getByText("Products")
getByLabel(text)Associated <label>getByLabel("Email")
getByPlaceholder(text)Placeholder attributegetByPlaceholder("Search")
getByAltText(text)Image altgetByAltText("Logo")
getByTitle(text)title attributegetByTitle("Close")
getByTestId(id)data-testid (configurable)getByTestId("submit")
locator(selector)CSS / XPath / text enginelocator("#id"), locator("xpath=//a")

getByRole options

new Page.GetByRoleOptions()
    .setName("Login")        // accessible name (String or Pattern)
    .setExact(true)          // exact name match
    .setChecked(true)        // checkbox/radio state
    .setPressed(true)        // toggle buttons
    .setSelected(true)       // options
    .setExpanded(true)       // expandable widgets
    .setLevel(2)             // heading level h2
    .setDisabled(false);

Refining & combining locators

MethodPurpose
.filter(setHasText / setHasNotText)Keep matches with/without text
.filter(setHas / setHasNot(locator))Keep matches containing/not a child
.and(locator)Must match both
.or(locator)Match either (e.g. success OR error)
.first() / .last() / .nth(i)Pick from a list (0-based)
.locator(sel) / .getByRole(...)Scope a search inside
.count()Number of matches (no wait)
.all()List<Locator> of all matches
.allTextContents() / .allInnerTexts()List<String> of texts

Selector Engines & Pseudo-Classes

SelectorMeaning
css=div.card / #id / .classCSS (default engine)
xpath=//button[text()="OK"]XPath engine
text=Add to cartText engine (substring, case-insensitive)
id=submit / data-testid=goAttribute engines
:has-text("Total")Element containing text (substring)
:text("OK")Smallest element with that text
:text-is("OK")Exact text
:has(button)Element that contains a match
:nth-match(:text("Add"), 2)The 2nd match overall
:visibleOnly visible elements
a >> spanChaining engines
:near(:text("Price")) / :right-of() / :below()Layout selectors (by position)
// Configure the test-id attribute name (default: data-testid)
playwright.selectors().setTestIdAttribute("data-qa");

Locator Actions (all auto-wait)

ActionPurpose
click() / dblclick()Click / double-click
click(new ClickOptions().setButton(RIGHT))Right-click, modifiers, position, force
fill(value)Clear + set value (fast)
clear()Empty an input
pressSequentially(text, opts)Type key-by-key (autocomplete)
press("Control+A")Key / combo
check() / uncheck() / setChecked(b)Checkbox / radio
selectOption(value/label/index)Native <select>
selectText()Select element text
hover()Mouse over
dragTo(target)Drag & drop
tap()Touch tap (mobile)
focus() / blur()Focus management
setInputFiles(path)File upload
scrollIntoViewIfNeeded()Scroll to element
dispatchEvent("click")Fire a DOM event directly
highlight()Debug: highlight the element
screenshot(opts)Element screenshot

Locator State & Info (no auto-wait)

These return immediately — use for reading data or branching, NOT for assertions (use web-first assertions for those).

MethodReturns
textContent() / innerText()Raw / rendered text (single element)
innerHTML()Inner HTML string
inputValue()Value of input/textarea/select
getAttribute("href")Attribute value or null
isVisible() / isHidden()boolean (immediate)
isEnabled() / isDisabled()boolean
isEditable() / isChecked()boolean
boundingBox()x/y/width/height
evaluate(js) / evaluateAll(js)Run JS on element / all matches
ariaSnapshot()YAML accessibility snapshot

Web-First Assertions (auto-retrying)

import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;

Locator assertions

AssertionPasses when the element...
isVisible() / isHidden()is / is not visible
isEnabled() / isDisabled()is enabled / disabled
isEditable()is editable
isChecked() / isChecked(setChecked(false))checkbox is checked / unchecked
isFocused()has focus
isEmpty()has no text/children
isAttached() / isInViewport()is in DOM / in viewport
hasText(t) / containsText(t)exact / substring text (t may be regex/List)
hasValue(v) / hasValues(list)input value / multiselect values
hasAttribute(name, value)attribute equals value
hasClass(c) / hasId(id)class / id matches
hasCSS(prop, value)computed CSS matches
hasJSProperty(name, value)JS property equals value
hasCount(n)exactly n elements match
matchesAriaSnapshot(yaml)a11y tree matches snapshot

Page & APIResponse assertions; negation & timeout

assertThat(page).hasTitle("Swag Labs");
assertThat(page).hasURL(Pattern.compile(".*inventory.*"));
assertThat(apiResponse).isOK();                 // 2xx

// Negation with not()
assertThat(page.getByText("Error")).not().isVisible();

// Per-assertion timeout
assertThat(locator).isVisible(
    new LocatorAssertions.IsVisibleOptions().setTimeout(10000));

// Global assertion timeout
PlaywrightAssertions.setDefaultAssertionTimeout(10000);

Waiting & Timeouts

CallWaits for
(auto-wait)Actionability before every action
locator.waitFor(setState(VISIBLE/HIDDEN/ATTACHED/DETACHED))An element state
page.waitForURL("**/x")Navigation to a URL
page.waitForResponse("**/api", () -> action)A specific network response
page.waitForRequest("**/api", () -> action)A specific request
page.waitForLoadState(LOAD/DOMCONTENTLOADED/NETWORKIDLE)A load state
page.waitForFunction("() => window.ready")A JS predicate to be true
page.waitForPopup(() -> action)A new tab/popup
page.waitForDownload(() -> action)A download to start
page.waitForCondition(() -> boolean)A Java predicate

Page — Advanced APIs

Running JavaScript (the JavascriptExecutor equivalent)

// Return a value from the page
String title = (String) page.evaluate("() => document.title");
int height = (int) page.evaluate("() => document.body.scrollHeight");

// Pass arguments
page.evaluate("([a, b]) => a + b", java.util.List.of(2, 3));

// Operate on a specific element
page.getByTestId("row").evaluate("el => el.scrollIntoView()");

// Run script on EVERY new document (e.g. stub a global before app loads)
page.addInitScript("window.isAutomated = true;");

// Wait until a JS condition holds
page.waitForFunction("() => document.querySelectorAll('.row').length > 10");

Page events (listen to the browser)

Event handlerFires on
page.onConsoleMessage(m -> ...)console.log/warn/error
page.onPageError(e -> ...)Uncaught JS exceptions
page.onRequest / onResponse / onRequestFailedNetwork activity
page.onDialog(d -> ...)alert/confirm/prompt
page.onDownload(d -> ...)File download
page.onPopup(p -> ...)New tab/popup
page.onWebSocket(ws -> ...)WebSocket opened
page.onFileChooser(fc -> ...)File input opened
// Example: fail the test if the page logs a JS error
page.onPageError(err -> { throw new RuntimeException("JS error: " + err); });
page.onConsoleMessage(msg -> {
    if ("error".equals(msg.type())) System.out.println("Console error: " + msg.text());
});

Emulation, clock & misc

// Dark mode / print media
page.emulateMedia(new Page.EmulateMediaOptions()
    .setColorScheme(ColorScheme.DARK));

// Freeze / control time (clock API)
page.clock().install();
page.clock().setFixedTime(java.time.Instant.parse("2026-01-01T00:00:00Z"));
page.clock().fastForward("30:00");    // advance 30 minutes

page.setViewportSize(1280, 720);
page.addStyleTag(new Page.AddStyleTagOptions().setContent("* {animation:none!important}"));
page.bringToFront();

Keyboard & Mouse

CallPurpose
page.keyboard().press("Enter")Press a key/combo
page.keyboard().type("hello")Type text
page.keyboard().down("Shift") / up("Shift")Hold / release
page.keyboard().insertText("é")Insert without key events
page.mouse().move(x, y) / click(x, y)Move / click at coords
page.mouse().down() / up()Press / release
page.mouse().wheel(0, 500)Scroll

Common keys: Enter, Tab, Escape, Backspace, Delete, ArrowUp/Down/Left/Right, Home, End, PageUp, PageDown, F1-F12. Modifiers: Control, Shift, Alt, Meta (e.g. "Control+Shift+K").

Options Objects (most-used setters)

LaunchOptions

new BrowserType.LaunchOptions()
    .setHeadless(false).setSlowMo(300)
    .setChannel("chrome")          // chrome / msedge
    .setArgs(List.of("--start-maximized"))
    .setProxy("http://proxy:8080")
    .setDownloadsPath(Paths.get("downloads"))
    .setTracesDir(Paths.get("traces"))
    .setTimeout(30000);

NewContextOptions

new Browser.NewContextOptions()
    .setViewportSize(1920, 1080)
    .setBaseURL("https://site.com")
    .setLocale("en-US").setTimezoneId("Asia/Kolkata")
    .setGeolocation(12.97, 77.59).setPermissions(List.of("geolocation"))
    .setColorScheme(ColorScheme.DARK)
    .setIsMobile(true).setHasTouch(true).setDeviceScaleFactor(2)
    .setUserAgent("...")
    .setHttpCredentials("user", "pass")   // basic auth
    .setOffline(true)
    .setStorageStatePath(Paths.get("auth/state.json"))
    .setRecordVideoDir(Paths.get("videos"))
    .setRecordHarPath(Paths.get("net.har"))
    .setIgnoreHTTPSErrors(true)
    .setExtraHTTPHeaders(Map.of("X-Env", "qa"));

API Testing — APIRequestContext

APIRequestContext api = playwright.request().newContext(
    new APIRequest.NewContextOptions()
        .setBaseURL("https://api.site.com")
        .setExtraHTTPHeaders(Map.of("Authorization", "Bearer " + token)));
CallPurpose
api.get / post / put / patch / delete / head / fetchHTTP methods
RequestOptions.create().setData(obj/json)JSON/raw body
.setForm(FormData) / .setMultipart(...)Form / file upload body
.setQueryParam(k, v)Query string
.setHeader(k, v) / .setTimeout(ms)Per-request header/timeout
response.status() / statusText() / ok()Status info
response.text() / body()Body as String / bytes (parse w/ Jackson)
response.headers() / headersArray()Response headers
response.dispose()Free the response

Network & Routing

CallPurpose
page.route(glob, handler)Intercept matching requests
context.route(glob, handler)Intercept for whole context
page.unroute(glob)Remove a route
route.fulfill(FulfillOptions)Return a mock response
route.abort() / abort("failed")Block the request
route.resume() / fallback()Continue / defer to next handler
route.fetch()Get the real response (to modify)
context.routeFromHAR(path, opts)Replay recorded traffic
page.waitForResponse / waitForRequestSync on a call

route.fulfill(new Route.FulfillOptions()

.setStatus(200).setContentType("application/json")
.setBody("{\"ok\":true}"));    // or .setPath(file) / .setResponse(apiResp)

TestNG Reference (Selenium-shop favourite)

Annotation / FeaturePurpose
@Test(priority=, groups=, enabled=)A test; ordering / grouping
@BeforeMethod / @AfterMethodPer-test setup/teardown (context+page)
@BeforeClass / @AfterClassPer-class (browser)
@BeforeSuite / @AfterSuiteOnce per suite
@DataProviderData-driven Object[][]
dependsOnMethods / dependsOnGroupsOrdering by dependency
@Test(invocationCount=, threadPoolSize=)Repeat / concurrency
IRetryAnalyzerRetry failed tests
ITestListener / ISuiteListenerHooks for reporting/screenshots
ITestContext / ITestResultRuntime info in listeners
<!-- testng.xml — parallel across methods with a thread pool -->
<suite name="pw" parallel="methods" thread-count="4">
  <test name="regression">
    <classes><class name="tests.LoginTest"/></classes>
  </test>
</suite>
@DataProvider(name = "logins", parallel = true)
public Object[][] logins() {
    return new Object[][] {{"standard_user","secret_sauce"}, {"locked_out_user","secret_sauce"}};
}
@Test(dataProvider = "logins", retryAnalyzer = Retry.class)
public void login(String u, String p) { ... }

JUnit 5 Reference

Annotation / FeaturePurpose
@Test / @DisplayNameA test + readable name
@BeforeEach / @AfterEachPer-test (context+page)
@BeforeAll / @AfterAllPer-class (browser) — static
@ParameterizedTestData-driven test
@ValueSource / @CsvSource / @CsvFileSourceInline / CSV data
@MethodSource / @ArgumentsSourceProgrammatic data (Excel/JSON)
@Tag("smoke")Group & filter (-Dgroups=smoke)
@RepeatedTest(n) / @OrderRepeat / order
@ExtendWith(Watcher.class)Extensions (failure capture)
@Timeout / assertAllTimeout / soft-ish grouped asserts
# junit-platform.properties — parallel execution
junit.jupiter.execution.parallel.enabled = true
junit.jupiter.execution.parallel.mode.default = concurrent
junit.jupiter.execution.parallel.config.strategy = fixed
junit.jupiter.execution.parallel.config.fixed.parallelism = 4

Maven & Gradle

Maven — run commands

mvn clean test
mvn test -Dbrowser=firefox -Dheadless=true
mvn test -Dgroups=smoke              # JUnit tags via Surefire
mvn test -Dtest=LoginTest#validLogin # single method
mvn test -DsuiteXmlFile=testng.xml   # TestNG suite

Gradle — equivalent setup

// build.gradle
dependencies {
    implementation "com.microsoft.playwright:playwright:1.63.0"
    testImplementation "org.junit.jupiter:junit-jupiter:5.11.3"
}
test {
    useJUnitPlatform()
    systemProperty "browser", System.getProperty("browser", "chromium")
}
// Install browsers:
// gradle -q compileJava; then run the CLI main class, or use a Playwright Gradle exec task

One-Glance Cheat-Sheet

Launch → Act → Assert (the whole loop)
  • Playwright pw = Playwright.create();
  • Browser b = pw.chromium().launch(new LaunchOptions().setHeadless(false));
  • Page page = b.newContext(new NewContextOptions().setBaseURL(url)).newPage();
  • page.navigate("/");
  • page.getByRole(BUTTON, name("Login")).click();
  • assertThat(page.getByText("Products")).isVisible();

Locator picks (in priority order)

page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Save"))
page.getByLabel("Email")   page.getByPlaceholder("Search")   page.getByText("Products")
page.getByTestId("submit")
page.locator("#id")   page.locator("xpath=//a")   // last resort

Top assertions

assertThat(loc).isVisible();     assertThat(loc).hasText("x");
assertThat(loc).hasCount(3);     assertThat(loc).isEnabled();
assertThat(input).hasValue("x"); assertThat(page).hasURL(pattern);

Handle anything

Dropdown : loc.selectOption("value")

Checkbox : loc.check() / assertThat(loc).isChecked()

Dialog : page.onDialog(d -> d.accept()); // register BEFORE click

Frame : page.frameLocator("#f").getByRole(...)

Tab : Page p = page.waitForPopup(() -> click)

Upload : loc.setInputFiles(Paths.get("f.pdf"))

Download : page.waitForDownload(() -> click).saveAs(path)

Network : page.route("**/api", r -> r.fulfill(...))

JS : page.evaluate("() => document.title")

Trace : context.tracing().start(...) / stop(setPath("t.zip"))

Golden rules

  • Prefer getByRole/getByTestId over XPath.
  • Use web-first assertThat(...) for UI state; never Thread.sleep().
  • One BrowserContext + Page per test; ThreadLocal for parallel.
  • storageState() to skip logins; API to seed data.
  • Debug failures with the Trace Viewer, not print statements.

Keep this open while you build. 📖

One-Page Quick Reference Card

PLAYWRIGHT (JAVA) — QUICK REFERENCE CARD

Playwright 1.63 | Java 17 | print & pin to your desk

CLI & RUN

Install browsers...CLI -Dexec.args="install --with-deps"
Codegen (record)...CLI -Dexec.args="codegen <url>"
Run allmvn test
One browsermvn test -Dbrowser=firefox
One methodmvn test -Dtest=LoginTest#valid
View tracenpx playwright show-trace trace.zip
InspectorPWDEBUG=1 mvn test / page.pause()

BOOT (launch → act → assert)

Playwright pw = Playwright.create();
Browser b = pw.chromium().launch(new LaunchOptions().setHeadless(false));
Page page = b.newContext(new NewContextOptions().setBaseURL(url)).newPage();
page.navigate("/");
page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Login")).click();
assertThat(page.getByText("Products")).isVisible();
LOCATORS  (priority: role → label/text → testId → css → xpath)
By rolegetByRole(AriaRole.BUTTON, opts.setName("Save"))
By label/phgetByLabel("Email") / getByPlaceholder("Search")
By textgetByText("Products", opts.setExact(true))
By test idgetByTestId("submit")
CSS / XPathlocator("#id") / locator("xpath=//a")
Filterloc.filter(new FilterOptions().setHasText("X"))
Pickloc.first() / last() / nth(i) / count()
Combineloc.and(x) / loc.or(x)

ACTIONS (all auto-wait)

Type/clearfill(v) / clear() / pressSequentially(v)
Click/keyclick() / dblclick() / press("Control+A")
Checkcheck() / uncheck() / setChecked(b)
DropdownselectOption(value|label|index)
Mousehover() / dragTo(t) / scrollIntoViewIfNeeded()
FilessetInputFiles(Paths.get("f.pdf"))

WEB-FIRST ASSERTIONS (assertThat(...), auto-retry)

VisibilityisVisible() / isHidden() / isEnabled() / isDisabled()
StateisChecked() / isEditable() / isFocused() / isEmpty()
TexthasText(t) / containsText(t)
Value/attrhasValue(v) / hasAttribute(n,v) / hasClass(c) / hasCSS(p,v)
CounthasCount(n)
PageassertThat(page).hasTitle(t) / hasURL(regex)
Negate/timeoutnot().isVisible() / isVisible(opts.setTimeout(ms))

WAITING (never Thread.sleep)

URL / loadpage.waitForURL("**/x") / waitForLoadState(...)
Responsepage.waitForResponse("**/api", () -> click())
Stateloc.waitFor(opts.setState(HIDDEN))
JS predicatepage.waitForFunction("() => window.ready")
Defaultscontext.setDefaultTimeout(ms)

HANDLE ANYTHING

Dialogpage.onDialog(d -> d.accept()) // before trigger
Framepage.frameLocator("#f").getByRole(...)
New tabPage p = page.waitForPopup(() -> click)
Downloadpage.waitForDownload(() -> click).saveAs(path)
Uploadloc.setInputFiles(Paths.get("f.pdf"))
Run JSpage.evaluate("() => document.title")
Network mockpage.route("**/api", r -> r.fulfill(opts))
Blockpage.route("**/*.png", r -> r.abort())
Tracecontext.tracing().start(...) / stop(setPath("t.zip"))
Screenshotpage.screenshot(opts.setFullPage(true))

FRAMEWORK SKELETON (JUnit 5)

@BeforeAll static  launch browser
@BeforeEach        context = browser.newContext(); page = context.newPage();
@Test              new LoginPage(page).loginAs(u,p); assertThat(...).isVisible();
@AfterEach         context.close();
@AfterAll static   browser.close(); playwright.close();

POM: locators as fields, actions as methods, return next page.

Parallel: ThreadLocal<Page/Context>. Skip login: storageState().

API (built-in)

APIRequestContext api = pw.request().newContext(opts.setBaseURL(base));
APIResponse r = api.post("/users", RequestOptions.create().setData(map));
assertEquals(201, r.status());  JsonNode j = mapper.readTree(r.text());

GOLDEN RULES: getByRole/testId over XPath • web-first assertThat over sleep • one Context+Page per test • debug with traces