ai-search-browser-use

AI Search Browser Use

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "ai-search-browser-use" with this command: npx skills add jwcodewrote/ai-search-browser-use/jwcodewrote-ai-search-browser-use-ai-search-browser-use

AI Search Browser Use

Overview

Enable reliable AI-assisted web research by using Chrome CDP as the primary automation method. This approach connects to a Chrome instance with remote debugging enabled, allowing direct control over browser tabs for Gemini + Qwen queries.

Key Advantage: CDP uses your logged-in Chrome profile, so no additional authentication is needed for Gemini and Qwen.

Workflow

  1. Check Prerequisites

Required: Python + websockets

python3 --version python3 -m pip show websockets

If websockets is missing, install in a venv:

python3 -m venv .venv ./.venv/bin/pip install websockets

Required: Google Chrome

Verify Chrome is installed:

"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --version

If not installed:

  • macOS: brew install --cask google-chrome

  • Windows: winget install --id Google.Chrome -e

  1. Launch Chrome with CDP (Remote Debugging)

CRITICAL: CDP requires a non-default user data directory. This serves two purposes:

  • Allows running alongside your normal Chrome: By using a separate --user-data-dir , the CDP Chrome runs as an independent process. You can continue using your regular Chrome without any conflicts.

  • Preserves login state: By cloning your existing Chrome profile, the CDP Chrome inherits your logged-in sessions for Gemini, Qwen, and other sites.

Clone your existing Chrome profile:

Clean and clone profile (only needed once, or when login expires)

rm -rf /tmp/chrome-ai-profile rsync -a "$HOME/Library/Application Support/Google/Chrome/" /tmp/chrome-ai-profile/

Launch CDP Chrome (runs independently from your normal Chrome!)

"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
--remote-debugging-port=9222
--user-data-dir="/tmp/chrome-ai-profile"
"https://gemini.google.com/app" "https://chat.qwen.ai/" &

Note: You will see two Chrome icons in your dock - one is your normal Chrome, the other is the CDP instance.

For Windows:

Clone profile

Remove-Item -Recurse -Force "$env:TEMP\chrome-ai-profile" -ErrorAction SilentlyContinue Copy-Item -Recurse "$env:LOCALAPPDATA\Google\Chrome\User Data" "$env:TEMP\chrome-ai-profile"

Launch Chrome with remote debugging

Start-Process "chrome.exe" -ArgumentList "--remote-debugging-port=9222", "--user-data-dir=$env:TEMP\chrome-ai-profile", "https://gemini.google.com/app", "https://chat.qwen.ai/"

  1. Verify CDP Connection

Confirm Chrome is listening on the debugging port:

curl -s http://localhost:9222/json | python3 -m json.tool

You should see a JSON array containing page entries for both gemini.google.com and chat.qwen.ai :

[ { "type": "page", "url": "https://gemini.google.com/app", "webSocketDebuggerUrl": "ws://localhost:9222/devtools/page/..." }, { "type": "page", "url": "https://chat.qwen.ai/", "webSocketDebuggerUrl": "ws://localhost:9222/devtools/page/..." } ]

  1. Run AI Queries via CDP

Use the CDP Query Script to send queries to both AI engines:

ai_query.py:

import asyncio import websockets import json import subprocess import sys

def find_page(pages, host): for page in pages: if page.get("type") == "page" and host in page.get("url", ""): return page return None

async def send_query(ws_url, query_text, wait_seconds=30): async with websockets.connect(ws_url) as ws: input_js = f""" (function() {{ const editor = document.querySelector('div[contenteditable="true"]') || document.querySelector('textarea'); if (editor) {{ editor.focus(); document.execCommand('insertText', false, {query_text}); editor.dispatchEvent(new Event('input', {{bubbles: true}})); return 'input-ok'; }} return 'editor-not-found'; }})() """ await ws.send(json.dumps({"id": 1, "method": "Runtime.evaluate", "params": {"expression": input_js}})) await ws.recv()

    click_js = """
    (function() {
        const btn = document.querySelector('button[aria-label*="傳送"]')
                 || document.querySelector('button[aria-label*="Send"]')
                 || document.querySelector('button[type="submit"]');
        if (btn) { btn.click(); return 'clicked'; }
        return 'button-not-found';
    })()
    """
    await ws.send(json.dumps({"id": 2, "method": "Runtime.evaluate", "params": {"expression": click_js}}))
    await ws.recv()

    await asyncio.sleep(wait_seconds)

    extract_js = """
    (function() {
        const md = document.querySelectorAll('.markdown');
        if (md.length > 0) return md[md.length - 1].innerText;
        return 'No response found';
    })()
    """
    await ws.send(json.dumps({"id": 3, "method": "Runtime.evaluate", "params": {"expression": extract_js}}))
    response = await ws.recv()
    result = json.loads(response)
    return result.get("result", {}).get("result", {}).get("value", "No content")

async def main(query): result = subprocess.run(["curl", "-s", "http://localhost:9222/json"], capture_output=True, text=True) pages = json.loads(result.stdout)

gemini = find_page(pages, "gemini.google.com")
qwen = find_page(pages, "chat.qwen.ai")
if not gemini or not qwen:
    print("Error: Gemini or Qwen page not found.")
    return

g = await send_query(gemini["webSocketDebuggerUrl"], query)
q = await send_query(qwen["webSocketDebuggerUrl"], query)

print("GEMINI RESPONSE:\\n" + g)
print("\\n" + "=" * 50 + "\\n")
print("QWEN RESPONSE:\\n" + q)

if name == "main": query = sys.argv[1] if len(sys.argv) > 1 else "請用繁體中文回答:什麼是區塊鏈?" asyncio.run(main(query))

Run:

python3 ai_query.py "你的查詢問題"

  1. Synthesize and Cite Results
  • Consolidate results from Gemini and Qwen into a single, coherent answer.

  • Highlight consensus points first, then disagreements or uncertainties.

  • Provide citations for each major claim using this format:

  • Source Title — Domain — URL

  • If the AI answers do not provide sources, open the referenced sites and cite the primary sources directly.

  1. Close AI Pages (Recommended) or Chrome Instance

After completing the task, you have two options:

Option A: Close only the AI pages (keep Chrome running)

Use CDP to close only the Gemini and Qwen tabs, keeping the Chrome instance running for other tasks:

close_ai_pages.py:

import json import subprocess import asyncio import websockets

async def close_page(browser_ws_url, target_id): async with websockets.connect(browser_ws_url) as ws: await ws.send(json.dumps({ "id": 1, "method": "Target.closeTarget", "params": {"targetId": target_id} })) await ws.recv()

def main(): result = subprocess.run(["curl", "-s", "http://localhost:9222/json"], capture_output=True, text=True) pages = json.loads(result.stdout)

# Get browser WebSocket URL
version = subprocess.run(["curl", "-s", "http://localhost:9222/json/version"], capture_output=True, text=True)
browser_ws = json.loads(version.stdout).get("webSocketDebuggerUrl")

for page in pages:
    url = page.get("url", "")
    if "gemini.google.com" in url or "chat.qwen.ai" in url:
        target_id = page.get("id")
        print(f"Closing: {url}")
        asyncio.run(close_page(browser_ws, target_id))

if name == "main": main()

Run:

python3 close_ai_pages.py

Or use a quick one-liner (bash + Python):

Get page IDs and close them

curl -s http://localhost:9222/json | python3 -c " import json, sys, subprocess, asyncio, websockets

pages = json.load(sys.stdin) version = json.loads(subprocess.run(['curl', '-s', 'http://localhost:9222/json/version'], capture_output=True, text=True).stdout) browser_ws = version.get('webSocketDebuggerUrl')

async def close(browser_ws, tid, url): async with websockets.connect(browser_ws) as ws: await ws.send(json.dumps({'id': 1, 'method': 'Target.closeTarget', 'params': {'targetId': tid}})) await ws.recv() print(f'Closed: {url}')

for p in pages: url = p.get('url', '') if 'gemini.google.com' in url or 'chat.qwen.ai' in url: asyncio.run(close(browser_ws, p['id'], url)) "

Option B: Close the entire CDP Chrome instance

If you want to close the entire Chrome instance (releases port 9222):

macOS

pkill -f "Google Chrome.*--remote-debugging-port=9222"

Windows

Get-Process chrome | Where-Object {$_.CommandLine -match "remote-debugging-port=9222"} | Stop-Process -Force

CDP Troubleshooting

Problem Cause Solution

curl: (7) Failed to connect

Chrome not running with --remote-debugging-port

Re-launch Chrome with the CDP flags

WebSocket connection refused Page ID changed Re-fetch http://localhost:9222/json for new WebSocket URLs

editor not found

Page not fully loaded Wait a few seconds and retry

Login page instead of /app

Profile lacks login state Re-clone a properly logged-in Chrome profile

DevTools remote debugging requires a non-default data directory

Using default profile Always use /tmp/chrome-ai-profile or custom path

Port 9222 already in use Previous CDP instance not closed Kill the previous instance first

Best Practices

  • Always use CDP as the primary method for authenticated queries.

  • Clone the profile each time to ensure a fresh, logged-in state.

  • Wait longer for complex prompts (30–60 seconds).

  • Close the CDP Chrome instance after use to release port 9222.

  • Update the cloned profile if login expires.

Fallback: browser-use

If CDP is unavailable (e.g., Chrome not installed, or CDP setup fails), use browser-use as a fallback:

Install browser-use

brew install pipx pipx install browser-use pipx ensurepath

Restart the terminal after pipx ensurepath to load PATH changes.

Launch with browser-use

browser-use --browser real open "https://gemini.google.com/app" browser-use --browser real open "https://chat.qwen.ai/"

Close browser-use session

browser-use close

Note: When using browser-use as a fallback, clearly document this in your outputs. Do not claim CDP was used if it was not.

Browser Selection (Optional)

Run scripts/browser_plan.py --json to detect OS, find installed browsers, and get open/close commands:

python3 scripts/browser_plan.py --json

For custom browser paths, set BROWSER_PATH_OVERRIDES :

BROWSER_PATH_OVERRIDES='{"quark":["/Custom/Path/Quark.app"]}' python3 scripts/browser_plan.py --json

Outputs

  • Final answer with integrated reasoning from Gemini and Qwen.

  • Explicit citations showing where each major claim was found.

  • Clear indication of which automation method was used (CDP or browser-use fallback).

Resources

  • scripts/browser_plan.py : Detect OS, select browser, and provide open/close/install commands.

  • references/ai_search_targets.md : Public entry points for Gemini/Qwen and citation guidance.

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

meihua-yishu

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

li-er

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

shaoji-style-writer

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

openclaw-version-monitor

监控 OpenClaw GitHub 版本更新,获取最新版本发布说明,翻译成中文, 并推送到 Telegram 和 Feishu。用于:(1) 定时检查版本更新 (2) 推送版本更新通知 (3) 生成中文版发布说明

Archived SourceRecently Updated