← All skills
Data https://ai-skills-vault.pages.dev/skills/agentic-web-scraper.md

Agentic Web Scraper

A data pipeline an agent can run unsupervised for a year.

Download .md All skills
Install URLhttps://ai-skills-vault.pages.dev/skills/agentic-web-scraper.md
Install prompt tap to copy
Read the skill at https://ai-skills-vault.pages.dev/skills/agentic-web-scraper.md and install it as a skill in your agent. Follow it exactly, including its checklists. Then ask me the questions it requires and do the work.

A scraper that runs once is a script. A scraper that runs daily for a year without you touching it is a system. This skill builds the second one.

When to use this skill

Stage 0 - Legality and permission (do not skip)

  1. Read the site's Terms of Service and robots.txt. Disallowed paths are disallowed, including for "just testing".
  2. Prefer an official API, RSS feed, sitemap or bulk export if one exists. Say so if it does.
  3. Never bypass logins, CAPTCHAs, paywalls, rate limits or bot protection. If the data is gated, ask the user to obtain access legitimately.
  4. Do not collect personal data (names, emails, phone numbers, profiles) without a lawful basis. Prefer aggregate or non-personal fields.
  5. Respect Crawl-delay. If absent, default to 1 request per 2 seconds per host.
  6. Record the legal basis, source URL, terms link and date checked in the pipeline's SOURCE.md.

If the request is to scrape a site that forbids it, or to defeat protections, say so plainly and offer the legitimate alternative (API, licensed dataset, manual export).

Stage 1 - Define the output schema first

Write the target table before you look at any HTML. The schema is the contract; the scraper is disposable.

from pydantic import BaseModel, Field
from datetime import datetime

class Listing(BaseModel):
    source_id: str = Field(description="Stable id from the site, not a row number")
    title: str
    price: float | None
    currency: str | None
    location: str | None
    posted_at: datetime | None
    url: str
    scraped_at: datetime

Rules: every field either has a stable source or is nullable. source_id + source is the dedupe key. Never invent a value to fill a gap - null is information.

Stage 2 - Choose the extraction layer (cheapest first)

SituationMethodWhy
Server-rendered HTMLhttpx + selectolax/BeautifulSoupFast, cheap, no browser
JSON embedded in the page (__NEXT_DATA__, window.__INITIAL_STATE__)Parse the JSON blobMost robust - it is the site's own data
Documented/undocumented JSON endpointCall it directlyFar more stable than DOM
Content requires JS executionPlaywright (headless)Last resort: slow, heavy
Layout changes constantly, low volumeLLM extraction over cleaned textFlexible but non-deterministic, so validate

Check for the JSON blob before writing a single CSS selector. It removes 80% of future breakage.

Stage 3 - Discovery and pagination

Handle all four, because sites mix them:

  1. URL pattern - ?page=n until an empty result.
  2. Cursor / next-token - follow next_cursor until null.
  3. Infinite scroll - Playwright, scroll until the item count stops growing for 3 rounds.
  4. Sitemap - fetch sitemap.xml, follow nested sitemaps, filter by lastmod.

Always set a hard stop: max pages, max items, max runtime. An unsupervised crawler without a stop condition will eat the host's bandwidth and your budget.

Stage 4 - Anti-brittleness rules

Stage 5 - Fetching etiquette and retries

HEADERS = {"User-Agent": "MyDataBot/1.0 (+https://example.com/bot; contact@example.com)"}

Stage 6 - Storage and dedupe

Stage 7 - Validation gates before the data is used

  1. Schema validation on every row (pydantic). Reject, log, continue.
  2. Field-level sanity: price > 0, price < 100x median, URL matches host, date not in the future.
  3. Completeness report per run: rows, null rate per field, distinct source_id count.
  4. Drift report: field-level null rate versus the last 7 runs.
  5. Emit a run_report.json. An agent should be able to read it and decide whether the data is trustworthy.

Stage 8 - Scheduling and monitoring

Stage 9 - Agent operating instructions

When an AI agent runs this pipeline unsupervised:

  1. Read SOURCE.md and confirm the legal basis is still valid.
  2. Run in --dry-run first: fetch 1 page, parse, print 3 rows.
  3. Compare the row count to the previous run before committing to the database.
  4. On a structure-change alert: stop, save the fixture, report the diff, do not guess new selectors and push them live.
  5. Never escalate to a headless browser or a proxy pool to get around a block - report the block instead.

Quality checklist

Copy-ready agent prompt

Read the skill at the URL above. First, check robots.txt and the terms for the site I name and tell me plainly whether this is permitted and what the polite crawl rate is. If permitted, define the pydantic schema, write the fetcher with backoff and caching, parse with selector fallbacks, validate, upsert idempotently, and output a run_report.json. Do not use a headless browser unless server HTML has no data. Stop and report rather than inventing selectors after a structure change.
Copied