Claude Skill

servo-fetch

Fetch and render web pages using the Servo browser engine — a single binary with JS execution, CSS layout, screenshots, and content extraction. Use when a URL returns empty or incomplete content with plain HTTP fetch, when you need a screenshot without GPU, or when you need to ru

LLM Mart · 0 points · 7 views 31 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download konippi-servo-fetch-skills_servo-fetch-fa90cf0.zip · 5 KB

Install

skills CLI npx skills add https://github.com/konippi/servo-fetch/tree/main/skills/servo-fetch
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install konippi-servo-fetch@llmmart
Git git clone https://github.com/konippi/servo-fetch.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole konippi/servo-fetch collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

servo-fetch

When to use

  • A URL returns empty or incomplete content with simple HTTP fetch (SPA, React, Vue)
  • You need a screenshot of a web page in CI/Docker (no GPU available)
  • You need to evaluate JavaScript in a page context (DOM queries, data extraction)
  • You want clean Markdown from a documentation site, blog, or article
  • You need to crawl an entire documentation site or blog for RAG / knowledge ingestion
  • You need the accessibility tree with bounding boxes for a page

When NOT to use

  • The page is simple static HTML (use curl or built-in web fetch instead)
  • You need to interact with the page (click, fill forms) — servo-fetch is read-only
  • You need full Chromium compatibility for complex web apps

Tools (MCP)

Start the MCP server: servo-fetch mcp (stdio) or servo-fetch mcp --port 8080 (Streamable HTTP)

Large multi-block responses can omit URL-labeled blocks and include an omitted-count summary; paginate fetch output with maxLength and startIndex. Extracted Markdown and JSON use the final document URL after redirects, while batch and crawl block labels preserve the requested URL.

fetch

Extract readable content from a URL. JavaScript is executed, CSS layout is computed, and navigation noise (navbars, sidebars, footers, cookie banners) is stripped automatically.

Parameters:

  • url (required): URL to fetch (http/https only)
  • format: "markdown" (default), "json", "html", "text", or "accessibility_tree"
  • selector: CSS selector to extract a specific section instead of full-page extraction
  • maxLength: max characters to return (default 5000)
  • startIndex: character offset for pagination
  • visibility: "moderate" (default), "strict", or "off"
  • common: timeout (s, default 30), settleMs (ms, default 0), userAgent, cookiesFile, headers
fetch(url: "https://docs.rs/tokio", format: "markdown")
fetch(url: "https://example.com", format: "json", selector: "article")
fetch(url: "https://example.com", format: "accessibility_tree")

PDF URLs are auto-detected via Content-Type and extracted directly.

batch_fetch

Fetch multiple URLs in parallel. Results are returned as separate content entries in completion order. Failed URLs are reported inline without aborting the batch.

Parameters:

  • urls (required): array of URLs to fetch (http/https only, max 20)
  • format: "markdown" (default), "json", "html", "text", or "accessibility_tree"
  • selector: CSS selector to extract a specific section
  • maxLength: max characters per URL result (default 5000)
  • visibility: "moderate" (default), "strict", or "off"
  • common: timeout (s, default 30), settleMs (ms, default 0), userAgent, cookiesFile, headers
batch_fetch(urls: ["https://a.com", "https://b.com"], format: "markdown")
batch_fetch(urls: ["https://a.com", "https://b.com"], format: "json", selector: "article")

crawl

Crawl a website starting from a URL, following same-site links via BFS. JavaScript is executed, CSS layout is computed, and navigation noise is stripped. Respects robots.txt.

Parameters:

  • url (required): starting URL to crawl (http/https only)
  • limit: max pages to crawl (default 50, max 500)
  • maxDepth: max link depth from seed (default 3, max 10)
  • format: "markdown" (default) or "json"
  • include: URL path patterns to include (e.g. ["/docs/**"])
  • exclude: URL path patterns to exclude
  • maxLength: max characters per page result (default 5000)
  • selector: CSS selector to extract a specific section per page
  • common: timeout (s, default 30), settleMs (ms, default 0), userAgent, cookiesFile, headers
crawl(url: "https://docs.example.com", limit: 20, maxDepth: 3)
crawl(url: "https://docs.example.com", include: ["/guide/**"], limit: 50)

screenshot

Capture a PNG screenshot. Uses Servo's software renderer — works without GPU.

Parameters:

  • url (required): URL to capture
  • fullPage: capture the full scrollable page (default false)
  • common: timeout (s, default 30), settleMs (ms, default 0), userAgent, cookiesFile, headers
screenshot(url: "https://example.com")
screenshot(url: "https://example.com", fullPage: true)

execute_js

Evaluate a JavaScript expression after the page loads. Console messages (log, warn, error) are appended to the result.

Parameters:

  • url (required): URL to load
  • expression (required): JavaScript expression to evaluate
  • common: timeout (s, default 30), settleMs (ms, default 0), userAgent, cookiesFile, headers
execute_js(url: "https://example.com", expression: "document.title")
execute_js(url: "https://example.com", expression: "[...document.querySelectorAll('h2')].map(e => e.textContent)")

CLI

servo-fetch https://example.com                                  # Markdown (default)
servo-fetch https://example.com --format json                    # Structured JSON
servo-fetch URL1 URL2 URL3                                       # Parallel batch (Markdown with separators)
servo-fetch URL1 URL2 --format json                              # Parallel batch (NDJSON)
servo-fetch https://example.com --format png -o out.png          # Save PNG screenshot
servo-fetch https://example.com --js "document.title"            # Run JavaScript and print result
servo-fetch https://example.com --selector article               # Extract a section by CSS selector
servo-fetch https://example.com --schema schema.json             # Schema-driven JSON
servo-fetch https://example.com --cookies cookies.txt            # Send session cookies
servo-fetch https://example.com --cookie-jar cookies.txt         # Save session cookies (includes HttpOnly)
servo-fetch https://example.com -H "Authorization: Bearer TOKEN" # Custom request header (repeatable)
servo-fetch https://example.com --format html                    # Raw HTML
servo-fetch https://example.com --format text                    # Plain text
servo-fetch https://example.com -t 60                            # Custom timeout
servo-fetch https://example.com --settle 500                     # Extra wait for SPAs
servo-fetch crawl https://docs.example.com --limit 20            # Crawl a site (BFS)
servo-fetch crawl https://docs.example.com --include "/docs/**"  # Crawl with path filter
servo-fetch URL --output page.md                                 # Save a single URL to a file
servo-fetch crawl URL --output-dir ./pages/                      # One file per page

Gotchas

  • Servo's web compatibility is improving but not at Chromium level — best for docs, blogs, and SSR sites
  • Private/reserved IP addresses are blocked (SSRF protection)
  • CLI batch fetch exits non-zero on any fetch failure that servo-fetch detects, while crawl page failures exit non-zero only when every attempted page fails
  • Default timeout is 30 seconds; increase with timeout parameter for slow pages
  • Cookie banners and newsletter popups are stripped via injected user stylesheets

For pagination patterns, format selection, and MCP configuration, see references/guide.md.

Files (servo-fetch)
  • references
    • guide.md 6.1 KB
      # servo-fetch Reference Guide
      
      ## Pagination
      
      Large pages are truncated at `maxLength` (default 5000 characters). The response includes a hint:
      
      ```text
      <content truncated. total_length=42000, next startIndex=5000>
      ```
      
      Fetch the next chunk:
      
      ```text
      fetch(url: "https://...", startIndex: 5000)
      ```
      
      ## Batch fetching
      
      Use `batch_fetch` to fetch multiple URLs in a single call.
      
      ```text
      batch_fetch(urls: ["https://a.com", "https://b.com", "https://c.com"])
      ```
      
      Batch and crawl return URL-labeled blocks that preserve completion order, each starting with its requested URL. Extracted Markdown and JSON resolve links and report metadata against the final document URL after redirects. Oversized results may omit whole blocks and include an omitted-count summary. Failed URLs are reported inline (prefixed with `[error]`) without aborting the batch.
      
      CLI equivalent:
      
      ```bash
      servo-fetch https://a.com https://b.com https://c.com                 # Markdown
      servo-fetch https://a.com https://b.com https://c.com --format json   # NDJSON
      servo-fetch https://example.com --output page.md                      # Save single URL to a file
      servo-fetch https://example.com --cookie-jar cookies.txt              # Save cookies sendable to this URL
      servo-fetch URL1 URL2 --output-dir ./out/                             # One file per URL
      ```
      
      CLI batch fetches attempt every URL, keep successful output, and exit non-zero if any fetch fails. Mixed failures are summarized with deterministic per-category counts and selected by fixed category precedence, not by treating numeric `sysexits` values as severity. Aside from a closed output pipe, command-level output errors are fatal and take precedence over the item-failure summary.
      
      ## Crawling
      
      Use `crawl` to follow links within a site and extract content from multiple pages.
      
      ```text
      crawl(url: "https://docs.example.com", limit: 20, maxDepth: 3)
      crawl(url: "https://docs.example.com", include: ["/guide/**"])
      ```
      
      Crawl follows same-site links only (eTLD+1), respects `robots.txt`, and applies a 500ms interval between requests by default (CLI: `--delay-ms`, library: `CrawlOptions::delay()`).
      
      CLI equivalent:
      
      ```bash
      servo-fetch crawl "https://docs.example.com" --limit 20 --max-depth 3
      servo-fetch crawl "https://docs.example.com" --include "/guide/**"
      ```
      
      CLI `crawl --limit` must be at least 1. Per-page failures exit non-zero only when every attempted page fails; partial success exits zero, while command-level setup, configuration, and output failures other than a closed output pipe are fatal. JSON stats are emitted before an all-pages-failed result whenever the stats stream remains writable.
      
      For CLI automation, distinguish Clap syntax/value failures (`2`) from runtime-invalid URLs, headers, glob patterns, and browser-session configurations (`64`, `EX_USAGE`). Other option-combination validation errors use status `1`. Raw or wrapped I/O failures, including failure to read a schema file, exit `74` (`EX_IOERR`), while malformed or invalid schemas exit `65` (`EX_DATAERR`). A closed output pipe remains a successful exit for pipelines.
      
      ## Format selection
      
      | Goal | Format |
      | ---- | ------ |
      | Read content, summarize, answer questions | `markdown` (default) |
      | Extract title, byline, excerpt, language | `json` |
      | Get raw HTML for further processing | `html` |
      | Get plain text (document.body.innerText) | `text` |
      | Get page structure with roles and bounding boxes | `accessibility_tree` |
      
      ## Selector extraction
      
      Use `selector` to extract a specific section instead of full-page Readability:
      
      ```text
      fetch(url: "https://example.com", selector: "article")
      fetch(url: "https://example.com", selector: ".main-content", format: "json")
      ```
      
      ## Schema extraction
      
      For structured data (product catalogs, listings, comment threads), use `--schema` on the CLI with a schema file. No LLM required — selectors pull fields declaratively.
      
      ```bash
      servo-fetch "https://shop.example.com" --schema schema.json
      servo-fetch URL1 URL2 --schema schema.json    # batch → NDJSON
      ```
      
      Schema:
      
      ```json
      {
        "base_selector": ".product",
        "fields": [
          { "name": "title", "selector": "h2", "type": "text" },
          { "name": "price", "selector": ".price", "type": "text" },
          { "name": "url", "selector": "a", "type": "attribute", "attribute": "href" }
        ]
      }
      ```
      
      Field `type` values: `text`, `attribute`, `html`, `inner_html`, `nested_list`. An empty selector (`""`) reads from the matched element itself — handy inside `nested_list` when you want each item's own text or attribute. Schema selectors are validated at load time.
      
      ## Troubleshooting
      
      | Symptom | Solution |
      | ------- | -------- |
      | Empty content | Site may require JS features not yet supported by Servo. Try `execute_js` with `document.body.innerText` |
      | Timeout | Increase timeout: `fetch(url: "...", timeout: 60)` |
      | Blocked URL | URL resolves to a private IP (SSRF protection). Use a public URL |
      | Noisy output | Try `selector` to target the main content area, e.g. `selector: "article"` or `selector: "main"` |
      
      ## Screenshots
      
      Default viewport is 1280×800. Screenshots are rendered with Servo's software renderer (no GPU).
      
      ## Accessibility tree
      
      The `accessibility_tree` format returns a JSON object of all AccessKit nodes with roles, names, and bounding boxes. Password input values are automatically masked.
      
      ## MCP configuration
      
      ### stdio (default)
      
      ```json
      {
        "mcpServers": {
          "servo-fetch": {
            "command": "servo-fetch",
            "args": ["mcp"]
          }
        }
      }
      ```
      
      ### Streamable HTTP
      
      ```bash
      servo-fetch mcp --port 8080
      ```
      
      Connect your MCP client to `http://127.0.0.1:8080/mcp`.
      
      ### HTTP REST API
      
      For non-MCP HTTP clients (direct REST calls, Docker deployments):
      
      ```bash
      servo-fetch serve --port 3000
      ```
      
      `POST /v1/fetch`, `/v1/batch_fetch`, `/v1/screenshot`, `/v1/execute_js`, `/v1/crawl`, `/v1/map` accept the same parameters as the MCP tools as JSON bodies. `GET /health` and `/version` are also exposed.
      
      ### Docker
      
      Prebuilt multi-arch image published on every release:
      
      ```bash
      docker run --rm -p 3000:3000 ghcr.io/konippi/servo-fetch:latest
      ```
      
      The container runs the HTTP API on port 3000 as non-root (UID 1001) and exposes the same endpoints as above.
      
  • SKILL.md 7.3 KB
    ---
    name: servo-fetch
    description: "Fetch and render web pages using the Servo browser engine — a single binary with JS execution, CSS layout, screenshots, and content extraction. Use when a URL returns empty or incomplete content with plain HTTP fetch, when you need a screenshot without GPU, or when you need to run JavaScript in a page context. No browser download required."
    ---
    
    # servo-fetch
    
    ## When to use
    
    - A URL returns empty or incomplete content with simple HTTP fetch (SPA, React, Vue)
    - You need a screenshot of a web page in CI/Docker (no GPU available)
    - You need to evaluate JavaScript in a page context (DOM queries, data extraction)
    - You want clean Markdown from a documentation site, blog, or article
    - You need to crawl an entire documentation site or blog for RAG / knowledge ingestion
    - You need the accessibility tree with bounding boxes for a page
    
    ## When NOT to use
    
    - The page is simple static HTML (use `curl` or built-in web fetch instead)
    - You need to interact with the page (click, fill forms) — servo-fetch is read-only
    - You need full Chromium compatibility for complex web apps
    
    ## Tools (MCP)
    
    Start the MCP server: `servo-fetch mcp` (stdio) or `servo-fetch mcp --port 8080` (Streamable HTTP)
    
    Large multi-block responses can omit URL-labeled blocks and include an omitted-count summary; paginate `fetch` output with `maxLength` and `startIndex`. Extracted Markdown and JSON use the final document URL after redirects, while batch and crawl block labels preserve the requested URL.
    
    ### fetch
    
    Extract readable content from a URL. JavaScript is executed, CSS layout is computed, and navigation noise (navbars, sidebars, footers, cookie banners) is stripped automatically.
    
    Parameters:
    
    - `url` (required): URL to fetch (http/https only)
    - `format`: `"markdown"` (default), `"json"`, `"html"`, `"text"`, or `"accessibility_tree"`
    - `selector`: CSS selector to extract a specific section instead of full-page extraction
    - `maxLength`: max characters to return (default 5000)
    - `startIndex`: character offset for pagination
    - `visibility`: `"moderate"` (default), `"strict"`, or `"off"`
    - common: `timeout` (s, default 30), `settleMs` (ms, default 0), `userAgent`, `cookiesFile`, `headers`
    
    ```text
    fetch(url: "https://docs.rs/tokio", format: "markdown")
    fetch(url: "https://example.com", format: "json", selector: "article")
    fetch(url: "https://example.com", format: "accessibility_tree")
    ```
    
    PDF URLs are auto-detected via Content-Type and extracted directly.
    
    ### batch_fetch
    
    Fetch multiple URLs in parallel. Results are returned as separate content entries in completion order. Failed URLs are reported inline without aborting the batch.
    
    Parameters:
    
    - `urls` (required): array of URLs to fetch (http/https only, max 20)
    - `format`: `"markdown"` (default), `"json"`, `"html"`, `"text"`, or `"accessibility_tree"`
    - `selector`: CSS selector to extract a specific section
    - `maxLength`: max characters per URL result (default 5000)
    - `visibility`: `"moderate"` (default), `"strict"`, or `"off"`
    - common: `timeout` (s, default 30), `settleMs` (ms, default 0), `userAgent`, `cookiesFile`, `headers`
    
    ```text
    batch_fetch(urls: ["https://a.com", "https://b.com"], format: "markdown")
    batch_fetch(urls: ["https://a.com", "https://b.com"], format: "json", selector: "article")
    ```
    
    ### crawl
    
    Crawl a website starting from a URL, following same-site links via BFS. JavaScript is executed, CSS layout is computed, and navigation noise is stripped. Respects robots.txt.
    
    Parameters:
    
    - `url` (required): starting URL to crawl (http/https only)
    - `limit`: max pages to crawl (default 50, max 500)
    - `maxDepth`: max link depth from seed (default 3, max 10)
    - `format`: `"markdown"` (default) or `"json"`
    - `include`: URL path patterns to include (e.g. `["/docs/**"]`)
    - `exclude`: URL path patterns to exclude
    - `maxLength`: max characters per page result (default 5000)
    - `selector`: CSS selector to extract a specific section per page
    - common: `timeout` (s, default 30), `settleMs` (ms, default 0), `userAgent`, `cookiesFile`, `headers`
    
    ```text
    crawl(url: "https://docs.example.com", limit: 20, maxDepth: 3)
    crawl(url: "https://docs.example.com", include: ["/guide/**"], limit: 50)
    ```
    
    ### screenshot
    
    Capture a PNG screenshot. Uses Servo's software renderer — works without GPU.
    
    Parameters:
    
    - `url` (required): URL to capture
    - `fullPage`: capture the full scrollable page (default false)
    - common: `timeout` (s, default 30), `settleMs` (ms, default 0), `userAgent`, `cookiesFile`, `headers`
    
    ```text
    screenshot(url: "https://example.com")
    screenshot(url: "https://example.com", fullPage: true)
    ```
    
    ### execute_js
    
    Evaluate a JavaScript expression after the page loads. Console messages (log, warn, error) are appended to the result.
    
    Parameters:
    
    - `url` (required): URL to load
    - `expression` (required): JavaScript expression to evaluate
    - common: `timeout` (s, default 30), `settleMs` (ms, default 0), `userAgent`, `cookiesFile`, `headers`
    
    ```text
    execute_js(url: "https://example.com", expression: "document.title")
    execute_js(url: "https://example.com", expression: "[...document.querySelectorAll('h2')].map(e => e.textContent)")
    ```
    
    ## CLI
    
    ```bash
    servo-fetch https://example.com                                  # Markdown (default)
    servo-fetch https://example.com --format json                    # Structured JSON
    servo-fetch URL1 URL2 URL3                                       # Parallel batch (Markdown with separators)
    servo-fetch URL1 URL2 --format json                              # Parallel batch (NDJSON)
    servo-fetch https://example.com --format png -o out.png          # Save PNG screenshot
    servo-fetch https://example.com --js "document.title"            # Run JavaScript and print result
    servo-fetch https://example.com --selector article               # Extract a section by CSS selector
    servo-fetch https://example.com --schema schema.json             # Schema-driven JSON
    servo-fetch https://example.com --cookies cookies.txt            # Send session cookies
    servo-fetch https://example.com --cookie-jar cookies.txt         # Save session cookies (includes HttpOnly)
    servo-fetch https://example.com -H "Authorization: Bearer TOKEN" # Custom request header (repeatable)
    servo-fetch https://example.com --format html                    # Raw HTML
    servo-fetch https://example.com --format text                    # Plain text
    servo-fetch https://example.com -t 60                            # Custom timeout
    servo-fetch https://example.com --settle 500                     # Extra wait for SPAs
    servo-fetch crawl https://docs.example.com --limit 20            # Crawl a site (BFS)
    servo-fetch crawl https://docs.example.com --include "/docs/**"  # Crawl with path filter
    servo-fetch URL --output page.md                                 # Save a single URL to a file
    servo-fetch crawl URL --output-dir ./pages/                      # One file per page
    ```
    
    ## Gotchas
    
    - Servo's web compatibility is improving but not at Chromium level — best for docs, blogs, and SSR sites
    - Private/reserved IP addresses are blocked (SSRF protection)
    - CLI batch fetch exits non-zero on any fetch failure that servo-fetch detects, while crawl page failures exit non-zero only when every attempted page fails
    - Default timeout is 30 seconds; increase with `timeout` parameter for slow pages
    - Cookie banners and newsletter popups are stripped via injected user stylesheets
    
    For pagination patterns, format selection, and MCP configuration, see `references/guide.md`.
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related