agentleFS
ykotikykotik/cli-power-skills/skills/web-crawling/SKILL.md

web-crawling

Skill1 starsChanged 7 months agoMITView on GitHub

Use when scraping web pages, automating browser interactions, crawling sites for content, or extracting data from rendered JavaScript pages

2 other projects use a version of this.

Adopted by

Most recently taken up by

  • Other versions2 projects use a version of this.

    Word for word · 0

    None found.

    Edited · 0

    None found.

    Wrote their own version · 2

    1. valtterimelkko/agent-workflow-skills★ 2same name
    2. mahumadad/quarry★ 1same name

    How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.

  • In this repository6 other files it gives its agents.

The file

We split this skill into the rules it gives an agent

3 rules. About 0 are common, 3 are distinctive, and 0 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈3

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 0

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Prefer Playwright over curl for JavaScript-rendered pages — curl only gets raw HTML, Playwright executes JS

    line 180
  2. Distinctive:

    Prefer Katana over manual URL enumeration — fast, recursive, handles JS links

    line 181
  3. Distinctive:

    Prefer Scrapy over ad-hoc scripts for structured multi-page crawling — built-in rate limiting, pipelines, persistence

    line 182

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Web Crawling

When to Use

  • Scraping content from web pages (especially JavaScript-rendered)
  • Automating browser interactions (login, form submission, navigation)
  • Crawling a site to discover and extract structured data
  • Taking screenshots or generating PDFs of web pages
  • Discovering URLs and endpoints on a target site
  • Extracting data from sites with anti-bot protection

Tools

ToolPurposeWhen to choose
PlaywrightCross-browser automation (Chromium, Firefox, WebKit)JS-rendered pages, screenshots, complex interactions
PuppeteerChrome/Firefox automation via DevTools ProtocolChrome-specific automation, familiar API
ScrapyProduction-grade Python crawling frameworkLarge-scale structured crawling with pipelines
CrawleeNode.js crawling with anti-blocking built inSites with bot detection, proxy rotation needed
KatanaFast Go-based URL discovery crawlerEndpoint discovery, reconnaissance, speed

Patterns

Playwright: Scrape a page (inline Node.js script)

node -e "
const { chromium } = require('playwright');
(async () => {
  const browser = await chromium.launch();
  const page = await browser.newPage();
  await page.goto('https://example.com');
  const title = await page.title();
  const text = await page.locator('body').innerText();
  console.log(JSON.stringify({ title, text }));
  await browser.close();
})();
"

Playwright: Take a screenshot

node -e "
const { chromium } = require('playwright');
(async () => {
  const browser = await chromium.launch();
  const page = await browser.newPage();
  await page.goto('https://example.com');
  await page.screenshot({ path: 'screenshot.png', fullPage: true });
  await browser.close();
})();
"

Playwright: Extract structured data from a table

node -e "
const { chromium } = require('playwright');
(async () => {
  const browser = await chromium.launch();
  const page = await browser.newPage();
  await page.goto('https://example.com/data');
  const rows = await page.locator('table tr').evaluateAll(trs =>
    trs.map(tr => Array.from(tr.querySelectorAll('td,th')).map(c => c.textContent.trim()))
  );
  console.log(JSON.stringify(rows));
  await browser.close();
})();
"

Playwright: Wait for JS content to load

node -e "
const { chromium } = require('playwright');
(async () => {
  const browser = await chromium.launch();
  const page = await browser.newPage();
  await page.goto('https://example.com/spa');
  await page.waitForSelector('.content-loaded');
  const data = await page.locator('.content-loaded').innerText();
  console.log(data);
  await browser.close();
})();
"

Puppeteer: Generate PDF from a page

node -e "
const puppeteer = require('puppeteer');
(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('https://example.com', { waitUntil: 'networkidle0' });
  await page.pdf({ path: 'output.pdf', format: 'A4' });
  await browser.close();
})();
"

Katana: Discover all URLs on a site

katana -u https://example.com -silent -d 3

Katana: Discover URLs and output as JSON

katana -u https://example.com -silent -d 2 -jsonl

Katana: Crawl with headless browser for JS-rendered links

katana -u https://example.com -headless -d 2 -silent

Scrapy: Quick single-page scrape (no project needed)

scrapy fetch --nolog https://example.com | python3 -c "
import sys
from scrapy import Selector
html = sys.stdin.read()
sel = Selector(text=html)
for item in sel.css('h2::text').getall():
    print(item)
"

Crawlee: Basic crawler with anti-blocking

node -e "
const { PlaywrightCrawler } = require('crawlee');
const crawler = new PlaywrightCrawler({
  async requestHandler({ page, request }) {
    const title = await page.title();
    console.log(JSON.stringify({ url: request.url, title }));
  },
  maxRequestsPerCrawl: 10,
});
crawler.run(['https://example.com']);
"

Pipelines

Discover URLs → filter interesting ones → scrape

katana -u https://example.com -silent -d 2 | grep '/blog/' | head -5 | while read url; do
  node -e "
    const { chromium } = require('playwright');
    (async () => {
      const browser = await chromium.launch();
      const page = await browser.newPage();
      await page.goto('$url');
      const title = await page.title();
      const text = await page.locator('article').innerText().catch(() => '');
      console.log(JSON.stringify({ url: '$url', title, text: text.slice(0, 500) }));
      await browser.close();
    })();
  "
done

Each stage: Katana discovers URLs, grep filters to blog posts, Playwright scrapes each page.

Crawl → extract to JSON → query with DuckDB

katana -u https://example.com -silent -d 2 -jsonl > crawl.jsonl
duckdb -c "SELECT endpoint, status_code, COUNT(*) FROM read_json_auto('crawl.jsonl') GROUP BY endpoint, status_code ORDER BY COUNT(*) DESC"

Each stage: Katana crawls to JSONL, DuckDB runs SQL on the crawl results.

Prefer Over

  • Prefer Playwright over curl for JavaScript-rendered pages — curl only gets raw HTML, Playwright executes JS
  • Prefer Katana over manual URL enumeration — fast, recursive, handles JS links
  • Prefer Scrapy over ad-hoc scripts for structured multi-page crawling — built-in rate limiting, pipelines, persistence

Do NOT Use When

  • Page content is available via a REST API — use the API directly (api-testing skill)
  • Extracting article text from a news URL — use newspaper4k (web-research skill), it's purpose-built
  • Simple static HTML that curl can fetch — use curl + jq/pup
  • The site explicitly prohibits scraping — respect robots.txt and ToS

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.