Skim
将任何URL转换为适用于AI代理的干净Markdown——一个read(url)工具,托管式,无需注册,无需API密钥。
文档
Skim docs
Skim reads a URL and returns its main content as clean Markdown. Free, no signup, no key. Two ways to use it.
1. MCP (recommended for agents)
Streamable-HTTP MCP endpoint — add it as a remote server:
https://skim.perch-app.workers.dev/mcp
Tool: read
read({ url: "https://example.com/post", // required, absolute http(s) links: true, // optional, keep text; default true max_chars: 8000 // optional, truncate long content })
Returns { url, title, description, format, content, word_count, bytes, ms }.
2. HTTP
GET https://skim.perch-app.workers.dev/api/read?url=https%3A%2F%2Fexample.com%2F POST https://skim.perch-app.workers.dev/api/read {"url":"https://example.com/","links":true,"max_chars":8000}
Query/body options: format=markdown|text|data (markdown default; text also drops link markup; data = structured JSON, see below), links=0, max_chars=N.
Structured data (format=data) — for aggregators
Instead of the readable body, get the machine-readable data the page already embeds — no HTML parsing on your side:
GET https://skim.perch-app.workers.dev/api/read?url=&format=data
Returns { title, description, canonical, jsonld:[…], opengraph:{…}, twitter:{…}, meta:{…}, counts:{…} }. jsonld is the page's schema.org blocks (Product, Offer, JobPosting, Review, Article, BreadcrumbList…) parsed from every <script type="application/ld+json"> (including @graph), so a price/spec/job/product aggregator can read structured fields straight from the source. Works with render=js for SPA pages. Sites without embedded data return empty arrays (still valid JSON).
3. Read it yourself (clean reader)
Not an agent? Paste any URL into the clean reader to strip ads, popups and clutter and get a readable, shareable page: https://skim.perch-app.workers.dev/r?url=<page>.
Building a job aggregator or feed reader
Skim works well as a server-side fetch + extract layer: your aggregator or agent calls Skim, Skim fetches upstream and hands back clean content, so you never ship a browser or a scraper stack. Two patterns:
ATS JSON APIs — Skim returns JSON verbatim (the whole body, up to 5 MB), so you can parse it directly:
Greenhouse: https://boards-api.greenhouse.io/v1/boards/{company}/jobs
Ashby: https://api.ashbyhq.com/posting-api/job-board/{company}
Lever: https://api.lever.co/v0/postings/{company}?mode=json
Client-rendered job boards (SPA) — add render=js so Skim runs the page in a real headless browser before extracting, then returns clean Markdown:
GET https://skim.perch-app.workers.dev/api/read?url=&render=js
Skim passes the upstream HTTP status straight through — a 404 means that company/board doesn't exist on that ATS (not a Skim error), and a 403 means the site blocked the fetch. Large bodies come back whole up to 5 MB; pass max_chars=N only if you want to cap length yourself.
Batch reads — polling several boards at once? Send up to 10 URLs in one call and get an array back (each result carries its own url/status/content or error):
POST https://skim.perch-app.workers.dev/api/read-batch {"urls":["https://boards-api.greenhouse.io/v1/boards/a/jobs","https://api.lever.co/v0/postings/b?mode=json"]}
or: GET https://skim.perch-app.workers.dev/api/read-batch?urls=, → {"count":N,"results":[...]}
Call it straight from the browser — every endpoint sends Access-Control-Allow-Origin: *, so a client-side dashboard or aggregator can fetch() Skim directly with no backend and no CORS errors (Skim does the upstream fetch server-side for you):
const r = await fetch("https://skim.perch-app.workers.dev/api/read?url=" + encodeURIComponent(u) + "&format=data"); const data = await r.json(); // JSON-LD / OpenGraph / meta, from your frontend
What it handles
HTML (→ Markdown, main-content extracted), plain text, JSON and XML (returned as-is). PDFs and binaries aren't supported yet. Private/internal addresses are blocked. Rate limit: 40 reads/minute per IP.
Notes
Skim identifies itself as SkimBot/1.0 and follows redirects. It's a reader, not a scraper farm — be considerate of the sites you read.