browsing
Use when you need direct browser control - teaches Chrome DevTools Protocol for controlling existing browser sessions, multi-tab management, form automation, and content extraction via use_browser MCP tool
By obra · 401 installs
npx skills add obra/superpowers-chrome --skill browsing
Source repository · Upstream listing
Browsing with Chrome Direct
Overview
Control Chrome via DevTools Protocol using the use browser MCP tool. Single unified interface with auto starting Chrome.
Announce: "I'm using the browsing skill to control Chrome."
When to Use
Use this when:
Controlling authenticated sessions
Managing multiple tabs in running browser
Playwright MCP unavailable or excessive
Use Playwright MCP when:
Need fresh browser instances
Generating screenshots/PDFs
Prefer higher level abstractions
Auto Capture
Every DOM action (navigate, click, type, select, eval, keyboard press, hover, drag drop, double click, right click, file upload) automatically saves:
{prefix}.png — viewport screenshot
{prefix}.md — page content as structured markdown
{prefix}.html — full rendered DOM
{prefix} console.txt — browser console messages
Files are saved to the session directory with sequential prefixes (001 navigate, 002 click, etc.). You must check these before using extract or screenshot actions.
Pause switch ( pause capture / resume capture ): the shape/marker/URL defenses below only catch a secret with a recognized shape, an opt in data sen secret mark, or a known sensitive URL. A page that reveals a secret a different way — a "show password"/"reveal" click that renders the plaintext into an ordinary, unremarkable element (no secret looking id/name/class, no sensitive URL) — slips past all three, and the very next auto capture writes it to disk. Call pause capture immediately BEFORE any action you expect to reveal a secret this way; every auto capture (DOM/markdown/screenshot/console/dialog) is skipped — no CDP call is even made — until you call resume capture . The action that triggers the reveal still runs normally; only its capture is skipped. An explicit screenshot call also refuses outright while paused. Pause state lives on the session and persists across actions until you resume: forgetting to call resume capture just means no more captures for the rest of the session, never a silent leak. Caveat: this is in memory, process local state — it does NOT survive the MCP server process restarting (e.g. restart chrome re adopting a still running Chrome keeps the SAME process and stays paused, but a full MCP server restart starts a fresh capturePaused:false ). If the server restarts while a secret is still on screen from a paused reveal, the next auto capture after that restart will NOT be paused — the only signal is that the pause notice stops appearing in responses. Use the credential broker to capture the value itself while paused; resume as soon as the secret is off screen.
Credential shaped pages: when a page shows a token or secret (Slack xoxb / xapp , GitHub ghp / github pat , 1Password ops / A3 keys, otpauth:// seeds, or any element marked data sen secret ), no files are written for that action and the response says ⚠️ Page shows credential shaped content; auto capture and DOM output suppressed. with only metadata. Token shaped values in extract / eval output are replaced by [REDACTED credential shaped] , and screenshot refuses. Capture secrets with a credential broker. On a token shaped page, use eval only for value blind queries (e.g. "is the token field present?"). On a page with any data sen secret element, eval refuses outright, and extract / attr refuse for the marked element or strip it from HTML/markdown output. The marker scan covers the top document, open shadow roots, and same origin iframe / frame / object / embed ; it does not see closed shadow roots or cross origin frames. Markup inside an <iframe srcdoc="…" attribute is not stripped: extract html and attr srcdoc return it verbatim.
When to mark a secret: mark its element with set attr ( data sen secret ) as soon as the action that revealed it returns, before any other action on that page, then capture the value with the credential broker. Marking only affects later actions. The capture files the revealing action already wrote (e.g. 003 click.html / .md ) still hold the value and are not deleted, so don't read them back. This is an accident guard for a cooperating agent, not a security boundary. SUPERPOWERS CHROME ALLOW CREDENTIAL CAPTURE=1 turns all of this off.
Separately (and unconditionally): a plain password or one time code has no shape the check above recognizes, so a page's own handler mirroring one into an attribute, a hidden input, or visible text would otherwise land in the .html / .md / diff.txt files. Whatever gets written is scrubbed on an inert clone ( document.implementation.createHTMLDocument + importNode , never cloneNode on the live document): value and every data / aria attribute are stripped from input[type="password"] (case insensitive; remembered on that same element after a "show password" toggle flips it to type="text" ), any field whose autocomplete contains current password , new password , one time code , cc number , or cc csc (case insensitive substring), and data sen secret marked elements. A field with none of those signals is still caught if its own live .value exactly matches one of its OTHER attributes (a self mirror) the case for Google's 2 step verification totpPin field, which has no recognized type or autocomplete but copies the typed code into data initial value itself. Self mirror detection skips inputs nobody types into ( submit , button , reset , checkbox , radio , hidden , image ) and ignores attributes that name or label a field ( type , name , id , aria label , title , placeholder , for , class ). The live .value of every field found any of these ways, plus its HTML entity escaped forms (including ), is also replaced with [REDACTED] wherever it occurs in the output any attribute, on any element, not just the field's own value if it is at least 4 characters long (3 for cc csc ). Dialog captures are redacted with the values from the most recent page capture; a value typed in the same action that opened the dialog is not. Redaction is a plain string replace, so a secret that also appears as ordinary page text (a password of password ) replaces that text too; the artifact is degraded but nothing leaks. Self mirror detection can also flag a non secret typeable field whose value happens to equal one of its other attributes (a search box synced into data query ), with the same effect. The live page is never touched.
Known gaps (the secret is written to disk in clear): split one digit OTP boxes feeding an aggregate hidden input (each digit is below the length floor, so the aggregate leaks); a field cleared on submit whose mirror remains; a "show password" toggle that swaps in a new element instead of changing type ; a self mirrored value shorter than the length floor (the field is still found, but its value is too short to substring redact). Screenshots are pixels, not scrubbed text: a visible ( type="text" ) typed value can appear in a .png .
Default secret pattern detection (no marking, no click required): everything above needs a recognized type/autocomplete, or a value already mirrored somewhere neither helps a secret already in the DOM at page load, before any action (and so before any marking) has run. Real case: Slack's 2FA setup page puts the TOTP seed in a hidden init key code element from load, so the very first navigate's auto capture would otherwise leak it. Any element whose id / name / class / autocomplete / aria label contains secret , totp , otp , 2fa , mfa , key code , seed , recovery , backup code , api key , or token as a WORD (split on / /camelCase/whitespace, not a raw substring "otp" no longer matches inside "footprint", "token" no longer matches inside "token list") is redacted on sight: a value bearing match ( input / textarea / select ) joins the same value collection/redaction pass as above; a leaf match (no element children a <span / <div / <code holding the secret as text) has its own text blanked directly by element reference, regardless of length, never via a page wide substring replace (that used to corrupt unrelated text sharing the same word, e.g. Prism's class="token keyword" spans turning every class= attribute into [REDACTED]= ); a wrapping container (has element children) is fully blanked every descendant's text is blanked too, not just its own attributes, so a secret split across child elements ( <div id="totp secret" Key: <code SEED</code </div , a <ul class="recovery codes" list) no longer leaks but only when the match is STRONG (an exact compound like totp secret / recovery codes / api key / private key , not a bare single word) and the container's text is 2000 characters or fewer; a WEAK match (bare token / secret , e.g. a design system class sn token provider or a docs <section id="module secrets" ) does not wholesale blank that wiped real page content (a "Get started" paragraph) in testing though any descendant that independently matches on its own is still found and blanked regardless. A button/link (and anything nested inside one) is never text blanked even when matched (its own text is a UI label, e.g. copy seed btn 's "Copy", not the secret) but its own attributes ARE still stripped (fixed: an earlier version returned before stripping them, so a copy button's data clipboard text leaked). label / summary / legend / option are no longer exempt either their own text is blanked and recursed into, since a <label wrapping a matched leaf is routinely the only place the secret renders at all. An otpauth:// URI is redacted unconditionally wherever it appears (href/src/data /text/alt/title), independent of the word boundary match. The .md artifact gets the same redaction independently (it walks the live DOM directly, not the HTML clone), including a matched element sitting INLINE inside an emitted block ( <p Key: <code id="totp secret" SEED</code </p ) by walking each block's own subtree instead of flattening it via textContent . A bare token is broad enough to also catch an ordinary CSRF token field accepted, since this only touches the disk copy, never the live page.
URL based suppression: independent of markup, a page whose URL matches /2fa , /two factor (unanchored GitHub/GitLab/1Password's real 2FA routes all need the open suffix, same as Slack's), /two step , /mfa (segment anchored, unlike the others an unanchored /mfa also matched a docs page merely about mfa), /totp , /security/keys , security keys , /recovery codes , /backup codes , login verification , or security info has its html/md capture AND its screenshot including an explicit screenshot action, not just auto capture suppressed outright, same as a credential shaped page but with its own distinct message (an earlier version always said "page shows credential shaped content" for an explicit screenshot refusal, even when the real reason was the URL). /2fa / /totp / security keys / security info require a word boundary on the open side /2fast , /totpal and /security keyset docs no longer match just because they start with the same letters. Matched against the URL's pathname and hash (never its query string, which over suppressed an ordinary /login?next=/settings/2fa redirect) the hash is included so a hash routed SPA route (e.g. AWS's /security credentials/mfa ) still matches and only for a real page location (http(s):, file:); never for data: / blob: / about: URLs, whose "pathname" is not a path (a data: URL's pathname IS its percent encoded body, so a page merely mentioning a sensitive word in its own title would otherwise false match on itself). Catches a secret with no recognized shape or attribute naming at all (a bare seed, a QR code) purely by the page it's on. SUPERPOWERS CHROME ALLOW CREDENTIAL CAPTURE=1 disables this (for auto capture and an explicit screenshot alike). SUPERPOWERS CHROME SENSITIVE