本文へ移動
cccskills
無料GitHub で公開

stealth-browser

Anti-detection behaviour for Genesis browser automation - what the Camoufox tools already do, what the agent must still do, Cloudflare Turnstile handling, and per-site notes for bot-hostile sites

インストール方法を見る

含まれるファイル(5)

  • SKILL.md12.3 KB
  • references/anti-detection-research.md5.6 KB
  • references/per-site/ats-ashby.md3.7 KB
  • references/per-site/reddit.md2.0 KB
  • references/services.md6.8 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Stealth Browser

Behaviour rules for sites that try to detect automation. Read the browser-automation skill first: layers, timeouts, safety gates, verify-after-act, overlays and closing browsers live there and are not repeated here.

Bot detection scores the environment (fingerprint, IP, how the browser is driven) and the behaviour. The browser engine and the tools cover most of both. Your job is the part only a planner can do: what to visit, in what order, what not to touch, and when to stop.

What the tools already do

Do not re-implement any of this.

BehaviourWhereDetail
FingerprintCamoufox engineFirefox-based, spoofed at engine level
Delay before browser_click, browser_fill, browser_uploadall layers belowsee Timing
Per-keystroke typingCamoufox, remote CDPfield cleared first; key hold log-normal, median 86 ms (clamped 30-200 ms, p95 ~153 ms); 50-200 ms between keys; 5% of gaps are 0.3-1 s pauses. Chromium and TinyFish fill atomically
CursorCamoufoxscrolls the target into view, humanize=2.5 cursor trail to a point in the central 60% of the element that hit-tests as the element (when none does, Playwright picks the point), 50-200 ms dwell, 40-120 ms press through Playwright's click, which hit-tests again. A cover the hit test finds fails as Click blocked naming it; a styled checkbox or radio is clicked through its own label. See browser-automation, "Clicking"
TurnstileCamoufox, Chromiumdetected and worked on inside browser_navigate (below)
Keyboard repeatbrowser_press_key50-150 ms between repeats, no pre-delay

Not done for you, and not to be faked: idle cursor jitter, humanized scrolling, tab visibility changes. _idle_jitter() and _human_scroll() exist in browser.py with no call site. Do not emulate them with browser_run_js: script-dispatched events carry isTrusted=false and a synthetic visibilitychange leaves document.visibilityState at visible, so both are easier to detect than doing nothing.

Timing

ContextDelay before click/fill/upload
Camoufox (default)1-15 s log-normal, median ~3.3 s, p90 ~7 s
Camoufox with browser_collaborate(True)0.5-2 s uniform
Remote CDP0.5-2 s uniform, always
Chromium, TinyFishnone

Remote CDP uses fast timing on its own and never changes this setting. Timing set with browser_collaborate(True) (for example for a VNC hand-off) stays on: call browser_collaborate(False) before stealth work in Camoufox, or every later click, fill and upload runs at the fast 0.5-2 s pace.

The delays are automatic. Never add sleeps, and never "wait 1-3 s" yourself. Spend the time reading the snapshot and planning the next action instead.

What you must do

  1. Arrive like a visitor. Before a target form, login or checkout, open the site's public page (careers page, home page) in the same profile and reach the target by clicking links. browser_navigate sends no referrer, so a cold navigate straight to a deep form URL has no history behind it. Benefit is plausible but unmeasured; skip it when the form URL is the only entry.
  2. Check for honeypots before filling. The snapshot is an accessibility tree: it drops display: none fields and says nothing about opacity, clip, overflow, size or position, so it cannot tell you which field is a honeypot, while a selector can still reach one. Run this with browser_run_js; it returns only the suspect controls, each with reasons:
    (() => {
      const why = el => {
        const r = [], b = el.getBoundingClientRect();
        for (let n = el; n && n.nodeType === 1; n = n.parentElement) {
          const s = getComputedStyle(n);
          if (s.display === 'none') r.push('display:none');
          if (s.visibility === 'hidden') r.push('visibility:hidden');
          if (+s.opacity === 0) r.push('opacity:0');
          if (s.clip && s.clip !== 'auto') r.push('clip');
          if (s.clipPath && s.clipPath !== 'none' && (n === el || /inset\((50|100)%|circle\(0/.test(s.clipPath))) r.push('clip-path');
          if (n === el && n.getAttribute('aria-hidden') === 'true') r.push('aria-hidden');
          if (n !== el && n !== document.body && n !== document.documentElement) {
            const a = n.getBoundingClientRect(), cuts = v => v === 'hidden' || v === 'clip';
            const ox = Math.min(b.right, a.right) - Math.max(b.left, a.left);
            const oy = Math.min(b.bottom, a.bottom) - Math.max(b.top, a.top);
            if ((cuts(s.overflowX) && ox < 2) || (cuts(s.overflowY) && oy < 2)) r.push('clipped by ancestor');
          }
        }
        if (b.width < 2 || b.height < 2) r.push('zero size');
        if (b.left >= innerWidth || b.right <= 0 || b.bottom + scrollY <= 0) r.push('off-screen');
        return [...new Set(r)];
      };
      const out = [];
      for (const e of document.querySelectorAll('input:not([type=hidden]):not([type=file]):not([type=checkbox]):not([type=radio]),textarea,select')) {
        const r = why(e);
        if (r.length) out.push({field: e.name || e.id, type: e.type, reasons: r});
      }
      for (const e of document.querySelectorAll('input[type=checkbox],input[type=radio]')) {
        const label = e.labels && e.labels[0];
        const r = label ? why(label) : ['no label'];
        if (r.length) out.push({field: e.name || e.id, type: e.type, reasons: r.map(x => 'label: ' + x)});
      }
      return out;
    })()
    
    It checks text-like fields and selects against their own style and every ancestor's, including an ancestor with overflow: hidden that cuts the field off. Checkboxes and radios are judged by their <label>, because real sites routinely hide the native control (opacity 0, appearance: none) behind a styled label; file inputs are skipped for the same reason. Fields below the fold and inside scrollable boxes are not reported. Never fill a reported field. A checkbox or radio reported with no label may be a custom control: confirm with a screenshot. If every field is reported, a dialog is probably open: dismiss it and re-run. Measured 2026-10-04 on a fixture, identical in Chromium (headed) and Camoufox 135 (headless): 13 of 13 hidden fields reported, 0 of 10 legitimate controls (styled checkbox, radio and file input, a rounded clip-path container, a scroll container, below-the-fold fields, a page with overflow-x: hidden on html and body, an aria-hidden ancestor).
  3. Fill in visual order, top to bottom, the way a person tabs through.
  4. Use the tools for every interaction. Never click, type or submit through browser_run_js (el.click(), dispatchEvent, setting .value) on a protected site: those events are untrusted. Reading with it is fine.
  5. Type exactly what is meant. No deliberate typos: browser_fill clears the field and types the whole value, so a "correction" cannot be appended and a typo can land in the submitted text. Fields with input masks (phone, dates) reformat as you type; if the read-back value is wrong, call browser_fill again with the raw digits.
  6. On a failed action, re-read the snapshot before retrying, retry once with a better selector, and decide data rejection versus bot detection (browser-automation, Diagnosis) before switching layers.
  7. Pace the site, not the page. Space repeated submissions from one identity (several minutes apart for applications) and avoid bursts.
  8. Check src/genesis/skills/stealth-browser/references/per-site/ (in the Genesis repo) before Ashby, Greenhouse, Lever or Reddit. For another high-detection site (X, LinkedIn, Google, Hacker News, Stack Overflow) with no file, research its detection first.

Cloudflare Turnstile

browser_navigate handles it (Camoufox and Chromium; not remote CDP or TinyFish). Read turnstile in the result:

  • absent: no challenge detected, OR detection itself errored (the cascade returns nothing when it throws). Check the result's title is not "Just a moment..." before treating the page as loaded.
  • resolved: page is ready. method says how.
  • embedded: the page only embeds a widget on already-loaded content; no interstitial. It matters only if a later submit needs the token.
  • blocked: not resolved. The tool attempted a Telegram alert (skipped when Telegram credentials are missing). Hand off to the user (browser-automation, Safety gates) or stop. Do not loop navigations; Cloudflare rate-limits rapid retries, so wait at least 10 s before one retry.

The cascade for a blocking interstitial, in order: auto-resolve poll (15 s), widget click (up to 3), playwright-captcha solver, VNC click (up to 3), page reload plus 2 more VNC clicks, then blocked. playwright-captcha and vncdotool are optional and not Genesis dependencies; when absent those phases fail with nothing in the tool result (only the server log). The full cascade can run past the 300 s navigate timeout: you then get a timeout error with no turnstile field and a reset page. Check the title on the next navigate before retrying.

cf_clearance (the cookie that skips the challenge next time) lasts 30 min by default, configurable per site; Cloudflare recommends 15-45 min (Cloudflare docs, "Challenge Passage", read 2026-10-04). Do not assume a cleared challenge persists across a long task.

Debugging the VNC click by hand

Only to debug the cascade; the tool does this itself. The VNC bridge injects OS-level pointer events (x11vnc delivers them through XTEST); whether that passes Turnstile more often than the widget click is unmeasured.

  • Server: genesis-vnc.service, x11vnc on display :99, port 5999, password auth. Talk to it with vncdo -s 127.0.0.1:99 -p "${GENESIS_VNC_PASSWORD:-genesis}" (display notation; localhost::5999 fails over IPv6). Never start another VNC server, and never one without a password: the display shows logged-in sessions, and when the service is down the tools kill a foreign x11vnc holding port 5999. The tools start x11vnc themselves only when the systemctl binary is missing or a systemctl call times out; they use the password only if ~/.genesis/vnc_passwd exists, so check that it does before relying on VNC. If systemd is present but the unit is missing or fails to start, nothing starts and VNC stays down.
  • vncdotool is optional (vncdo may be absent).
  • Window origin: DISPLAY=:99 xdotool getactivewindow getwindowgeometry, as the code does. Display :99 is shared, so confirm the active window is this session's Camoufox.
  • Convert with vnc_click_target() in browser.py: x = win_x + left * dpr, y = win_y + (chrome_h + top) * dpr, where left/top come from getBoundingClientRect(), chrome_h from outerHeight - innerHeight and dpr from devicePixelRatio.
  • Move and click as separate vncdo calls, then allow 5-8 s and check that the title left "Just a moment...".
  • reCAPTCHA is not handled by this path; its targeting knows Cloudflare selectors only.

When stealth is not enough

  • Fingerprint scoring (reCAPTCHA v3, enterprise anti-bot): behaviour cannot fix a fingerprint score. Move to remote CDP (the user's Chrome) with the user, or hand the step to the user.
  • Paid services (TinyFish, CAPTCHA solvers, cloud browsers, residential proxies): src/genesis/skills/stealth-browser/references/services.md (in the Genesis repo). Every paid use needs the user's approval, each time.
  • IP reputation: a datacenter IP is the strongest single signal on several sites; there is no tool-level fix. Ask the user.

References

Paths are relative to the Genesis repo root:

  • src/genesis/skills/stealth-browser/references/anti-detection-research.md: detection signals and vendor notes.
  • src/genesis/skills/stealth-browser/references/services.md: paid services, with dated prices.
  • src/genesis/skills/stealth-browser/references/per-site/: ats-ashby.md (Ashby, Greenhouse, Lever), reddit.md.

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Forward Deployed Engineer delivery contract for AWS engagements, build-first artifacts, grounded cost estimates, Well-Architected review, evolution roadmap

日本語の概要は準備中です。原文の説明を表示しています。

WingedGuardian/GENesis-AGI962026年10月12日 更新

Canonical guide to Genesis browser automation - layers (Camoufox, Chromium, the user's Chrome over CDP, TinyFish, desktop), per-tool timeouts, safety gates, verify-after-act, what a click checks (scroll, hit test, covered targets), overlays, iframes, tabs, and failure diagnosis

日本語の概要は準備中です。原文の説明を表示しています。

WingedGuardian/GENesis-AGI962026年10月12日 更新

cc-update

無料

Update Claude Code (the CC CLI / "clog code") to a new version, or bump the pinned CC version. Use when the user asks to update Claude Code, bump the CC pin, evaluate a new CC release, or says "clog code update". Routes to the canonical, standardized process in docs/reference/cc-compatibility.md — do NOT re-derive the update mechanism by grepping every time. Do NOT use for general "what changed in CC" trivia with no intent to update.

日本語の概要は準備中です。原文の説明を表示しています。

WingedGuardian/GENesis-AGI962026年10月12日 更新

This skill should be used when a session's job is to DRIVE OPEN PRs TO MERGE rather than to write new code — "close out the open PRs", "review and fix the open PRs", "what's blocking our PRs", "which PRs are mergeable". It owns the In Review column: it reads each PR's gate status, verifies and fixes review findings on PRs OTHER sessions built, replies in-thread, and stops at the merge gate for the user's per-PR approval. Do NOT load it for building a feature and opening its PR — that is a build session (`genesis-development`).

日本語の概要は準備中です。原文の説明を表示しています。

WingedGuardian/GENesis-AGI962026年10月12日 更新

Code understanding tool selection. Use when exploring architecture, finding definitions, tracing call chains, assessing blast radius of changes, or debugging code paths in the Genesis codebase.

日本語の概要は準備中です。原文の説明を表示しています。

WingedGuardian/GENesis-AGI962026年10月12日 更新

End-to-end content creation and publishing. Takes a topic (or generates one), drafts in the user's voice, gets approval via Telegram, and publishes to Medium via browser automation. Invoke with "publish a post about X", "write and publish to Medium", "content-publish", or when an ego-dispatched session needs to create and distribute content.

日本語の概要は準備中です。原文の説明を表示しています。

WingedGuardian/GENesis-AGI962026年10月12日 更新

WingedGuardian のスキルをすべて見る

このスキルの問題を報告する