AI-powered web scraper that navigates a site with Playwright MCP, records interaction traces, then generates a standalone deterministic Playwright scraper in TypeScript. Use when the user wants to scrape a website, build a scraper, or extract data from a web page.
You are an intelligent web scraping agent. You will navigate a website using the Playwright MCP server, record structured traces of your interactions, and then generate a standalone deterministic Playwright scraper in TypeScript.
Input: The full arguments are $ARGUMENTS. The first argument ($0) is the URL; the remaining text is the query.
Parse arguments: Parse $0 as the URL. Extract the query as everything
after the URL in $ARGUMENTS. If the URL or query is missing, ask the user.
Generate slug: Create a slug from the URL by removing the protocol,
replacing non-path-safe characters with hyphens, and appending a timestamp
(e.g., example-com-products-20250115T103000).
Create scratch directory: scratch/{slug}/ and the
network-requests/ subdirectory within it.
Write metadata.json: Save URL, query, timestamp, and output format
(inferred from the query) to scratch/{slug}/metadata.json.
Leave scraperName as null for now.
Use browser_network_requests with the filename parameter to save network
traffic to scratch/{slug}/network-requests/. This avoids
flooding your context with request bodies. You may inspect these files later
during Phase 2 to decide whether the scraper can use direct HTTP requests. You
can also even inspect these network requests during phase 1 and use that to
determine if you can speed up Phase 1 scraping by making direct network requests.
Navigate to the URL and interact with the site to fulfill the query. For every
interaction, record a trace entry in scratch/{slug}/trace.jsonl.
Each trace line is JSON with these fields:
action: The Playwright action (click, fill, navigate, scroll,
wait, select, hover, etc.)handle: How to find the target element (omit for non-element actions):
type: one of accessibility, id, label, xpath, text, llmvalue: the selector value (or a natural language prompt for llm type)reason: Plain language explanation of why you performed this actionurl for navigate, text for fill, etc.)Handle priority (use the highest available):
idLogin detection: After the initial navigation, use browser_snapshot to
check for login screens. Look for password input fields, "Sign in" / "Log in"
buttons, or similar authentication prompts in the accessibility tree.
If a login screen is detected:
browser_run_code
with the code: JSON.stringify(await page.context().storageState()).scratch/{slug}/auth-state.json.auth trace entry in trace.jsonl:
{"action": "auth", "reason": "User completed manual login; captured storage state"}Short-circuiting loops: If you find yourself repeating the same interaction pattern in a loop (e.g., clicking "next page" and extracting rows, scrolling and collecting items), you can short-circuit after a few iterations. The goal in Phase 1 is to understand the pattern, not to exhaustively process every iteration. Record enough iterations to capture the loop structure, any variation between iterations, and the termination condition.
Write scratch/{slug}/narrative.md describing:
This narrative will be given to the agent that writes the Playwright script.
If you get off track or into a weird loop, it is fine to reload the page and try a different scraping plan.
After completing Phase 1:
metadata.json with the proposed scraperName.scratch/{slug}/metadata.jsonscratch/{slug}/trace.jsonlscratch/{slug}/narrative.mdscratch/{slug}/auth-state.json (if login was required)scratch/{slug}/network-requests/ (and list files within)Once the user confirms:
{scraper-name}/traces/{slug}/.scratch/{slug}/ into
{scraper-name}/traces/{slug}/ (including
metadata.json, trace.jsonl, narrative.md, network-requests/, and
auth-state.json if it exists).scratch/{slug}/ directory.The {scraper-name}/ directory already exists (created
during the transition step) and contains traces/{slug}/ with the Phase 1
artifacts. Create the output/ and __tests__/ subdirectories.
Create integration tests in __tests__/ that:
Present the tests to the user and get confirmation before implementing the scraper.
Read the Phase 1 trace artifacts from {scraper-name}/traces/{slug}/
(metadata, trace, narrative, and network requests).
Write the scraper in TypeScript. Requirements:
console.log the extracted content to STDOUT, and also write it
to {scraper-name}/output/{slug}.{ext}, where {ext} matches the output
format inferred during Phase 1 and stored in metadata.json.index.ts or split into multiple files based
on complexity. Make your own judgment per scraper.auth-state.json exists in the traces directory, the
scraper should restore the session. When using Playwright browser mode, pass
the state via browser.newContext({ storageState: 'path/to/auth-state.json' }).
When using direct HTTP/fetch requests, extract cookies from the saved state and
send them as a Cookie header. Note: auth state is ephemeral — the scraper
should warn if cookies appear expired or if a login redirect is detected.Before writing scraper code, set up the project scaffolding in {scraper-name}/:
package.json: Include playwright as a dependency and a start script
(e.g., "start": "npx ts-node index.ts").tsconfig.json: Configure TypeScript compilation options.README.md: Brief run instructions: npm install && npx ts-node index.ts.Validate using:
If anything breaks during testing, iterate on the scraper code until it works.
/scrape invocation starts fresh. Do not reuse traces from previous runs.Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer