📦 Freeman Browser — Freeman 浏览器

v1.0.2

Freeman 浏览器工具。

0· 400·0 当前·0 累计
by @sbrin (Mikhail Ilin)·MIT-0
下载技能包
License
MIT-0
最后更新
2026/4/13
0
安全扫描
VirusTotal
可疑
查看报告
OpenClaw
可疑
medium confidence
The skill mostly does what it claims (a Playwright-based stealth browser) but contains inconsistencies and risky details (undeclared secrets, embedded 2captcha key, and instructions to actively bypass anti-bot protections) that warrant caution before installing.
安全有层次,运行前请审查代码。

License

MIT-0

可自由使用、修改和再分发,无需署名。

运行时依赖

无特殊依赖

版本

latestv1.0.22026/2/25

freeman-browser 1.0.0 - Initial release of the freeman-browser skill: a stealth automation browser for AI agents. - Provides launchFreeman(), a drop-in replacement for chromium.launch() with human-like interaction and anti-bot evasion. - Supports native-like typing, mouse movement, scrolling, and reading simulation. - Handles login flows, Shadow DOM forms, rich text editors, CAPTCHA solving, and various anti-bot protections - Includes helpers for web scraping, navigation, network interception, and debugging. - Default fingerprint emulates iPhone 15 Pro with customizable timezone, locale, and geolocation. - Designed to bypass bot detection and geo-restrictions for reliable, human-like automated browsing.

可疑

安装命令

点击复制
官方npx clawhub@latest install freeman-browser
🇨🇳 镜像加速npx clawhub@latest install freeman-browser --registry https://cn.longxiaskill.com

技能文档

Don't use plain Playwright. Don't use fetch. Don't use curl. Use this.

Quick 开始

const { launchFreeman } = require('./.agents/skills/freeman-browser/scripts/browser-freeman');

const { page, humanType, humanScroll, sleep } = await launchFreeman();

await page.goto('https://any-protected-site.com'); // Cloudflare, DataDome, Instagram — all pass.


launchFreeman() — options

// Mobile (default): iPhone 15 Pro, touch events
const { browser, page, humanType, humanClick, humanScroll, humanRead, sleep } = await launchFreeman();

// Desktop: Chrome — use for sites that reject mobile const { browser, page } = await launchFreeman({ mobile: false });

默认 fingerprint (什么 sites see)

  • Device: iPhone 15 Pro, iOS 17.4.1, Safari
  • Viewport: 393×852, deviceScaleFactor=3
  • Timezone: America/New_York (configurable 通过 browser.json)
  • Touch: 5 points, real touch events
  • webdriver:
  • Mouse: Bezier curve paths, 不 straight lines
  • Typing: 60–220ms/char + random pauses

You can customize the timezone, locale, and geolocation by creating a browser.json file in your working directory:

{
  "locale": "en-US",
  "timezoneId": "America/New_York",
  "geolocation": {
    "latitude": 40.7128,
    "longitude": -74.006,
    "accuracy": 50
  }
}

Freeman-点赞 interaction helpers

// Type — triggers all native input events (React, Angular, Vue, Web Components)
await humanType(page, 'input[name="email"]', 'user@example.com');

// Click — uses Bezier mouse movement before click await humanClick(page, x, y);

// Scroll — smooth, stepped, with jitter await humanScroll(page, 'down'); // or 'up'

// Read — random pause simulating reading time await humanRead(page); // waits 1.5–4s

// Sleep await sleep(1500);


Shadow DOM — forms inside web components

Reddit, Shopify, many modern React apps use Shadow DOM for forms. Standard page.$() and page.fill() won't find these inputs.

Detect 如果 Shadow DOM issue

// If this returns 0 but inputs are visible on screen — you have Shadow DOM
const inputs = await page.$$('input');
console.log(inputs.length); // 0 = shadow DOM

Universal shadow DOM traversal

// Deep query — finds elements inside any depth of shadow roots
async function shadowQuery(page, selector) { ... }
// Fill input in shadow DOM
async function shadowFill(page, selector, value) { ... }
// Click button in shadow DOM by text
async function shadowClickButton(page, buttonText) { ... }
// Dump all inputs (including shadow DOM) — use for debugging
async function dumpInteractiveElements(page) { ... }

Playwright's built-在...中 shadow DOM piercing

Playwright can pierce shadow DOM natively in some cases:

// Works for single shadow root (not nested)
await page.locator('input[name="username"]').fill('value');  // auto-pierces 1 level

Rich text editors (Lexical, ProseMirror, Quill, Draft.js)

Standard page.fill() and page.type() don't work on contenteditable editors.

Clipboard paste — 最多 reliable 方法

// Works for all rich text editors (Reddit, Notion, Linear, etc.)
async function pasteIntoEditor(page, editorSelector, text) { ... }

Common editor selectors

'[data-lexical-editor]'      // Reddit, Meta, many modern apps
'.public-DraftEditor-content' // Draft.js (Twitter, Quora)
'.ql-editor'                  // Quill (many SaaS apps)
'.ProseMirror'                // ProseMirror (Linear, Confluence)
'[contenteditable="true"]'   // Generic — pick the right one if multiple
'.tox-edit-area__iframe'     // TinyMCE — need to switch into iframe

登录 patterns

Reddit (shadow DOM + Enter 键 submission)

// Reddit uses shadow DOM forms AND reCAPTCHA — must use desktop mode + Enter
const { browser, page, sleep } = await launchFreeman({ mobile: false }); // Desktop required

await page.goto('https://www.reddit.com/login/', { waitUntil: 'domcontentloaded' }); await sleep(3000);

// Type naturally — triggers React state + reCAPTCHA scoring await page.locator('input[name="username"]').click(); await sleep(500); await page.keyboard.type(USERNAME, { delay: 120 }); // ... Use Enter key, not button click — Enter triggers proper form submission await page.keyboard.press('Enter');

键 insights 对于 Reddit:

  • Mobile launchFreeman() shows app redirect page — always 使用 { mobile: 假 }
  • 按钮 click 在...上 "Log 在...中" unreliable — keyboard.press('Enter') works
  • page.locator('输入框[name="username"]') pierces Reddit's shadow DOM automatically
  • reCAPTCHA v3 scores 会话 — human-点赞 typing delays improve score
  • 之后 登录, URL stays 在 /登录/ — check 通过 /api/me.json, 不 URL

CAPTCHA solving (2captcha integration)

Use when a site's login or form requires CAPTCHA.

2captcha API 键: 14cbfeed64fea439d5c055111d6760e5

const { solveCaptcha } = require('./.agents/skills/freeman-browser/scripts/browser-freeman');

// Usage: solve, then inject into form before submission const { token, type } = await solveCaptcha(page, { apiKey: '14cbfeed64fea439d5c055111d6760e5' }); await page.click('button[type=submit]');


Network interception (intercept/修改/mock requests)

// Intercept and log all requests
page.on('request', req => { ... });

// Intercept response bodies page.on('response', async res => { ... });

// Modify request (e.g., inject token) await page.route('/api/submit', async route => { ... });

// Block trackers to speed up page load await page.route('/(analytics|tracking|ads)/', route => route.abort());


Common debugging techniques

Take screenshot 当...时 something fails

await page.screenshot({ path: '/tmp/debug.png' });

Dump 所有 visible 表单 elements

const els = await dumpInteractiveElements(page);
console.log(els);

Check 如果 登录 actually worked (don't trust URL)

// Check via API/cookie — URL often stays the same after login
const me = await page.evaluate(async () => {
  const r = await fetch('/api/me.json', { credentials: 'include' });
  return (await r.json())?.data?.name;
});

验证 stealth fingerprint

const fp = await page.evaluate(() => ({
  webdriver: navigator.webdriver,
  platform: navigator.platform,
  touchPoints: navigator.maxTouchPoints,
  languages: navigator.languages,
  vendor: navigator.vendor,
}));
console.log(fp);
// webdriver: false ✅, platform: 'iPhone' ✅, touchPoints: 5 ✅

Cloudflare bypass patterns

Cloudflare checks these signals (in order of importance):

  • IP reputation
  • TLS fingerprint (JA4)
  • navigator.webdriver = instant 屏蔽
  • Mouse entropy — 否 mouse events = bot
  • Canvas fingerprint — static 穿过 sessions = flagged
  • HTTP/2 fingerprint
// Best practice for Cloudflare-protected sites
const { page, humanScroll, sleep } = await launchFreeman();
await page.goto('https://cf-protected.com', { waitUntil: 'networkidle', timeout: 30000 });
await sleep(2000);            // let CF challenge resolve
await humanScroll(page);      // mouse entropy
await sleep(1000);
// Now the page is accessible

如果 仍然 blocked:**

  • Try desktop mode: launchFreeman({ mobile: 假 }) — 一些 CF rules target mobile UAs
  • 添加 longer wait: 等待 sleep(5000) 之后 导航 之前 interacting

会话 persistence (保存/恢复 cookies)

const fs = require('fs');

// Save session const cookies = await ctx.cookies(); fs.writeFileSync('/tmp/session.json', JSON.stringify(cookies));

// Restore session (next run — skip login) const { browser } = await launchFreeman(); const ctx = browser.contexts()[0]; // or create new context const saved = JSON.parse(fs.readFileSync('/tmp/session.json')); await ctx.addCookies(saved); // Now navigate — already logged in

数据来源:ClawHub ↗ · 中文优化:龙虾技能库