Skip to main content

agent-web-fetch

Read a public web page reliably and honestly. Use whenever the user gives you a URL to read, summarise, or extract from (articles, blog posts, WeChat 公众号 links, GitHub repos, X posts, JS-heavy pages). Escalates from a plain request to client rotation, structured-data extraction, alternates (AMP/RSS) and a headless browser only when blocked, and reports exactly why a page could not be read instead of bypassing logins, paywalls or CAPTCHAs.

Source facts

Repository
mrlong0129/agent-web-fetch
Last source activity
October 5, 2026 at 18:03
Detected SKILL.md language
English
Stars
0
Forks
0

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
agent-web-fetch
description
Read a public web page reliably and honestly. Use whenever the user gives you a URL to read, summarise, or extract from (articles, blog posts, WeChat 公众号 links, GitHub repos, X posts, JS-heavy pages). Escalates from a plain request to client rotation, structured-data extraction, alternates (AMP/RSS) and a headless browser only when blocked, and reports exactly why a page could not be read instead of bypassing logins, paywalls or CAPTCHAs.
# Reading the web: the escalation playbook Goal: get the real content of a public page with the least effort and the fewest requests, and if you cannot, tell the user precisely why. Never summarise a verification page, login page or error page as if it were the article. ## 0. If the `awf` tool is available, use it - MCP: call `fetch_page(url)`; for HTML you already have, `extract_from_html(html, url)`. - CLI: `awf fetch <url> --format json` (or `--format md`). Exit code 2 means blocked/empty; the reason is in `blocked_reason`. - Not installed but `uv` is available? Run it with zero install/config: `uvx --from git+https://github.com/mrlong0129/agent-web-fetch awf fetch <url> --format json`. - Check `ok`. If `ok` is false, read `blocked_reason` and `fetch_attempts`, then follow "When you are blocked" below. - `extraction_method` tells you where the text came from; `meta` means you only got a summary, so say so. Everything below is the same strategy done by hand (with `curl`, a fetch tool, or a browser tool), for when the package is not installed. ## 1. Use a public API when the site has one (cheapest, most reliable) - GitHub repo: `https://api.github.com/repos/{owner}/{repo}/readme` with header `Accept: application/vnd.github.raw`, or `https://raw.githubusercontent.com/{owner}/{repo}/HEAD/README.md`. - X/Twitter single post: `https://cdn.syndication.twimg.com/tweet-result?id={id}&token=a` (JSON), fallback `https://publish.twitter.com/oembed?url=https://twitter.com/i/status/{id}`. Profiles, timelines and search need login: report that, do not scrape x.com. - Prefer a site's RSS/Atom feed for blogs when the HTML is hard to read. ## 2. One plain request that looks like a normal browser Send a coherent header set, not a library default (`python-requests` and empty UAs are often refused): ``` User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8 ``` Most public pages succeed here. ## 3. Check what you actually got (after EVERY request) Look at the status code, the `<title>`, and how much visible text there is. If the page is short and says any of these, it is not the content: | Signal | Meaning | What to do | |---|---|---| | title "Just a moment...", `cf-mitigated: challenge`, `/cdn-cgi/challenge-platform` on a near-empty 403/503 page | Cloudflare challenge | try another client; a real browser may pass it | | reCAPTCHA / hCaptcha / Turnstile / GeeTest / DataDome (`captcha-delivery.com`) / TCaptcha | CAPTCHA | stop; never solve or outsource a CAPTCHA; report | | "环境异常", "完成验证后即可继续访问", "unusual traffic", "verify you are human" | verification wall | try another client once; otherwise report | | HTTP 401, redirect to `/login`, "sign in to continue", password form on an empty page, "请登录" | login required | stop; ask the user to open it or paste the content | | "subscribe to continue reading", JSON-LD `isAccessibleForFree: false` with a teaser | paywall | stop; report | | HTTP 429, "too many requests", `Retry-After` | rate limited | wait `Retry-After` (if short) then retry once; otherwise report | | HTTP 404/410, or 200 with title "Page not found" | not found / soft 404 | stop; report | | "该内容已被发布者删除", "此内容因违规无法查看", "post was deleted" | content removed | stop; report | | almost no text, `<div id="root"></div>` / `<div id="__next"></div>`, many scripts | JavaScript shell | go to step 5 first, then 6 | Caution: an article that merely mentions "captcha" or "login" is fine. Only trust these signals when the page has little real text. Cloudflare injects `challenge-platform` scripts into many normal pages too. ## 4. Blocked for a retryable reason? Change the client, politely Try, in order, with a pause of at least 1 second between requests to the same site: 1. Mobile Safari: `Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1`, plus `Referer: https://<same-site>/` 2. Android Chrome. 3. An in-app browser if the content was made for one. WeChat articles (`mp.weixin.qq.com/s/...`) are built for WeChat's browser, so for them start with: `Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.47(0x18002f2f) NetType/WIFI Language/zh_CN` with `Accept-Language: zh-CN,zh;q=0.9`. A different network egress (e.g. your own machine instead of a cloud fetch service) also often helps. Do NOT impersonate search-engine crawlers (Googlebot etc.), forge cookies or tokens, or reuse someone's logged-in session. Do not retry non-retryable verdicts (CAPTCHA, login, paywall, 404, removed): a different client will get the same answer. ## 5. Extract with several strategies and keep the richest The visible HTML is not the only place text lives. Check all of these and keep the longest real body: 1. Main content (readability-style): the `<article>` / main text block without nav, footer, ads. 2. JSON-LD: `<script type="application/ld+json">` objects of type `NewsArticle`, `Article`, `BlogPosting` often contain the full `articleBody` (also check inside `@graph`). 3. Embedded JS state: `<script id="__NEXT_DATA__">` (Next.js, look under `props.pageProps`), `__NUXT__` / `__NUXT_DATA__`, `window.__INITIAL_STATE__`, `__APOLLO_STATE__`, YouTube `ytInitialPlayerResponse` (`videoDetails.shortDescription`). Look for long prose under keys like `content`, `body`, `articleBody`, `html`, `text`, `description`. 4. Meta: `og:title`, `og:description`, `twitter:description`, `article:published_time`, `author`. Usually only a summary: label it as such. 5. Site rules. WeChat: long articles are in `#js_content` (images in `data-src`); short text posts have an empty `#js_content` and the full text in the JS variable `content_noencode` (decode `\x0a` etc.) and often in `og:title`. Author is `author`, account name `nick_name`, time `ori_create_time` (Unix seconds) or `create_time` (China time, +08:00). If the result is still thin, try the page's AMP version (`<link rel="amphtml">`) and its RSS/Atom feed (`<link rel="alternate" type="application/rss+xml">`), matching the entry by URL. Tell the user which source you used when it matters ("from the page's structured data", "only the meta description was available"). ## 6. Last resort: a real (headless) browser If you have a browser tool and the failure was retryable (JS shell, Cloudflare wait page, thin content), open the page like a normal visitor, wait for it to settle, scroll once, then run steps 3 and 5 on the rendered HTML. If a CAPTCHA or login is still shown, stop and report. Never click through CAPTCHAs. ## When you are blocked Tell the user plainly, in one or two sentences: what you tried, what you hit, and what they can do. Examples: - "That page is behind a login (it redirected me to the sign-in page), so I can't read it. If you paste the text or a screenshot, I'll work from that." - "Reuters showed me a DataDome CAPTCHA. I don't solve CAPTCHAs; could you open it and paste the article?" - "WeChat returned its '环境异常' verification page. Sending the article text or opening it in WeChat and sharing the content would work." Never present a block page, cookie banner or error text as the article's content. ## Responsible use Only public content. Respect robots.txt (always for crawls, batch jobs and schedules; for a single link the user handed you, note it if robots.txt disallows), the site's terms, rate limits (≥1 s between requests to one site, back off on 429/503), and copyright (summarise and cite; don't republish whole articles).
View on GitHub