---
canonical: "https://agi-labo.com/en/tools/cockpit/docs/cockpit-cli/reference/browser"
title: "cockpit browser"
description: "Generated reference for cockpit browser, including its syntax, options, results, and constraints from the canonical cockpit CLI source."
section: "Reference"
order: 105
pageType: reference
lastVerifiedVersion: 4.61.0
lastVerifiedAt: "2026-08-27"
draft: false
surfaces:
  - cli
operatingSystems:
  - windows
  - macos
  - linux
plans:
  - guest
  - member
navigation: false
---

This reference is generated from the same canonical source distributed as cockpit CLI help. See [Cockpit CLI](/en/tools/cockpit/docs/cockpit-cli) for concepts and safe operating guidance.

Usage: `cockpit browser <command> [options]`

Real web browsing with task-scoped in-app browser sessions: navigation, DOM inspection, screenshots, and showing the browser in the right side panel. The browser is driveable, not just viewable — use it to check a live page or verify a web UI change end-to-end even when you have no browser tool of your own.

Within a Cockpit task, this is the first-choice browser route. Use it before generic Browser plugin or IAB routes for local web app verification, visual checks, DOM inspection, screenshots, and side-panel display. Fall back to generic Browser plugin routes only when the user explicitly asks for them or `cockpit browser` is unavailable after a direct attempt.

```bash
cockpit browser identity list --json
cockpit browser identity list --in-use --json
cockpit browser identity get work --json
cockpit browser identity usages work --json
cockpit browser identity create --name work --color "#3B82F6" --json
cockpit browser identity update work --name client-a --color "#8B5CF6" --json
cockpit browser identity clear client-a --cookies --confirm --json
cockpit browser identity remove client-a --replace-with default --confirm --json
cockpit browser identity delete client-a --replace-with default --confirm --json
cockpit browser session list --json
cockpit browser session list --browser-identity work --json
cockpit browser session create --task-id <taskId> --name "Browser" --json
cockpit browser session create --browser-identity work --name "Browser" --json
cockpit browser open <url> --json
cockpit browser open <url> --new-tab --json
cockpit browser open <url> --browser-identity work --json
cockpit browser tabs --session <sessionId> --json
cockpit browser tabs --session <sessionId> --summary --json
cockpit browser tab close <tabId> --json
cockpit browser tab close <tabId> --others --json
cockpit browser tab close --others --session <sessionId> --json
cockpit browser tab recreate <tabId> --json
cockpit browser goto <tabId> <url> --json
cockpit browser reload <tabId> --json
cockpit browser import-session --session <sessionId> --json
cockpit browser import-session --session <sessionId> --profile "Profile 2" --json
cockpit browser import-session --browser-identity work --profile "Profile 2" --json
cockpit browser import-cookies --session <sessionId> --json
cockpit browser import-cookies --session <sessionId> --profile "Profile 2" --json
cockpit browser scroll <tabId> --delta-y 600 --json
cockpit browser scroll-into-view <tabId> --selector "#submit" --json
cockpit browser scroll-into-view <tabId> --role button --name "Submit" --json
cockpit browser snapshot <tabId> --json
cockpit browser snapshot <tabId> --wait-for-selector ".loaded" --timeout 10000 --json
cockpit browser snapshot <tabId> --wait-for-text "Ready" --timeout 10000 --json
cockpit browser screenshot <tabId> --output <path> --json
cockpit browser screenshot <tabId> --full-page --output <path> --json
cockpit browser click <tabId> --selector "<selector>" --json
cockpit browser click <tabId> --text "<visible text or accessible name>" --json
cockpit browser click <tabId> --role button --name "公開設定" --json
cockpit browser click <tabId> --role link --name "Docs" --name-match prefix --json
cockpit browser click <tabId> --selector "app-shell >>> #save" --json
cockpit browser click <tabId> --x 320 --y 240 --json
cockpit browser click <tabId> --selector "#save" --wait-for-url "*/complete" --json
cockpit browser click <tabId> --selector "#save" --wait-for-text "Saved" --timeout 10000 --json
cockpit browser click <tabId> --selector "#save" --wait-for-selector-state ".modal:hidden" --json
cockpit browser click <tabId> --selector "#save" --wait-for-response-url "*/api/orders*" --wait-for-response-status "200-299" --json
cockpit browser click <tabId> --selector ".message" --wait-for-new-tab --json
cockpit browser click <tabId> --selector ".message" --double --json
cockpit browser type <tabId> --selector "<selector>" --text "<text>" --json
cockpit browser type <tabId> --role textbox --name "Email" --text "<text>" --json
cockpit browser select <tabId> --selector "#tax-type" --value "102" --json
cockpit browser select <tabId> --selector "#tax-type" --option-text "Corporate tax" --json
cockpit browser dismiss-dialog <tabId> --json
cockpit browser dismiss-dialog <tabId> --button-text "OK" --json
cockpit browser dismiss-dialog <tabId> --reject --json
cockpit browser upload <tabId> --selector "input[type=file]" --path ./build.zip --json
cockpit browser upload <tabId> --selector ".dropzone" --path ./cover.png --path ./trailer.mp4 --json
cockpit browser upload <tabId> --selector "#folder-input" --path ./game-build --json
cockpit browser upload <tabId> --role button --name "Attach a file" --path ./build.zip --json
cockpit browser paste <tabId> --json
cockpit browser paste <tabId> --selector "<selector>" --json
cockpit browser paste <tabId> --selector "<selector>" --text "<text>" --json
cockpit browser press <tabId> --key Enter --json
cockpit browser press <tabId> --key A --mod Meta --json
cockpit browser press <tabId> --selector "<selector>" --key Enter --json
cockpit browser keydown <tabId> --key Escape --json
cockpit browser keydown <tabId> --selector "<selector>" --key Escape --json
cockpit browser show --session <sessionId> --json
cockpit browser hide --session <sessionId> --json
cockpit browser client --json
cockpit browser diagnostics --json
```

Typical flow:

1. Create or reuse a task-scoped browser session.
2. Open the target URL with `cockpit browser open`.
3. Use `scroll` for pages below the first viewport.
4. Use `snapshot` to inspect DOM text, element roles, and accessible names.
5. Use `screenshot` when the user wants a visual check.
6. Use `show` to display the browser in Cockpit's right side panel so the user can watch.

Inside a Cockpit task, `open`, `tabs`, `show`, `hide`, and session commands use the calling task automatically when neither `--task-id` nor `--session` is supplied. `open` reuses that task's most recently used session and selected tab. Each task has one assigned Browser Identity. Sessions in that Identity share its persistent Electron partition, while cookies, cache, localStorage, permissions, proxy authentication, and other browser state are isolated from every other Identity. Tasks without an explicit assignment use the Default Identity, which preserves the legacy `persist:in-app-browser` profile and existing sign-ins.

Use `--browser-identity <name|id|default>` to assert the assigned Identity when resolving or creating a session. It does not change a task's assignment. A task-scoped command rejects another Identity, even when a session or tab ID from that Identity is supplied, and the error points to the assignment command. Change an existing task with `cockpit task browser-identity <taskId> <name|id|default>`, or change the calling task with `cockpit task browser-identity <name|id|default>`.

`cockpit browser identity` manages Identities from the CLI. `list` returns usage counts and accepts `--filter all|in-use|unused`, `--in-use`, or `--unused`; both `get` and `usages` include Identity metadata, usage counts, and the referencing tasks, Autoruns, and browser sessions. `create` accepts `--name` and optional `--color`; `update` accepts a name or id plus `--name` and/or `--color`.

Clearing persistent browser data and removing an Identity both require `--confirm`. `clear` accepts exactly one of `--all`, `--cookies`, `--cache`, or `--scope all|cookies|cache`, and closes that Identity's live sessions before clearing the selected data. `remove` and its `delete` alias always clear all persistent data. The Default Identity cannot be removed. An Identity assigned to active tasks or Autoruns cannot be removed unless `--replace-with <name|id|default>` is supplied; replacement reassigns every referencing task and Autorun before removal and rolls those assignments back if removal fails. Without a replacement, references held only by completed tasks return to Default.

Each tab has one canonical page instance shared by the user and agent. Switching tasks, tabs, or right-side panels detaches that page from the window without reloading it, preserving unsaved form input, scroll position, SPA state, and popup/OAuth context in memory. Popup and OAuth windows inherit the parent Identity partition. `tab close <tabId>` closes one tab; add `--others` to keep that tab and close every other tab in its session. Omit the tab ID with `--others` to keep the selected tab. A page-side `window.close()` also removes its Cockpit tab. `tabs --summary` adds `selected` and a whitespace-normalized preview of the first 300 body-text characters to each tab. Every tab also includes `health`: `loading`, `loadingDurationMs` (elapsed milliseconds while Chromium still reports loading, otherwise `null`), `rendererResponsive` (whether the page renderer answered a short JavaScript ping), and `lastNavigationError` (the last main-frame load failure, or `null`). Use those fields to tell a slow site, a navigation error, and a stuck renderer apart. `snapshot --wait-for-selector` / `--wait-for-text` and click postcondition timeouts return `ok:false` with the same `health` object in `details` instead of only `DOM wait timed out`. `tab recreate <tabId>` destroys the tab's renderer and creates a new one in the same session and Browser Identity, keeping the tab ID and current URL. Browser sessions and navigation history survive task completion, resume, and app restart; Chromium page state such as form values and scroll position is restored on a best-effort basis after restart and is encrypted at rest when the operating system credential store is available. Closing a browser session or removing its task discards only its saved session and tab metadata, not the Identity's persistent browser data.

When the right-side browser has been shown, navigation, click, type, select, upload, paste, press, keydown, scroll, snapshot, reload, and screenshot commands keep operating on that page instance while the panel is visible or hidden. This preserves in-memory SPA state and makes CLI changes visible when the panel is shown again. `open` reuses the selected tab by default; add `--new-tab` when the current page contains unsaved input or other state that must be preserved. `click` sends trusted pointer input and can target a selector, visible text, an accessible name with `--role` / `--name`, or viewport coordinates. Selector and text clicks wait for the target to be enabled and positionally stable after scrolling, exclude `disabled`, `aria-disabled="true"`, and `inert` targets, and reject points covered by another element. When a selector resolves to a child such as `span` or `p`, the click keeps that child's hit point but reports and activates its nearest clickable anchor, button, role, label, summary, or `onclick` ancestor. Text clicks resolve in a fixed priority order and stop at the first tier that matches: exact visible text, exact accessible name, partial visible text, partial accessible name. The response returns `matchCount` plus `textMatch` (`exact`, `name-exact`, `partial`, or `name-partial`) so ambiguous targets and the tier that matched are both detectable. The accessible-name tiers make an icon-only button with `aria-label` clickable by its label even though its visible text is only the icon. Add `--double` to dispatch two trusted clicks and a browser `dblclick` sequence.

Every DOM locator — `snapshot`, `click`, `type`, `fill`, `select`, `upload`, `paste`, `press`, `keydown`, `scroll-into-view`, and the `--wait-for-selector` / `--wait-for-selector-state` conditions — traverses open shadow roots. A plain CSS selector is matched in the top-level document first and then in every open shadow root, in document order, so existing selectors keep resolving to the same element. Write `host >>> inner` to pin a path explicitly across a shadow boundary; each `>>>` step searches inside the previous step's shadow root. Selectors reported back by `snapshot` and by click results use the same `>>>` form, so they can be passed straight back to any command. Closed shadow roots are not reachable: the page holds the only reference to them, and Cockpit does not patch `attachShadow` to capture it, because that would change page behavior. Use coordinate clicks for content inside a closed root.

`--role` and `--name` select an element by its implicit or explicit ARIA role and its accessible name instead of a CSS path. The accessible name is computed from `aria-labelledby`, `aria-label`, the associated or wrapping `<label>`, `alt`, the button `value`, the element's text content, and `title`, in that order. Text content follows the flat tree: an element's own open shadow root replaces its light children, `<slot>` contributes its assigned nodes or its fallback content, and `aria-hidden` subtrees are skipped, so slotted text is counted once. `--name-match` chooses `exact` (default), `prefix`, or `contains`; matching is whitespace-normalized and case-insensitive. Add `--selector` alongside them to restrict the search to the descendants of that selector. Elements nested inside another match are preferred, and only visible elements are eligible. When nothing matches, the command fails with `browser_target_not_found`; when more than one element matches, it fails with `browser_target_ambiguous`; when every match is hidden, it fails with `browser_target_not_visible`. Each of those errors returns the candidate `role`, `name`, and `selector` values in `details.candidates` so the next attempt can be narrowed.

Each subcommand accepts a fixed set of options, and nested commands are checked against their own action rather than the union of their siblings, so `browser tab recreate --others`, `browser session list --name`, and `browser identity list --confirm` are rejected too. An option that a command does not implement — `snapshot --deep`, `click --force`, a misspelling, or an option that belongs to another command — fails with `invalid_arguments` and lists the unknown and allowed options in `details`, instead of being silently ignored.

Click postconditions are optional. `--wait-for-url` and `--wait-for-response-url` match a URL substring, or the entire URL when the pattern contains `*`. `--wait-for-text` waits for visible body text. `--wait-for-selector-state` accepts `<selector>:attached`, `<selector>:detached`, `<selector>:visible`, or `<selector>:hidden`; the state suffix is parsed from the final colon, so selectors may contain colons. `--wait-for-new-tab` waits for a popup or new tab in the same session. Every click response includes `newTabId` when a new tab is observed, even without the wait flag. `--wait-for-response-status` accepts one status such as `204` or an inclusive range such as `200-299`, defaults to `200-299`, and requires `--wait-for-response-url`. `--timeout` defaults to 5000 milliseconds and is capped at 30000 milliseconds. Multiple postconditions are ANDed, and an unmet condition, timeout, or status mismatch returns `ok:false`. Response monitoring starts before the trusted `mousePressed` event. A successful matched response returns only its masked `url`, `method`, and `status`; query values and the hash are replaced with `***`. Request and response bodies, headers, and payloads are never returned. Every click observes the resulting click event and URL, DOM, and form-value changes. DOM observation, form-value collection, and `--wait-for-text` cover open shadow roots as well as the light DOM, so a component that only re-renders its own shadow content still reports `changed:true` with a `dom` signal. Shadow text is read as rendered text: `display:none`, `visibility:hidden`, `hidden`, `<style>`, and `<script>` content never satisfies a text wait, whether it sits inside the component or on the host or one of its ancestors, so a pre-rendered hidden status node only matches once it is shown. `<slot>` contributes the nodes assigned to it, or its fallback content only while it is empty, so text a component receives from its parent is matched and the fallback of a filled slot is not. Shadow roots attached after the command started are not observed. The response includes `changed` and `changeSignals`; a focus-only change leaves `changed:false`, so a no-op submission is not reported as a verified effect. When the top-level document can observe the target, the response also includes `eventDispatched` and `inputDelivered`. When no pointer event reaches the page at all, the command returns `ok:false` with code `browser_event_not_dispatched` instead of reporting success. When pointer events reached the page but no `click` event was observed — for example a capture listener stopped propagation, or the target was disabled or detached mid-click — the command returns `ok:true` with `eventDispatched:false`, `inputDelivered:true`, and a `warning`; the click may already have taken effect, so verify the page state instead of retrying to avoid a duplicate click. Embedded-frame targets and pages where observation cannot start omit both fields rather than reporting a false delivery failure. Treat `changed:false` as unverified and inspect the intended outcome or repeat with an explicit postcondition.

`click`, `type`, `fill`, `select`, `upload`, `paste`, `press`, `keydown`, and `scroll-into-view` all accept the same locator: `--selector`, or `--role` and `--name`, or both together. `click`, `type`, `select`, `upload`, `paste`, `press`, `keydown`, and the HTML fallback of `dismiss-dialog` automatically select the specified tab before dispatching input, including when the tab was in the background. When an input command fails, the previously selected tab is restored; the selection stays on the target tab only after success. Parked tabs (not shown in the side panel) receive `click`, `type`, `fill`, `press`, and the HTML fallback of `dismiss-dialog` through CDP `Input.dispatchMouseEvent` / keyboard input, with focus emulation for the duration of the command, without showing a window, switching macOS Spaces, or focusing WebContents. Visible side-panel tabs still receive pointer focus for `click` and the HTML dismiss-dialog fallback; other input commands do not focus the owner window. `type` replaces the selected field's value using trusted keyboard input, falls back to the native value setter when trusted clearing is intercepted, and verifies the final value. `select` requires exactly one of `--value` or `--option-text`, uses the native select setter, and dispatches bubbling `input` and `change` events before verifying the selected option so dependent selects can update. `scroll` reports the actual movement and falls back to a trusted mouse wheel event when JavaScript scrolling has no effect. `scroll-into-view` centers a selector through its scrollable ancestors and returns its final bounds. `dismiss-dialog` first accepts a pending JavaScript dialog, then falls back to a visible HTML `dialog`, `role=dialog`, `aria-modal`, Bootstrap modal, or jQuery UI dialog. It chooses a conventional confirmation button by default; use `--button-text` for an exact label or `--reject` for a negative action. The HTML fallback dispatches its button click with the same delivery verification as `click` and reports `eventDispatched`, `inputDelivered`, and `warning` the same way. `upload` sets files through Chrome DevTools Protocol without opening the operating system file picker. Its selector can target an `input[type=file]` or a containing dropzone; containing elements are searched for a file input. Repeat `--path` for a `multiple` input. For a `webkitdirectory` input, pass one directory path and its files are uploaded recursively with relative paths. `type` also accepts a `contenteditable` host or any element inside one, including CodeMirror and ProseMirror editors; it inserts text through the same trusted input path, falls back to a `beforeinput`/`input` insertion for editors that intercept trusted clearing, and verifies the resulting text so an undelivered edit returns `ok:false` instead of a false success. A `contenteditable` fill always replaces the whole editing host: a selector pointing at a descendant such as one paragraph clears and rewrites the entire editor, and the response reports the resolved `host` plus `hostReplaced:true` so that widening is visible. Target a narrower editing host when only part of a document should change. `paste` performs a real clipboard paste: the page receives a genuine `paste` event with `clipboardData`, so rich-text editors handle it themselves. It pastes the current system clipboard by default; `--text` pastes explicit content, then restores every previous representation — text, HTML, RTF, image, or, when the clipboard held none of them, by clearing it — and leaves anything copied during the paste untouched. `--selector` resolves the same targets as `type`, including an element inside a `contenteditable` host, and focuses it before dispatch; otherwise the focused element receives the paste. The response reports `pasteEventDispatched`, `changed`, `changeSignals`, `verified`, and `textLength`. Success requires an observed change: `target` when the focused field's own text changed, or `dom` when a `paste` event was followed by the pasted text appearing in the document — the shape editors such as Monaco, Ace, and CodeMirror take, where a hidden textarea keeps focus and the content is rendered elsewhere. The `dom` signal matches the clipboard content itself — its head, its tail, or its longest line, and by counting occurrences so text already present on the page is still detected — so a virtualized editor that renders only the visible tail of a long paste counts as delivered, while a page that rejects the paste and merely renders something else, such as a blocked-paste notice or an unrelated live update, does not. A `paste` event that changes nothing, delivery of clipboard content other than the requested `--text`, or no delivery at all all return `ok:false`. When the target cannot be observed from the top document — a focused frame such as an editor's input iframe — the response is `ok:true` with `verified:false` and a `warning`, and the paste is never re-dispatched; check the page state instead of repeating it. `press --key v --mod Meta` (or `--mod Control`) runs the same verified paste path. `press` sends a trusted keydown and keyup pair; `keydown` sends only the keydown event. Both accept `--selector` to focus and verify a target before dispatch, support Enter, Tab, Escape, navigation keys, function keys, printable keys, and shortcuts through `--mod Alt|Control|Meta|Shift`. Combine modifiers with `+` or `,`, such as `--mod Meta+Shift`.Shortcuts for `a`, `c`, and `x` with the platform accelerator (`Meta` on macOS, `Control` elsewhere) are dispatched as the browser's `selectAll`, `copy`, and `cut` editing commands so they take effect instead of only firing a `keydown`; the other modifier keeps its native meaning. `keydown --key v` stays a plain key event, so use `paste` or `press` for clipboard content.  Successful action responses include verification metadata such as the fill value, click hit element, scroll delta, or active element. `snapshot` can wait for a selector or visible text before reading a client-rendered page. Its `links`, `buttons`, and `inputs` entries include the element `role` and `accessibleName` next to the shadow-aware `selector`, and cover elements inside open shadow roots; `shadowRoots` reports how many open shadow roots the page has. `text` stays the rendered text of the document body, so use the element entries to read shadow content field by field. `screenshot --full-page` captures the document beyond the current viewport; `--width` and `--height` set the hidden browser viewport when no visible browser is attached. `--timeout` on `snapshot` and `click` bounds that DOM or postcondition wait only; it does not abort an in-flight page load.

On macOS, prefer `import-session` to transfer the selected tab's sign-in state from Chrome. It imports cookies for the tab's registrable domain and merges localStorage entries for the tab's exact origin into the selected Browser Identity partition, then reloads the page. It never imports data for unrelated domains, origins, or Identities. `--browser-identity` selects the AGI Cockpit destination Identity. The separate `--profile` option selects the source Chrome profile directory; it does not select a Browser Identity. By default Chrome's last-used profile is the source. The first import can show a macOS Keychain permission dialog for `Chrome Safe Storage`. The structured result identifies the selected Chrome profile, origin, cookie and localStorage counts, unsupported storage types, warning, and next step.

To verify a public result without changing the signed-in browser state, create a logged-out Identity and assign it to the calling task before opening a separate session:

```bash
cockpit browser identity create --name logged-out-check
cockpit task browser-identity logged-out-check
cockpit browser session create --browser-identity logged-out-check --name "Public check" --json
cockpit browser open <url> --browser-identity logged-out-check --json
```

`import-session` does not transfer sessionStorage, IndexedDB, browser-extension state, or device-bound authentication such as DBSC. sessionStorage is tied to a Chrome tab's browsing context and cannot be safely restored as origin-wide state. If the site remains signed out, sign in once inside the in-app browser; the selected Browser Identity keeps that login for later assigned tasks and app restarts.

`import-cookies` remains available for backward compatibility and imports only Chrome cookies for the selected tab's registrable domain. It does not transfer localStorage, sessionStorage, or IndexedDB, so cookie import alone may leave an SPA signed out even when server-side redirects succeed. Use `import-session` when the goal is to reuse an existing Chrome login.

Passkey and WebAuthn sign-in uses the platform authenticator of the operating system. On macOS, packaged builds signed with the WebAuthn keychain entitlement show the Touch ID prompt for the tab the user is looking at; development builds and builds without that entitlement have no platform authenticator. On Windows, Windows Hello is provided by the operating system. On Linux there is no platform authenticator, so use a roaming security key or a password; `cockpit browser import-session` reads Chrome on macOS only, so a sign-in finished in the system browser cannot be carried back there. When more than one passkey matches, Cockpit asks which account to use instead of cancelling the request.

`cockpit browser diagnostics` reports why a passkey prompt did not appear. `platformAuthenticator` gives the authenticator kind, its state, whether it is available, whether a sign-in finished in the system browser can be imported back (`systemBrowserImportSupported`, macOS only), and a human-readable reason. `webAuthn` lists the recent WebAuthn attempts of the calling task's Browser Identity with the operation, relying party, outcome, and the notice shown for it, including attempts that never received an answer. Attempts made under another Identity are not returned. A page that requests a platform passkey while no platform authenticator is available no longer waits silently: the browser panel shows the reason, and the same reason is returned here. Passkey autofill (`mediation: "conditional"`) stays unreported, because such a request legitimately waits for the user. A request that a roaming security key could still answer is reported as information rather than as a failure, and a request that explicitly targets a security key is not reported at all.

Do not use HTML Mode for browser navigation. HTML Mode is for agent-generated HTML surfaces.
