agentsclimarketplace

Playwright cli cloakbrowser

Skill tenequm/skills/skills/playwright-cli-cloakbrowser

Agent skills for building, shipping, and growing software products

Install
npx -y skills add tenequm/skills --skill playwright-cli-cloakbrowser

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

What its author says it does

Copied from the file, not written here

Drive CloakBrowser Manager stealth profiles with @playwright/cli over CDP. Use for browser automation that needs a persistent logged-in session, anti-detect fingerprints, or to pass Cloudflare - attach reuses the profile's cookies and stealth where a fresh browser does not.

SKILL.md

12.7 KB, as published. Nobody here has run it

playwright-cli on CloakBrowser stealth profiles

CloakBrowser Manager runs isolated stealth Chromium profiles - unique fingerprint, optional proxy, persistent cookies, built-in noVNC live view - in a single Docker container. Every running profile exposes a CDP endpoint. playwright-cli attach connects to the profile's persistent context (contexts[0]), so automation inherits the profile's logins and stealth fingerprint; playwright-cli open would launch a plain local browser with neither. Always attach for this setup.

No Manager running yet? See Setting up the Manager below.

For the full command reference, run playwright-cli --help and open the Agent skill: path it prints (the official skill bundled with @playwright/cli). This file only covers the CloakBrowser-specific setup and gotchas.

Connect

# generic: attach to any CDP endpoint
playwright-cli attach --cdp=<CDP_URL>

# CloakBrowser Manager: per-profile CDP endpoint (shown via the toolbar
# code icon while a profile is running)
playwright-cli attach --cdp=http://localhost:8080/api/profiles/<profile-id>/cdp

# then drive normally
playwright-cli goto https://example.com
playwright-cli snapshot                       # a11y tree with refs (e3, e15, ...)
playwright-cli snapshot --depth=6             # bound the tree on huge pages
playwright-cli click e15
playwright-cli --raw eval "document.title"    # --raw = return value only (JSON-serialized), no snapshot noise
playwright-cli detach                         # leave the browser running for next time
  • The profile must be running first - click Launch in the Manager GUI, or curl -X POST http://localhost:8080/api/profiles/<profile-id>/launch.
  • --cdp=<url> and --cdp <url> both work.
  • attach creates an implicit session named default and prints a --s=default hint - that flag is only needed when juggling multiple sessions; plain commands use the default session. -s=<name> opens a second isolated session on the same CDP (e.g. -s=probe for in-page fetch checks while default drives the page).
  • playwright-cli writes a .playwright-cli/ scratch dir (snapshot .yml files, console logs) into the cwd - run from a scratch directory or gitignore it.
  • Never close / close-all / kill-all on an attached stealth profile - that can stop the shared browser and its session. Use detach to leave it running.

Logging into a site

The profile persists cookies, localStorage, and cache across restarts. To establish a login: open the Manager GUI at http://localhost:8080, view the running profile in the built-in noVNC viewer, and sign in there once. playwright-cli then drives the same session logged-in - the VNC view and the CDP connection share one browser.

Importing an existing login (two limits worth knowing):

  • Anti-automation sites (Google, Facebook) may flag the CDP-driven login and not persist a durable session even though the form submits. Bypass: import a real-browser session as Playwright storage-state (playwright-cli state-save/state-load, or capture with npx playwright codegen --save-storage=auth.json <url>) instead of logging in through VNC.
  • A session is often IP-bound: a cookie/state minted at your real location, replayed from a profile whose proxy egress is a different geo, gets forced back to login + 2FA. Transfer only works when the profile's proxy geo matches where the session was created.

Gotchas (all observed in practice)

  1. attach hangs ~30 s, then times out - the profile has a stale or heavy pre-existing tab that never finishes Playwright's connectOverCDP page-init handshake. Fix: close extra tabs via the noVNC view (or stop/relaunch the profile), then re-attach - drops to under a second. A clean about:blank profile attaches instantly.
  2. New-tab creation can be rejected ("Failed to open a new tab") - the stealth browser may forbid Target.createTarget in some states. Prefer navigating the current tab (goto) over tab-new. If a page closes or replaces its own tab (challenge redirects, heavy detail pages), the driver desyncs - just re-attach and continue.
  3. JS-rendered content (prices, dynamic cards) often is not in the a11y snapshot - scrape the DOM with eval: playwright-cli --raw eval "[...document.querySelectorAll('[data-card]')].map(e=>e.innerText)".
  4. Heavy detail pages are slow through a profile proxy and can timeout or desync. Read what you need from the list/results page when possible; treat opening detail pages as best-effort.
  5. Cookie/consent overlays block clicks ("element covered"). Dismiss via JS: playwright-cli eval "document.querySelector('#onetrust-accept-btn-handler')?.click()".
  6. Use --raw whenever scraping or piping - without it output is wrapped in markdown header blocks (### Result, ### Page, ### Snapshot - varies by command), which mangles piping. Even with --raw, eval values come back JSON-serialized (strings quoted).
  7. "Logged in" can be false. A CDP-attached context may render a login form (geo often defaults to US). Verify auth with an eval render check - playwright-cli --raw eval "!!document.querySelector('[href*=logout], [aria-label*=account]')" - not cookie-get, which can read the automation's own blank page and false-negative.
  8. goto may throw TimeoutError on heavy JS sites (it waits on domcontentloaded) yet a follow-up snapshot/eval still returns usable content - a nav timeout is not fatal, retry the read. (Extends gotcha 4.)
  9. click "<CSS selector>" often fails to match even when the element exists. Prefer snapshot eN refs, or click via JS: playwright-cli eval "document.querySelector('...')?.click()".
  10. To wait, poll - do not sleep. Loop on in-page state via eval (document.readyState, element presence) with a bounded max; cap any Cloudflare "Just a moment..." wait explicitly, it is otherwise unbounded.
  11. Browsing a logged-in session can log you out mid-run - anti-automation defenses fire on real activity. Treat a mid-run logout as a site defense, not a tool bug; re-establish the session and slow down.

Patterns for logged-in & JS-heavy sites

  • Reverse-engineer the site's own API. From the logged-in context, call same-origin authenticated endpoints directly - far more robust than DOM scraping:
    playwright-cli -s=probe --raw eval "(async()=>await (await fetch('/api/whatever',{headers:{'X-Requested-With':'XMLHttpRequest'}})).json())()"
    
    Discover the endpoints by monkeypatching fetch first: eval "window.__u=[];const f=fetch;window.fetch=(...a)=>{window.__u.push(a[0]?.toString?.()||a[0]);return f(...a)}", exercise the page, then read window.__u.
  • Use CDP-level network inspection when in-page hooks fall short. A page reload wipes an injected fetch/XHR hook, and service-worker / iframe traffic is invisible to a main-context hook. Use playwright-cli requests then playwright-cli --raw response-body <id> to capture what the page actually fetched.
  • Lazy-loaded lists: scroll-until-count, not fixed sleeps. Loop: scroll, poll the item count, stop on no-growth OR target OR max-rounds. For content inside a scrollable element, scroll that element's scrollHeight, not the window:
    playwright-cli --raw eval "(async()=>{let p=0;for(let i=0;i<30;i++){scrollTo(0,document.body.scrollHeight);await new Promise(r=>setTimeout(r,700));const n=document.querySelectorAll('[data-card]').length;if(n===p)break;p=n}return p})()"
    
  • Retry hard blocks with a fresh exit IP. On 403/429/503/empty content, retry once against a fresh context so a rotating proxy picks a new exit IP (only helps if the profile's proxy rotates).

Minimal working pattern

CDP=http://localhost:8080/api/profiles/<profile-id>/cdp
playwright-cli attach --cdp=$CDP
playwright-cli goto "https://www.amazon.com/s?k=iphone+16+pro+max"
playwright-cli --raw eval "[...document.querySelectorAll('[data-asin]')].slice(0,5).map(e=>e.innerText.split('\n')[0]).join(' | ')"
playwright-cli detach   # leave the stealth browser running

Setting up the Manager (local laptop)

Requirements: Docker 20.10+, ~2 GB disk (the image bundles the CloakBrowser binary; the Manager is ready seconds after start), ~512 MB RAM per running profile.

docker run -d -p 8080:8080 -v cloakprofiles:/data cloakhq/cloakbrowser-manager

Binds to localhost. If 8080 is taken, map another host port (-p 18080:8080) and adjust every URL in this file accordingly. Profiles, cookies, and session data live in the cloakprofiles volume and survive container updates (docker pull cloakhq/cloakbrowser-manager + recreate). By default there is no authentication - fine for local use; add -e AUTH_TOKEN=your-secret-token to protect it, and pass Authorization: Bearer <token> on API calls.

Open http://localhost:8080 - the Manager web GUI. Create a profile (set proxy, timezone, and locale together if you need specific geo) and click Launch. Or headless via API:

# create -> returns {"id": "<profile-id>", ...}
curl -s -X POST http://localhost:8080/api/profiles \
  -H 'Content-Type: application/json' \
  -d '{"name": "agent", "platform": "macos"}'

# launch
curl -s -X POST http://localhost:8080/api/profiles/<profile-id>/launch

# list profiles / find the id later
curl -s http://localhost:8080/api/profiles

The noVNC live view is built into the GUI: click the running profile to watch and interact with the browser in a tab. Use it to log into sites once, watch automation live (VNC and CDP share the same browser), and clear stuck tabs when attach hangs (gotcha 1).

Playwright/Puppeteer scripts work against the same CDP URL:

const { chromium } = require("playwright");
const browser = await chromium.connectOverCDP(
  "http://localhost:8080/api/profiles/<profile-id>/cdp"
);
const page = browser.contexts()[0].pages()[0];
await page.goto("https://example.com");

Remote Manager on a Linux VM over SSH

The same setup runs on any Linux VM you can SSH into - a VPS, home server, or cloud instance. Size it at ~512 MB RAM per running profile plus ~1 GB for the Manager itself.

On the VM:

# install Docker (Ubuntu/Debian; skip if present)
curl -fsSL https://get.docker.com | sh

# run the Manager, localhost-bound so nothing is exposed publicly
docker run -d --restart unless-stopped --name cloakbrowser \
  -p 127.0.0.1:8080:8080 -v cloakprofiles:/data cloakhq/cloakbrowser-manager

On your laptop:

ssh -L 8080:localhost:8080 user@vm

Everything above now works unchanged: the GUI, the noVNC login flow, and the CDP endpoint all ride the same tunneled port, so playwright-cli attach --cdp=http://localhost:8080/api/profiles/<id>/cdp is identical to the local case. Binding to 127.0.0.1 on the VM makes the SSH tunnel the auth boundary, so AUTH_TOKEN stays unnecessary.

If you must expose the Manager directly instead (no tunnel), set AUTH_TOKEN and put it behind an HTTPS reverse proxy - but note that playwright-cli attach cannot inject a Bearer header on the CDP WebSocket, so a token-protected Manager needs a small local proxy in front that injects the header. Prefer the tunnel.

Notes

  • Egress IP is whatever the profile's proxy is set to (or the Docker host's IP with no proxy). Sites see that location for geo, currency, and language - configure the profile's proxy, timezone, and locale together in the Manager. To force English on a geoip'd EU marketplace, a &language= URL param is not enough; override the header (route/run-code with Accept-Language: en-GB,en;q=0.9).
  • One profile = one persistent identity. Use separate profiles for separate accounts; that is the point of the Manager.
  • CloakBrowser is the stealth Chromium engine; cloakbrowser.dev is the project site. The Manager GUI is MIT; the CloakBrowser binary has its own license.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.