KMPwright

Introduction

KMPwright is a Kotlin Multiplatform browser automation library with a Playwright-style API and agent-browser commands for Android WebView, iOS WKWebView and Chromium on the JVM.

KMPwright lets you write browser automation once, in shared Kotlin, and run it against:

  • an Android WebView your app already shows,
  • an iOS WKWebView your app already shows,
  • a Chromium you launch or connect to over the Chrome DevTools Protocol (CDP) on the JVM.

The API follows Playwright names (goto, locator, getByRole, fill, expect, route) and adds the agent features of Vercel's agent-browser: accessibility snapshots with @e refs, page.runCommand("click @e3"), allowed domains, action policies and content boundaries.

Version 0.0.1 is available on Maven Central. This is an alpha release; APIs and platform coverage may change. See Installation.

Who it is for

  • App developers who embed web content and want to test, drive or inspect it from Kotlin on the device itself.
  • Agent builders who want to give an LLM a browser tool inside a mobile app or a JVM service, using the same command grammar as agent-browser.
  • Playwright users writing Kotlin Multiplatform code who want familiar names and semantics.

The 30-second example

The same Page works on every backend. An agent drives it with text commands; your code drives it with typed calls.

// Hand this to an LLM as a single "browser" tool.
page.runCommand("open example.com")
val snapshot = page.runCommand("snapshot -i")
println(snapshot.output)
// @e1 [heading] "Example Domain" [level=1]
// @e2 [link] "Learn more"

page.runCommand("click @e2")
println(page.runCommand("get title").output)

runCommand accepts the documented subset of agent-browser commands, returns plain text for the model in output, and also returns structured data (snapshot, screenshot) when a command produces it. See Coming from agent-browser for the supported commands.

How you get a page

BackendEntry pointPage source
Android WebViewBrowser(AndroidPlatformContext(activity, webView))browser.page() attaches to your WebView
iOS WKWebViewBrowser(IOSPlatformContext(webView = webView))browser.page() attaches to your WKWebView
JVM Chromium (owned)launchBrowser(executablePath)launched.browser.newPage()
JVM Chromium (existing or cloud)Browser(JvmPlatformContext(), KmpwrightConfig(cdp = CdpConfig(...)))browser.newPage() or browser.attachTarget(id)

Step-by-step setup is in the Quick start.

What works where

Most APIs live in commonMain and run on every backend. Where a backend can only do part of the job, page.capabilities() reports it as Supported, Partial or Unsupported, with human-readable notes that explain the gap. Check them before a workflow starts with page.requireCapabilities(...).

AreaAndroid WebViewiOS WKWebViewJVM Chromium (CDP)
Locators, actions, assertions, snapshotsYes (DOM input)Yes (DOM input)Yes (trusted CDP input)
Keyboard / mouse / touchSupported / Partial / SupportedPartial / Partial / PartialSupported / Supported / Partial
Request routing (route)PartialPartialSupported
Allowed domainsPartialSupportedSupported
Isolated browser contextsUnsupportedPartialSupported
Init scriptsPartialSupportedSupported
Network throttlingPartial (offline only)Partial (offline only)Supported
Downloads, file chooserUnsupportedUnsupportedSupported, Partial
Tracing, profiling, video, screencastUnsupportedUnsupportedSupported
PDFPartialPartialPartial

The full matrix, with each capability's notes, is in Capabilities.

Where to go next

On this page