# Minifetch Skill: SEO Audit Audit a single web page's SEO signals using the Minifetch API. The `/extract/url-metadata` response is a structured SEO checklist -- every field maps to a ranking signal or on-page optimization opportunity. **Base URL:** https://minifetch.com --- ## What You'll Do 1. Setup -- choose payment method and access method 2. (Free) Preflight -- confirm the URL is crawlable 3. (Paid) Fetch full metadata -- get all SEO signals in one request 4. Interpret the response -- map fields to SEO checklist items 5. Output findings as a structured checklist --- ## Step 1 — Setup ### Choose a payment method There is no account setup fee or monthly fee. Minifetch does not charge for blocked pages or errors. **Option 1: Credit card (account setup required)** Sign up and get your first 250 fetches free, no credit card required to begin: https://minifetch.com/dashboard Click the "Sign up" button and verify your email address to create your account. Once you are signed in to your account, each successful "Go Fetch!" will be deducted from your credit balance. Top up for as little as $2 with your credit card. **Option 2: USDC via x402 on Base or Solana (no account setup needed)** Pay with your crypto wallet. See: https://www.x402.org/ ### Prices (pay-as-you-go) - URL Check (preflight): Free - URL Preview: $0.001 - URL Content: $0.002 - URL Links: $0.002 - URL Metadata: $0.002 ### Choose an access method **Option A: minifetch-api (recommended for agents)** Handles payment automatically — no manual auth header or x402 handshake needed. ``` npm install minifetch-api --save ``` Quickstart: https://www.npmjs.com/package/minifetch-api **Option B: curl + API key** ``` curl "https://minifetch.com/api/v1/extract/url-metadata?url=https://example.com" \ -H "Authorization: Bearer [your_api_key]" ``` **Option C: Coinbase Payments MCP (for AI assistants like Claude)** Gives AI assistants a built-in wallet — no private key needed. ``` npx @coinbase/payments-mcp ``` See: https://www.npmjs.com/package/@coinbase/payments-mcp --- ## Step 2 (Free) -- Preflight Check Confirm the URL is crawlable before spending credits: ``` curl "https://minifetch.com/api/v1/free/preflight/url-check?url=[target_url]" ``` Or with minifetch-api (the `checkAndExtract*` methods run this automatically). You can also call it as a standalone function: ```js await client.preflightCheck(url); ``` If `allowed: false` is returned, skip the paid request -- Minifetch will not charge for blocked pages, but the preflight saves a round trip. If you own the site and want to allow Minifetch access, see: https://minifetch.com/skills/unblock-minifetch/SKILL.md --- ## Step 3 -- Fetch Full Metadata ``` curl "https://minifetch.com/api/v1/extract/url-metadata?url=https://example.com&verbosity=full" \ -H "Authorization: Bearer [your_api_key]" ``` Or with minifetch-api: ```js await client.checkAndExtractUrlMetadata(url, { verbosity: 'full' }); ``` Add `&verbosity=full` for maximum signal -- includes favicons, response headers, hreflang, full heading hierarchy, and image tags & their metadata. **Price:** $0.002 per URL --- ## Step 4 -- Interpret the Response as an SEO Checklist Map these response fields to SEO signals. Flag missing or suboptimal values. ### Core On-Page Signals | Field | What to check | |---|---| | `title` | Present? 50-60 chars? Contains primary keyword? | | `description` | Present? 120-160 chars? Compelling, contains keyword? | | `canonical` | Present? Points to itself (no duplicate content issue)? | | `lang` | Set correctly for target market? | | `hreflang` | If multilingual: all regions covered, no missing reciprocals? | | `viewport` | Present? (mobile-friendliness signal) | | `charset` | Set (typically utf-8)? | ### Structured Data (Rich Results) | Field | What to check | |---|---| | `jsonLd` | Present? Valid schema.org type for the content? | | `jsonLd[].@type` | Matches page intent (Article, Product, BreadcrumbList, FAQ, etc.)? | ### Social / Open Graph | Field | What to check | |---|---| | `og:title` | Present and distinct from title if needed? | | `og:description` | Present? | | `og:image` | Present? Sized correctly (1200x630px recommended)? | | `og:type` | Set (website, article, product)? | | `twitter:card` | Present? (summary_large_image recommended) | | `twitter:title` | Present? | | `twitter:image` | Present? | ### Content Structure | Field | What to check | |---|---| | `headings.h1` | Exactly one H1? Contains primary keyword? | | `headings.h2` | Present? Logical hierarchy? | | `images[].src` | Present on all images? | | `images[].alt` | Non-empty on all images? Missing alt is both an SEO and accessibility flag. | | `images[].width` / `height` | Set? Prevents layout shift (Core Web Vitals signal). | ### Favicons | Field | What to check | |---|---| | `favicons` | At least one present? Multiple sizes recommended (16x16, 32x32, 180x180 for Apple). | | `favicons[].rel` | Includes `icon`, `shortcut icon`, and `apple-touch-icon` variants? | ### Technical Signals (from response headers) | Field | What to check | |---|---| | `responseStatusCode` | 200? Anything else is a problem. | | `responseHeaders['x-robots-tag']` | Not set to noindex? | | `responseHeaders['cache-control']` | Set? Reasonable TTL? | --- ## Step 5 -- Output Format Return findings as a structured checklist. For each item: - Pass -- field present and within recommended parameters - Warning -- present but suboptimal (too short, too long, missing keyword) - Fail -- missing entirely Example summary output: ``` SEO Audit: https://example.com ------------------------------ PASS Title (54 chars) WARN Description (too short: 80 chars, recommend 120-160) FAIL Canonical tag missing PASS H1 present (1 found) FAIL JSON-LD structured data missing WARN og:image missing PASS Viewport set PASS Status 200 ``` --- ## Iterating on Results Every response includes a `minifetchCache` object: ```json "minifetchCache": { "hit": "false", "cachedAt": "2026-02-18T22:37:32.889Z", "expiresAt": "2026-02-18T22:39:32.889Z" } ``` - `hit: true` means the response was served from cache -- the page was not re-fetched. - `hit: false` means a live fetch was performed. - If you are iterating (e.g. monitoring a page for changes after a deploy), check `expiresAt` and wait until after that timestamp before re-fetching. Fetching before expiry will return the same cached result and cost a credit unnecessarily. - The cache window is typically 2 minutes. Use `expiresAt` as your retry-after value, not a fixed delay. --- ## Error Codes - 200 Success - 400 Bad Request — missing or invalid `url` param - 402 Payment Required — no valid payment or credits exhausted - 403 Forbidden — target URL blocked (not charged) - 429 Too Many Requests — back off and retry, max 5–10 req/s - 502 Bad Gateway — target URL blocked or DNS error (not charged) - 503 Service Unavailable — timeout on target URL, retry later --- ## Contact Questions or need help? Join our [Discord server](https://discord.gg/EM6ET8Dshm). Feedback or bulk credits waitlist? Use our [feedback form](https://forms.gle/rkMi7T23bHJc8XFw9). Follow us on X: [@minifetch](https://x.com/minifetch) Full API docs: https://minifetch.com/llms.txt All skills: https://minifetch.com/SKILL.md