Execute JavaScript in the Browser REPL

Execute JavaScript in a persistent Node.js Browser REPL. Start with live help:

repl.help();                         // List methods
repl.help("click");                  // Signature, behavior, defaults, and example
repl.help("webmcp.invokeTool");

Available methods:

<!-- BEGIN GENERATED REPL METHOD LIST -->
  • REPL: repl.help, repl.write, repl.emitImage
  • Browser control: cdp, drainEvents, waitForEvent, gotoUrl, pageInfo, accessibilitySnapshot, click, typeText, fillInput, pressKey, scroll, captureScreenshot, listTabs, currentTab, switchTab, newTab, closeTab, ensureRealTab, iframeTarget, waitMs, waitForLoad, waitForElement, waitForNetworkIdle, js, uploadFile, httpGet
  • WebMCP: webmcp.listTools, webmcp.invokeTool, webmcp.addCustomTools, webmcp.listCustomTools, webmcp.removeCustomTool
<!-- END GENERATED REPL METHOD LIST -->

Browser-control methods are available both directly and on browser. The same frozen browser-wide WebMCP client is available as webmcp and browser.webmcp, including custom tool add, list, and remove methods. webmcp.listTools() discovers tools through GET /webmcp/tools, and webmcp.invokeTool() calls POST /webmcp/invoke. Common workflows:

await gotoUrl("https://example.com");
await waitForLoad();
const tree = await accessibilitySnapshot();
const link = tree.nodes.find(node => node.role === "link" && node.name === "More information...");
if (!link) throw new Error("link not found");
await click(link);

const path = await captureScreenshot("/tmp/page.png", true, 1600);
await repl.emitImage({path});

Top-level bindings and dynamically imported modules persist until reset or process replacement. Expression values are ignored; emit output with repl.write(...), console methods, or repl.emitImage(...). Pinned patchright and playwright-core packages are available through dynamic import(), and cdp() provides unrestricted DevTools access.

The runtime starts lazily and is owned by the API process. Reset, API restart, timeout, crash, OOM, or protocol failure destroys its state and changes its CUID2 repl_id. Executions are serialized. This endpoint is unrestricted code execution inside the browser VM, equivalent in trust level to the process and Playwright execution APIs; it is not sandboxed.

post/repl

Request body

codestring required

JavaScript evaluated in a persistent Node.js runtime. Top-level bindings persist until the API process exits, the REPL is reset, or the REPL is terminated after a crash or timeout. Persistent names are live context-global accessors: closures and timers observe later-cell assignments. Function declarations use the same accessor path, including same-cell closures and assignments. Braceless multi-declarator var statements retain their single-statement control-flow semantics. var in top-level nested statements persists; function and nested-block locals do not. Function .name is preserved; Function.prototype.toString() may expose the generated internal alias. Lexical names are reserved after linking, so retry a failed declaration with a new name or reset the REPL. A failed lexical initializer leaves that name in the TDZ; assignments cannot initialize it. Static top-level imports are rejected; use dynamic import(). Expression values are not returned automatically. Output is optional; code may produce no content, call repl.write(...) or repl.emitImage(...), use console methods, or combine those mechanisms. May be empty only when reset is true. The HTTP body is limited to 8 MiB, and the API rejects a fully encoded daemon request over the daemon's 8 MiB request-line limit without terminating the REPL.

timeout_secinteger

Maximum execution time in seconds. Default is 60.

resetboolean

Terminate the current REPL, start a fresh one, and then evaluate code.

Response

Code executed (success or structured failure)

successboolean required

Whether the code executed successfully

repl_idstring required

CUID2 identifying the exact state-holding REPL process used for this execution. Stable across calls and Chromium reconnects; changes after an API restart, explicit reset, execution timeout, or REPL crash.

errorstring

Error message if execution failed

stackstring

Stack trace if execution failed

content_truncatedboolean

True if text or image output was dropped or truncated due to response limits, including the 1,000-item cap on stray output buffered between executions

repl_terminatedboolean

True if the REPL identified by repl_id was terminated by this request (timeout, protocol corruption, or a REPL crash/uncaught exception). The next request lazily starts a fresh REPL with a new repl_id.

duration_msinteger

Wall-clock execution time in milliseconds

Changes

Changed in 1 of the 65 revisions of this API.1