Kernel Browser Playwright API

Execute Playwright code against the browser instance.

Operations 3

POST /browsers/{id_or_name}/playwright/execute Execute Playwright/TypeScript code against the browser #
GET /browsers/{id_or_name}/playwright/executors List Playwright executors #
DELETE /browsers/{id_or_name}/playwright/executors/{name} Delete a Playwright executor #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/kernel:kernel-browser-playwright-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

kernel-browser-playwright-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  description: Developer tools and cloud infrastructure for AI agents to use web browsers
  title: Kernel Browser Playwright API
  version: 0.1.0
servers:
- description: API Server
  url: https://api.onkernel.com
security:
- bearerAuth: []
tags:
- description: Execute Playwright code against the browser instance and manage the executors it runs in.
  name: Browser Playwright
paths:
  /browsers/{id_or_name}/playwright/execute:
    post:
      description: 'Execute arbitrary Playwright code in a fresh execution context against the browser.

        The code runs in the same VM as the browser, minimizing latency and maximizing throughput.

        It has access to ''page'', ''context'', ''browser'', and ''webmcp'' variables.

        Use ''webmcp.listTools()'' to discover browser-wide WebMCP tools and

        ''webmcp.invokeTool(toolRef, input?, { timeoutSec? })'' to invoke an exact registration.

        It can `return` a value, and this value is returned in the response.


        Every call runs in an executor: a dedicated Node.js process with its own browser

        connection. Calls on different executors run concurrently; calls on the same executor run

        one at a time. A timeout, crash, or blocked event loop in one executor does not affect

        other executors. After a timeout the executor keeps its process and drops its browser

        connection, so code abandoned by the timeout cannot keep driving the browser. After a

        crash or a blocked event loop, the next call on that executor starts a fresh process.


        Calls without ''executor'' run in the executor named ''default'', which always exists and is

        the same as passing ''executor: "default"''. In the default executor, ''page'' is bound to an

        active tab reported by Chrome. In single-window sessions, this is the foreground tab. When

        multiple browser windows are open, Chrome reports one active tab per window and the

        selected window is unspecified. ''context'' is the BrowserContext that owns the selected

        page. Use ''browser.contexts()'' to select a context or page explicitly.


        Pass any other name to run the call in a named executor. The first call with a new name

        creates it. Each named executor owns a tab: its first call opens a new background tab in

        the default browser context, and ''page'' is bound to that tab on every later call while it

        stays open. Opening it does not change the active tab of an existing window. If the tab is

        closed, the next call opens a new one and reports ''tab.created: true''. Executor code can

        still reach other tabs through ''context'' and ''browser''; ownership only decides what ''page''

        is bound to. Use named executors to drive several tabs of one browser in parallel.


        A browser can have at most 8 named executors; the default executor does not count. A call

        that would create another returns 409 with the current executors; delete one with

        DELETE /browsers/{id_or_name}/playwright/executors/{name}. Named executors are not removed

        automatically while the browser runs; when it shuts down, they are removed and their tabs

        closed.'
      operationId: executePlaywrightCode
      parameters:
      - description: Browser session ID or name
        example: htzv5orfit78e1m2biiifpbv
        in: path
        name: id_or_name
        required: true
        schema:
          type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ExecutePlaywrightRequest'
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExecutePlaywrightResult'
          description: Code executed successfully
        '400':
          $ref: '#/components/responses/BadRequest'
        '409':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PlaywrightExecutorLimitError'
          description: The call would create a named executor beyond the per-browser limit
        '500':
          $ref: '#/components/responses/InternalError'
        default:
          $ref: '#/components/responses/BrowserProxyError'
      security:
      - bearerAuth: []
      summary: Execute Playwright/TypeScript code against the browser
      tags:
      - Browser Playwright
  /browsers/{id_or_name}/playwright/executors:
    get:
      description: 'Lists the default executor first, then the named executors created by

        POST /browsers/{id_or_name}/playwright/execute. Each entry reports whether a call is

        running on it and, for named executors, the target ID and URL of the tab it owns.

        Returns 404 for a browser whose image predates executors.'
      operationId: listPlaywrightExecutors
      parameters:
      - description: Browser session ID or name
        example: htzv5orfit78e1m2biiifpbv
        in: path
        name: id_or_name
        required: true
        schema:
          type: string
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PlaywrightExecutorList'
          description: Open executors
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalError'
        default:
          $ref: '#/components/responses/BrowserProxyError'
      security:
      - bearerAuth: []
      summary: List Playwright executors
      tags:
      - Browser Playwright
  /browsers/{id_or_name}/playwright/executors/{name}:
    delete:
      description: 'Stops the executor''s process. A call running on it fails with an error saying the

        executor was deleted. By default the executor''s tab is closed too. The name can be

        reused; the next call with it creates a new executor and tab.


        The default executor is restarted instead of removed: its process is stopped, a call

        running on it fails with an error saying the executor was restarted, and queued and later

        calls run on a new process. It owns no tab, so ''close_tab'' has no effect on it.'
      operationId: deletePlaywrightExecutor
      parameters:
      - description: Browser session ID or name
        example: htzv5orfit78e1m2biiifpbv
        in: path
        name: id_or_name
        required: true
        schema:
          type: string
      - description: Executor name
        in: path
        name: name
        required: true
        schema:
          $ref: '#/components/schemas/PlaywrightExecutorName'
      - description: Close the executor's tab. Defaults to true.
        in: query
        name: close_tab
        required: false
        schema:
          default: true
          type: boolean
      responses:
        '204':
          description: Executor deleted
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalError'
        default:
          $ref: '#/components/responses/BrowserProxyError'
      security:
      - bearerAuth: []
      summary: Delete a Playwright executor
      tags:
      - Browser Playwright
components:
  schemas:
    PlaywrightExecutor:
      additionalProperties: false
      description: A Playwright executor on the browser
      properties:
        busy:
          description: Whether a call is running on the executor
          type: boolean
        created_at:
          description: When the executor was created
          format: date-time
          type: string
        last_used_at:
          description: When the most recent call on the executor started
          format: date-time
          type: string
        name:
          $ref: '#/components/schemas/PlaywrightExecutorName'
        target_id:
          description: CDP page target ID of the executor's tab, once it has one. The default executor owns no tab.
          type: string
        url:
          description: Current URL of the executor's tab, when it is open
          type: string
      required:
      - name
      - busy
      - created_at
      - last_used_at
      type: object
    PlaywrightExecutorLimitError:
      additionalProperties: false
      description: Returned when a call would create a named executor beyond the per-browser limit
      properties:
        executors:
          description: The default executor and the named executors that already exist
          items:
            $ref: '#/components/schemas/PlaywrightExecutor'
          type: array
        message:
          description: Human-readable error description
          type: string
      required:
      - message
      - executors
      type: object
    PlaywrightExecutorList:
      additionalProperties: false
      description: The default executor followed by the named executors
      properties:
        executors:
          items:
            $ref: '#/components/schemas/PlaywrightExecutor'
          type: array
      required:
      - executors
      type: object
    ExecutePlaywrightResult:
      additionalProperties: false
      description: Result of Playwright code execution
      properties:
        error:
          description: Error message if execution failed
          type: string
        result:
          description: The value returned by the code (if any)
        stderr:
          description: Standard error from the execution
          type: string
        stdout:
          description: Standard output from the execution
          type: string
        success:
          description: Whether the code executed successfully
          type: boolean
        tab:
          $ref: '#/components/schemas/PlaywrightTab'
      required:
      - success
      type: object
    ErrorDetail:
      properties:
        code:
          description: Lower-level error code providing more specific detail
          example: invalid_input
          type: string
        message:
          description: Further detail about the error
          example: Provided version string is not semver compliant
          type: string
      type: object
    PlaywrightExecutorName:
      description: 'Name of a Playwright executor. Calls with the same name run in the same executor, one at a

        time; the first call with a new name creates it. Calls on different executors run

        concurrently. ''default'' names the executor that runs calls without a name.

        '
      example: checkout
      pattern: ^[A-Za-z0-9_-]{1,64}$
      type: string
    Error:
      properties:
        code:
          description: Application-specific error code (machine-readable)
          example: bad_request
          type: string
        details:
          description: Additional error details (for multiple errors)
          items:
            $ref: '#/components/schemas/ErrorDetail'
          type: array
        inner_error:
          $ref: '#/components/schemas/ErrorDetail'
        message:
          description: Human-readable error description for debugging
          example: 'Missing required field: app_name'
          type: string
      required:
      - code
      - message
      type: object
    ExecutePlaywrightRequest:
      additionalProperties: false
      description: Request to execute Playwright code
      properties:
        code:
          description: 'TypeScript/JavaScript code to execute. The code has access to ''page'', ''context'', and ''browser'' variables.

            It runs within a function, so you can use a return statement at the end to return a value.

            This value is returned as the `result` property in the response.

            Example: "await page.goto(''https://example.com''); return await page.title();"

            '
          type: string
        executor:
          $ref: '#/components/schemas/PlaywrightExecutorName'
        timeout_sec:
          default: 60
          description: Maximum execution time in seconds. Default is 60.
          maximum: 300
          minimum: 1
          type: integer
      required:
      - code
      type: object
    PlaywrightTab:
      additionalProperties: false
      description: The tab 'page' was bound to for this call. Absent if the call failed before binding a tab.
      properties:
        created:
          description: 'Whether this call opened the tab. For a named executor this happens on its first call and

            after its previous tab was closed. For the default executor it happens only when the

            browser had no open page.

            '
          type: boolean
        target_id:
          description: CDP page target ID of the tab
          type: string
      required:
      - target_id
      - created
      type: object
    InstanceProxyError:
      properties:
        code:
          $ref: '#/components/schemas/InstanceProxyErrorCode'
        message:
          description: Human-readable error description for debugging
          type: string
      required:
      - code
      - message
      type: object
    InstanceProxyErrorCode:
      description: Canonical error code returned by browser instance API proxy routes
      enum:
      - invalid_request
      - unauthorized
      - forbidden
      - session_not_leased
      - not_found
      - conflict
      - session_gone
      - rate_limit_exceeded
      - internal_error
      - browser_unavailable
      type: string
  responses:
    NotFound:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
      description: Resource not found
    BadRequest:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
      description: Bad Request – invalid input
    InternalError:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
      description: Internal Server Error
    BrowserProxyError:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/InstanceProxyError'
      description: Error returned by the browser or its proxy
  securitySchemes:
    bearerAuth:
      scheme: bearer
      type: http
x-service-info:
  categories:
  - browsers
  docs:
    apiReference: https://www.kernel.sh/docs
    homepage: https://www.kernel.sh
    llms: https://api.onkernel.com/llms.txt
x-provenance:
  method: harvested
  publisher: Kernel
  source: https://api.onkernel.com/openapi.json
  note: split by refine-openapis from the provider's own published document, verified by fetch (openapi/_original/*.fetch.json);
    stamped by stamp-openapi-provenance.py (roadmap#793)