Quickstart

Register for a free API key at captureweb.dev/signup. No credit card required. You get 100 credits to start.

curl -X POST https://api.captureweb.dev/v1/screenshot \
  -H "Authorization: Bearer pk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://stripe.com","format":"png"}' \
  --output screenshot.png

Authentication

Pass your API key in the Authorization header on every request:

Authorization: Bearer pk_live_YOUR_KEY

Keys start with pk_live_. Get yours at /signup. Store it securely — it's shown once.

Credits

Credits are consumed per successful render:

EndpointCreditsNotes
/screenshot1Per render
/pdf1URL or HTML input
/markdown1
/content1
/links1
/json1
/scrape1
/snapshot2Returns all formats in one call
Cache hit0Same URL within cache TTL
Failed render (4xx/timeout)0

Response headers on every request: x-credits-used, x-credits-remaining, x-cache (hit/miss), x-render-source, x-render-time.

Errors

StatusCodeMeaning
401invalid_api_keyKey missing or invalid
402credits_exhaustedMonthly credits used up
429rate_limit_exceededToo many requests. Check retry_after_seconds
422validation_errorBad request body
500internal_errorSomething went wrong on our end

/screenshot

POST/v1/screenshot1 credit · Returns image binary or base64
FieldTypeDefaultDescription
urlstringrequiredURL to capture
formatpng | jpeg | webppngOutput format
full_pagebooleanfalseCapture full scrollable height
dark_modebooleanfalseEnable dark mode
widthnumber1280Viewport width px
heightnumber800Viewport height px
qualitynumber90JPEG/WebP quality (1-100)
block_bannersbooleanfalseHide cookie banners and overlays
wait_modeload | idle | selectorloadWhen to consider page ready
wait_selectorstringCSS selector to wait for
asyncbooleanfalseReturn job ID immediately
webhook_urlstringURL to POST result to (async only)

/pdf

POST/v1/pdf1 credit · Returns PDF binary

Accepts either url or html. For HTML input, the PDF is generated directly from the raw HTML — no URL needed.

FieldTypeDefaultDescription
urlstringURL to render (mutually exclusive with html)
htmlstringRaw HTML to render (mutually exclusive with url)
formatA4 | LetterA4Page size
landscapebooleanfalseLandscape orientation
asyncbooleanfalseReturn job ID immediately
webhook_urlstringURL to POST result to (async only)

/snapshot

POST/v1/snapshot2 credits · Returns screenshot + PDF + HTML + Markdown

Cheapest way to get all formats. One call returns screenshot, PDF, HTML, and Markdown together — faster and cheaper than calling each endpoint separately.

/scrape

POST/v1/scrape1 credit · Returns structured JSON
FieldTypeDescription
urlstringrequired
selectorsarrayArray of {name, selector, attribute?} objects
wait_modeload | idleRender wait strategy

/markdown

POST/v1/markdown1 credit · Returns clean Markdown text

Strips navigation, ads, and boilerplate. LLM-ready output.

/content

POST/v1/content1 credit · Returns raw HTML string
POST/v1/links1 credit · Returns array of href strings

/json

POST/v1/json1 credit · Returns structured JSON extracted from page

/a11y

POST/v1/a11y1 credit · Returns ARIA accessibility tree as JSON

Extracts the full ARIA accessibility tree after JavaScript rendering. Useful for UI automation, accessibility audits, and giving AI agents a structured, semantic page representation.

FieldTypeDefaultDescription
urlstringrequiredURL to inspect
interesting_onlybooleantrueReturn only semantically meaningful nodes — omit generic containers
rootstringCSS selector to anchor the tree to a specific subtree
freshbooleanfalseBypass cache

Response: { url, tree, title, source, cached } where tree is the nested ARIA node object.

/brand

POST/v1/brand1 credit · Returns logo, favicon, colors, fonts, and OG data

Extracts brand assets from any domain using a plain HTTP fetch — no browser required. Fast (~300ms) and reliable. Ideal for directories, CRMs, and any product that needs brand metadata at scale.

FieldTypeDefaultDescription
urlstringrequiredThe domain or URL to extract brand data from

Response: { url, favicon, logo, og_image, og_title, og_description, colors[], fonts[], twitter_card, source, method, timing_ms, credits }

Async mode

Any endpoint accepts "async": true. The request returns immediately with a job ID. Poll GET /v1/jobs/:id or receive the result via webhook.

{
  "url": "https://example.com",
  "async": true,
  "webhook_url": "https://yoursite.com/hook"
}

Job status values: pendingrunningcompleted | failed

/crawl

POST/v1/crawlStarter+ · Async only · Credits per page crawled
FieldTypeDefault
urlstringrequired — seed URL
max_depthnumber2 (max 5)
max_pagesnumber50 (max 500)
include_patternregex string
exclude_patternregex string
webhook_urlstring

Render chain

Every request is automatically routed through up to 5 tiers. You never configure this — it's automatic.

TierMethodSpeedWhen used
1Plain fetch~300msStatic sites, SSR pages
2Headless browser (fast)~800msLight JS, cached responses
3Headless browser (full)~3sSPAs, dynamic content
4Stealth browser~8sBot-protected, CAPTCHA, fingerprint evasion
5Text extractor~2sText/Markdown fallback when rendering fails

The x-render-source header on every response tells you which tier was used.

Rate limits

PlanRequests / minute
Free5
Starter30
Pro60
Ultimate120

429 responses include retry_after_seconds in the JSON body. Rate limits reset every minute on a sliding window.

Agents & MCP

CaptureWeb ships an MCP (Model Context Protocol) server that gives Claude, Cursor, Codex, and any MCP-compatible client the ability to see the web — screenshots, PDFs, clean Markdown, structured JSON, and accessibility trees from any URL.

Install via npx — no separate install step needed. The server connects over stdio and exposes all CaptureWeb endpoints as first-class MCP tools.

Claude Desktop

Open ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) and add:

{
  "mcpServers": {
    "captureweb": {
      "command": "npx",
      "args": ["-y", "@captureweb/mcp"],
      "env": {
        "CAPTUREWEB_API_KEY": "pk_live_YOUR_KEY"
      }
    }
  }
}

Restart Claude Desktop. CaptureWeb tools appear in the tool picker automatically.

Cursor

Open Cursor → Settings → MCP and add:

{
  "captureweb": {
    "command": "npx",
    "args": ["-y", "@captureweb/mcp"],
    "env": {
      "CAPTUREWEB_API_KEY": "pk_live_YOUR_KEY"
    }
  }
}

MCP tools

Every CaptureWeb endpoint is exposed as an MCP tool. Claude can call these directly when you ask it to capture or extract from a URL.

ToolDescriptionCredits
screenshotPixel-accurate PNG/JPEG/WebP — returns an inline image block1
pdfExport any URL as PDF — returns a resource block1
markdownClean, LLM-ready Markdown — nav/footer stripped1
contentFull rendered HTML after JS execution1
linksAll hyperlinks as a JSON array1
scrapeStructured data via CSS selectors1
json_extractAI-powered JSON extraction with a plain-English prompt1
snapshotScreenshot + Markdown in one navigation2
a11yFull ARIA accessibility tree as JSON1
crawlAsync full-site crawl — returns job ID1/page

Example prompts once connected:

Skills

A Skill is a YAML file that gives any Claude Code project instant knowledge of the CaptureWeb API — no MCP server required. Drop it in your project and use it as a slash command.

Download captureweb-skill.yaml and save it to .claude/commands/captureweb.md in your project. Then in any Claude Code session, type /captureweb to activate it.

The skill includes the full endpoint reference, auth header format, and caching behaviour — so Claude knows exactly how to call the API without any extra context from you.

Agents.md

captureweb.dev/agents.md is a plain-text reference designed to be fed directly into any AI agent. It covers MCP setup, all 10 tools, REST examples in Python and TypeScript, and caching behaviour.

Paste this into your agent to let it handle setup automatically:

curl -s https://captureweb.dev/agents.md | claude -p "Follow these setup instructions"

Or open the file directly and copy it into any system prompt, CLAUDE.md, or agent context window.

Using the REST API in agent code

Prefer calling the API directly from your agent? Use the Authorization: Bearer header on any endpoint.

import os, requests

API = "https://api.captureweb.dev"
KEY = os.environ["CAPTUREWEB_API_KEY"]

# Extract Markdown for RAG
res = requests.post(f"{API}/v1/markdown",
    headers={"Authorization": f"Bearer {KEY}"},
    json={"url": "https://openai.com/blog"}
)
markdown = res.json()["markdown"]

# Screenshot
res = requests.post(f"{API}/v1/screenshot",
    headers={"Authorization": f"Bearer {KEY}"},
    json={"url": "https://stripe.com/pricing", "full_page": True}
)
open("screenshot.png", "wb").write(res.content)
const API = "https://api.captureweb.dev"
const KEY = process.env.CAPTUREWEB_API_KEY

// Accessibility tree for agent navigation
const res = await fetch(`${API}/v1/a11y`, {
  method: "POST",
  headers: { Authorization: `Bearer ${KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({ url: "https://github.com" }),
})
const { tree } = await res.json()

Cache is automatic — repeated calls to the same URL within 24 hours are free. Pass "fresh": true to force a new render.