{
 "slug": "firecrawl",
 "name": "Firecrawl",
 "url": "https://firecrawl.dev",
 "domain": "firecrawl.dev",
 "category": "web-scraping",
 "category_name": "Web scraping",
 "tested_at": "2026-10-06",
 "run": "20261006T072501Z",
 "draft": false,
 "reviewed": true,
 "owner_verified": null,
 "origin": "editorial",
 "history": [
  {
   "run": "20261001T055833Z",
   "date": "2026-10-01",
   "level": 3,
   "engine": {
    "runner": "omp",
    "model": null,
    "driver": null,
    "signed": false,
    "inbox": [
     "matfy.com"
    ],
    "robots": "start"
   }
  },
  {
   "run": "20261001T194832Z",
   "date": "2026-10-01",
   "level": 4,
   "engine": {
    "runner": "omp",
    "model": null,
    "driver": null,
    "signed": true,
    "inbox": [
     "agentdrives.com"
    ],
    "robots": "start"
   },
   "why": "product"
  },
  {
   "run": "20261006T072501Z",
   "date": "2026-10-06",
   "level": 4,
   "engine": {
    "runner": "omp",
    "model": "claude-opus-5-5",
    "driver": 2,
    "signed": true,
    "inbox": [
     "agentdrives.com"
    ],
    "robots": "start"
   }
  }
 ],
 "level": 4,
 "level_name": "Runs on its own",
 "level_selfhost": null,
 "entry": "self-start",
 "door": {
  "passed": 3,
  "tries": 3,
  "self_start": true
 },
 "badges": [],
 "stages": [
  {
   "key": "in",
   "label": "Access",
   "state": "yes",
   "text": "Gets in on its own: no key needed"
  },
  {
   "key": "work",
   "label": "Use",
   "state": "yes",
   "text": "Work done: 100% of the core"
  },
  {
   "key": "pay",
   "label": "Pay",
   "state": "part",
   "text": "Reaches the checkout: a billing API, none made yet",
   "value": "ready",
   "route": "billing_api"
  },
  {
   "key": "leave",
   "label": "Leave",
   "state": "yes",
   "text": "Nothing to cancel; can't delete its account",
   "at": "delete",
   "left": "stuck"
  }
 ],
 "outcomes": [
  {
   "key": "find",
   "label": "Find",
   "state": "yes",
   "text": "Docs agents can read: llms.txt, an OpenAPI and an MCP server",
   "have": [
    "llms_txt",
    "openapi",
    "mcp"
   ]
  },
  {
   "key": "access",
   "label": "Access",
   "state": "yes",
   "text": "Gets in on its own: no key needed",
   "stage": "in"
  },
  {
   "key": "use",
   "label": "Use",
   "state": "yes",
   "text": "Work done: 100% of the core",
   "stage": "work"
  },
  {
   "key": "pay",
   "label": "Pay",
   "state": "part",
   "text": "Reaches the checkout: a billing API, none made yet",
   "value": "ready",
   "route": "billing_api",
   "stage": "pay"
  },
  {
   "key": "leave",
   "label": "Leave",
   "state": "yes",
   "text": "Nothing to cancel; can't delete its account",
   "at": "delete",
   "left": "stuck",
   "stage": "leave"
  }
 ],
 "access": [
  {
   "key": "keyless",
   "label": "No key needed",
   "routes": [
    "keyless"
   ],
   "minutes": 8.3,
   "core": "8/8"
  }
 ],
 "minutes": 8.3,
 "next": {
  "to": 5,
  "text": "Next: pay without a person"
 },
 "stop": "pay",
 "core": "8/8",
 "scores": {
  "coverage": 88,
  "reliability": 88,
  "resilience": null,
  "setup": 100,
  "surface_coverage": null,
  "docs_accuracy": null,
  "docs_completeness": null
 },
 "parts": {
  "holds_up": null,
  "docs_match": null,
  "setup": 100,
  "security": "private",
  "standards": [
   {
    "standard": "MCP",
    "state": "behind",
    "behind": 1,
    "value": "2025-11-25"
   },
   {
    "standard": "MCP discovery",
    "state": "behind",
    "behind": null,
    "value": "legacy"
   },
   {
    "standard": "MCP client registration",
    "state": "current",
    "behind": null,
    "value": "cimd"
   },
   {
    "standard": "OpenAPI",
    "state": "behind",
    "behind": 2,
    "value": "3.0.0"
   }
  ]
 },
 "reliability_method": "first-try",
 "resilience": null,
 "stress": [],
 "surface_audit": null,
 "coverage_core": 100,
 "after_wall": null,
 "coverage_source": "computed",
 "driver": {
  "version": 2,
  "model": "claude-opus-5-5",
  "profile": "full",
  "assisted": false,
  "handoff": null,
  "prompt_sha": "f3d0adeeb256",
  "kb_version": "2+overlay-9e43028a2c",
  "identity": null
 },
 "methodology": 15,
 "rules_date": "2026-10-15",
 "engine": {
  "runner": "omp",
  "model": "claude-opus-5-5",
  "driver": 2,
  "signed": true,
  "inbox": [
   "agentdrives.com"
  ],
  "robots": "start"
 },
 "same_level_drives": 2,
 "drives": 3,
 "works_assisted": null,
 "freshness": "fresh",
 "nothing_to_pay": false,
 "core_gated": false,
 "profiles": {},
 "agent_check": null,
 "agent_pass": {
  "rung": "signup",
  "vendor": "Google reCAPTCHA (invisible)",
  "signed": true
 },
 "who_gets_in": {
  "server": {
   "state": "in"
  },
  "signed": {
   "state": "page",
   "kind": "home",
   "at": "2026-10-12"
  },
  "browser": {
   "state": "in",
   "measured": false
  },
  "our_key": "pending",
  "robots": null,
  "tip": false
 },
 "ladder": {
  "docs": {
   "status": "headless",
   "note": "llms.txt (www and docs), /auth.md, /SKILL.md (agent onboarding paths A-G), docs pages as markdown via .md and Accept: text/markdown, OpenAPI 3.0.0 at docs.firecrawl.dev/api-reference/v2-openapi.json"
  },
  "signup": {
   "status": "browser",
   "note": "No headless sign-up we could use: auth.md offers only WorkOS ID-JAG identity_assertion (no anonymous); Stripe Projects needs a Stripe account. Web form (email+password) worked in our agent's browser; invisible reCAPTCHA let us through."
  },
  "verify": {
   "status": "browser",
   "note": "Confirmation mail arrived in under a minute; the link is a Supabase PKCE link that only completes in the browser that signed up."
  },
  "credentials": {
   "status": "browser",
   "note": "Default key created at sign-up, read from dashboard API Keys; documented cli-auth flow (session_id + PKCE, poll /api/auth/cli/status) returned the key after onboarding + Authorize click in the signed-in browser.",
   "via": ""
  },
  "first_call": {
   "status": "headless",
   "note": "GET /v2/team/credit-usage 200 (1000 credits). Keyless: POST /v2/scrape, MCP firecrawl_scrape/search/parse also work without any account."
  },
  "first_action": {
   "status": "headless",
   "note": "POST /v2/crawl created a job, read back completed with 4 pages."
  },
  "pay": {
   "status": "blocked",
   "grade": "P3",
   "rails": [
    "Stripe Projects (CLI, Shared Payment Token)",
    "dashboard Billing (Add a card / Upgrade)"
   ],
   "rail_ids": [
    "stripe-projects"
   ],
   "first_party": true,
   "rail_scope": "full",
   "trial_path": "free tier",
   "note": "No 402 anywhere (keyless paid paths answer 401 + resource_metadata); no x402./mpp./agents. hosts; x402 Bazaar and mpp.dev list only third-party resellers. First-party: Stripe Projects upgrades to Hobby/Standard/Growth from the CLI against the payment method on the Stripe account (docs). Not confirmed live: we have no Stripe account or card.",
   "detected_grade": "P3",
   "exercised": false
  },
  "cancel": {
   "status": "n/a",
   "note": "Nothing to cancel: our agent used the free plan.",
   "docs_note": "No plan started. Documented: 'stripe projects upgrade firecrawl' to free or 'stripe projects remove firecrawl' cancels the plan; also dashboard Billing.",
   "docs_grade": "",
   "nothing": "free_plan"
  },
  "delete": {
   "status": "blocked",
   "note": "Deleted in the dashboard (Settings > Account > Delete, DELETE typed, password re-entered); login stopped working afterward. We could not confirm the deletion took effect.",
   "left": "stuck",
   "account": true
  }
 },
 "routes": [],
 "checkout": null,
 "docs": null,
 "claims": null,
 "pay_options": {
  "checked": "2026-10-06",
  "source": "drive",
  "options": [
   {
    "id": "stripe-projects",
    "name": "Stripe Projects",
    "kind": "agent-rail",
    "first_party": true,
    "lead": false,
    "networks": [],
    "testnet": false
   }
  ],
  "agentic": [
   "stripe-projects"
  ],
  "paid": null,
  "exercised": false,
  "detected_grade": "P3",
  "trial": {
   "no_card": null,
   "card_required": null,
   "free_plan": true
  },
  "owner_fixes": [
   {
    "title": "Accept x402 or MPP on your API",
    "how": "Answer an unpaid call with 402 and a payment challenge, so an agent pays per call or buys credits without an account or a card."
   }
  ]
 },
 "surfaces": {
  "api": true,
  "openapi": true,
  "cli": true,
  "sdk": true,
  "mcp": "official",
  "llms_txt": true,
  "webhooks": true,
  "sandbox": false
 },
 "surface_notes": {
  "api": "REST v2, 44 paths / 64 operations; keyless tier for scrape/search/parse/research",
  "openapi": "3.0.0 (behind 3.2.x), no x-payment-info",
  "mcp": "official, the older 25 Nov 2025 spec, 27 tools with key, 3 keyless",
  "cli": "firecrawl-cli (npx) not installed in this drive"
 },
 "can_do": [
  "Scrape a page to markdown/HTML, with or without an account",
  "Crawl a site and read the job back",
  "Map a site's URLs",
  "Search the web with full page content",
  "Extract schema-shaped JSON from a page",
  "Click, run JS, screenshot and print PDF via scrape actions",
  "Run the /agent endpoint for a structured answer",
  "Parse an uploaded PDF to markdown",
  "Batch-scrape a URL list",
  "Ask a question about a page, get highlights",
  "Track changes between scrapes with a diff",
  "Create, run, read and delete a monitor with email alerts",
  "Search the research paper index and the developer index",
  "Diagnose a failed call with /support/ask and list activity with /team/activity",
  "Get an API key through the documented cli-auth flow after the agent clicks Authorize in its own browser"
 ],
 "cannot_do": [
  {
   "what": "Sign up without a browser",
   "why": "Only agent registration is WorkOS ID-JAG (identity_assertion); anonymous and email registration are not offered"
  },
  {
   "what": "Run an Alexandria data provider",
   "why": "403 THIRD_PARTY_DATA_TERMS_REQUIRED: an org admin must accept provider terms on a web page"
  },
  {
   "what": "Manage API keys or delete the account by API",
   "why": "Key create/revoke and account deletion are dashboard-only"
  },
  {
   "what": "Pay through an agent-native rail on Firecrawl's own domain",
   "why": "No 402/x402/MPP; Stripe Projects needs a Stripe account with a card"
  }
 ],
 "blockers": [
  "Sign-up, email verification and first key need a browser (no anonymous agent registration)"
 ],
 "tips_for_owner": [
  "Offer anonymous or email-code agent registration",
  "Add an API route to delete the account",
  "Add key create/revoke endpoints",
  "Fix product format picking the wrong item",
  "Implement MCP (the 28 Jul 2026 spec) server/discover",
  "Publish OpenAPI 3.1+ with a server card"
 ],
 "tips_for_agents": [
  "No key? Use the keyless tier: MCP https://mcp.firecrawl.dev/v2/mcp, or POST https://api.firecrawl.dev/v2/scrape without Authorization (scrape/search/parse/research only).",
  "With a key, send Authorization: Bearer to /v2/mcp to get 27 tools instead of 3.",
  "executeJavascript wraps your script; do not use a top-level return (use an expression or an IIFE).",
  "Free plan rate limits are low (scrape ~10/min, monitor run ~3/min); 429 bodies say how many seconds to wait.",
  "Research papers search has no 'limit' param (400 'Unrecognized key'); full-text passages may be empty.",
  "Alexandria tools need an admin to accept provider terms in the dashboard first.",
  "cli-auth: wait for the page to finish loading before clicking through onboarding, or the clicks are lost."
 ],
 "selfhost": {
  "install": {
   "status": "skipped",
   "minutes": 0,
   "note": "no docker in the drive sandbox; Firecrawl has an open-source edition (github.com/firecrawl/firecrawl)"
  }
 },
 "summary": "Firecrawl's core works for an agent: scrape, crawl, map, search, extract, actions, agent and parse all ran and read back on the free plan, and scrape/search/parse even work keyless through MCP or the API. Getting your own key still needs a browser (web sign-up, PKCE email link, dashboard or cli-auth Authorize), since agent registration only accepts WorkOS ID-JAG. Leaving is web-only: the agent deleted the account in the dashboard, and we could not confirm the deletion took effect.",
 "wall": "Sign-up and first key need a browser",
 "plan_scope": "free plan",
 "robots_stop": null,
 "robots": null,
 "plain": {
  "summary": "Firecrawl is a web-scraping and data-extraction API for AI agents. An agent could do almost everything on its own once it had a key: scraping, crawling, mapping, searching and more all worked, and some of it even works with no account at all. It got its own key in a browser: it signed up, confirmed the email link and approved the CLI login itself. The only automatic sign-up method needs a partner identity token the agent didn't have.",
  "can_do": [
   "Pull clean text, screenshots, and structured data from web pages, even without signing up for an account",
   "Crawl a whole website and read the results back",
   "Search the web and get full page content",
   "Fill out structured questions about a page and get a direct answer",
   "Run small browser actions like clicking a link or taking a screenshot",
   "Upload and read a PDF",
   "Get a key for full account access, but only after clicking through a sign-up page and an email link in a browser"
  ],
  "cannot_do": [
   {
    "what": "Sign up or get a key without a browser",
    "why": "no anonymous or email sign-up offered; the only automatic option needs a partner account the agent lacked"
   },
   {
    "what": "Pay for a paid plan or cancel one",
    "why": "no payment method was available to the agent (no card, no Stripe account)"
   },
   {
    "what": "Confirm the account was fully deleted",
    "why": "the web delete form logged it out, but the drive could not confirm the deletion went through"
   },
   {
    "what": "Use some data-provider add-ons (Alexandria)",
    "why": "a human administrator has to accept the provider's terms on a web page first"
   }
  ]
 },
 "plan_gated": [
  {
   "capability": "Monthly pay-as-you-go spend cap",
   "plan": "paid (Smart Upgrade / Hobby+)",
   "evidence": "Billing tab: Smart Upgrade starts a 19 USD Hobby subscription, then pay-as-you-go up to the cap you set; payment method None"
  },
  {
   "capability": "IP restrictions",
   "plan": "Enterprise",
   "evidence": "docs: 'IP Restrictions are an enterprise feature and are gated per organization.'"
  },
  {
   "capability": "Key restrictions",
   "plan": "Enterprise",
   "evidence": "docs: 'Key Restrictions are an enterprise feature and are gated per organization.'"
  }
 ],
 "reply": null,
 "capabilities": [
  {
   "id": "cap-01",
   "group": "Scrape",
   "capability": "Scrape a single URL into clean markdown/HTML/structured data",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "POST /v2/scrape",
    "mcp": "firecrawl_scrape",
    "cli": "firecrawl <url>",
    "ui": "Playground > Scrape"
   },
   "check": "Response data.markdown/data.html non-empty and data.metadata.statusCode is 2xx/304",
   "source": "https://docs.firecrawl.dev/features/scrape"
  },
  {
   "id": "cap-02",
   "group": "Crawl",
   "capability": "Recursively crawl a whole website and scrape every reachable page",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "POST /v2/crawl, GET /v2/crawl/{id}",
    "mcp": "firecrawl_crawl",
    "cli": "firecrawl crawl <url> --wait",
    "ui": "Playground > Crawl"
   },
   "check": "GET /v2/crawl/{id} shows status completed with data[] containing pages beyond the start URL",
   "source": "https://docs.firecrawl.dev/features/crawl"
  },
  {
   "id": "cap-03",
   "group": "Map",
   "capability": "Map a website to list all discoverable URLs",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "POST /v2/map",
    "mcp": "firecrawl_map",
    "cli": "firecrawl map <url>",
    "ui": "Playground > Map"
   },
   "check": "Response links[] contains URLs under the target domain",
   "source": "https://docs.firecrawl.dev/features/map"
  },
  {
   "id": "cap-04",
   "group": "Search",
   "capability": "Search the web and get full content from results",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "POST /v2/search",
    "mcp": "firecrawl_search",
    "cli": "firecrawl search \"query\"",
    "ui": "Playground > Search"
   },
   "check": "Response data.web[] contains result objects with url/title; with scrapeOptions each result carries markdown",
   "source": "https://docs.firecrawl.dev/features/search"
  },
  {
   "id": "cap-05",
   "group": "Extract",
   "capability": "Extract structured JSON from a page via schema or prompt",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "POST /v2/scrape with formats:[{type:\"json\"}]",
    "mcp": "firecrawl_scrape (json format)",
    "cli": "firecrawl <url> --format json",
    "ui": "Playground > Scrape"
   },
   "check": "Response data.json matches the provided schema's fields with populated values",
   "source": "https://docs.firecrawl.dev/features/scrape#extract-structured-data"
  },
  {
   "id": "cap-06",
   "group": "Interact",
   "capability": "Drive a live browser session (click, type, scroll, screenshot, run JS) to interact with pages",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "POST /v2/scrape with actions[], POST /v2/interact",
    "mcp": "firecrawl_scrape (actions)",
    "cli": null,
    "ui": "Browser (app/browser)"
   },
   "check": "Response actions.javascriptReturns/actions.screenshots reflect the requested interaction sequence",
   "source": "https://docs.firecrawl.dev/advanced-scraping-guide#actions; https://docs.firecrawl.dev/dashboard"
  },
  {
   "id": "cap-07",
   "group": "Agent",
   "capability": "Run an autonomous AI agent that browses, follows links, and extracts data from a prompt",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "POST /v2/agent",
    "mcp": "firecrawl agent tool",
    "cli": null,
    "ui": "Agent (app/agent)"
   },
   "check": "Agent job status completed with structured output matching the prompt's goal",
   "source": "https://docs.firecrawl.dev/dashboard; https://www.firecrawl.dev/pricing"
  },
  {
   "id": "cap-08",
   "group": "Parse",
   "capability": "Parse uploaded documents (PDF, DOCX, spreadsheets) into clean markdown/JSON",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "POST /v2/parse",
    "mcp": "firecrawl_parse",
    "cli": null,
    "ui": null
   },
   "check": "Response markdown is non-empty and reflects the uploaded document's content",
   "source": "https://www.firecrawl.dev/changelog (v2.10 is live - /parse endpoint)"
  },
  {
   "id": "cap-09",
   "group": "Scrape",
   "capability": "Batch-scrape a list of URLs in one job",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST /v2/batch/scrape, GET /v2/batch/scrape/{id}",
    "mcp": "firecrawl_batch_scrape",
    "cli": null,
    "ui": null
   },
   "check": "GET /v2/batch/scrape/{id} shows status completed with data.length equal to submitted URL count",
   "source": "https://docs.firecrawl.dev/features/batch-scrape"
  },
  {
   "id": "cap-10",
   "group": "Scrape",
   "capability": "Ask a natural-language question about a page and get a grounded answer",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST /v2/scrape with formats:[\"question\"]",
    "mcp": null,
    "cli": null,
    "ui": "Playground > Scrape"
   },
   "check": "Response data.answer directly addresses the submitted question text",
   "source": "https://www.firecrawl.dev/changelog (Question Format)"
  },
  {
   "id": "cap-11",
   "group": "Scrape",
   "capability": "Get highlighted sentences/code/table rows on a page matching a query",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST /v2/scrape with formats:[\"highlights\"]",
    "mcp": null,
    "cli": null,
    "ui": null
   },
   "check": "Response highlights array contains exact source-page excerpts matching the query",
   "source": "https://www.firecrawl.dev/changelog (Highlights Format)"
  },
  {
   "id": "cap-12",
   "group": "Scrape",
   "capability": "Extract structured product data (title, price, availability, variants) deterministically",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST /v2/scrape with formats:[\"product\"]",
    "mcp": null,
    "cli": null,
    "ui": null
   },
   "check": "Response data.product has title/price/availability populated without defining a schema",
   "source": "https://docs.firecrawl.dev/features/scrape#scrape-formats"
  },
  {
   "id": "cap-13",
   "group": "Scrape",
   "capability": "Generate structured JSON without an LLM call via a cached deterministic extractor",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST /v2/scrape with formats:[\"deterministicJson\"]",
    "mcp": null,
    "cli": null,
    "ui": null
   },
   "check": "Repeat scrapes of the same site return consistent JSON fields faster/cheaper than LLM json mode",
   "source": "https://www.firecrawl.dev/changelog (v2.11.0 is live - deterministicJson format)"
  },
  {
   "id": "cap-14",
   "group": "Scrape",
   "capability": "Capture a screenshot of a page (viewport or full page)",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST /v2/scrape with formats:[\"screenshot\"]",
    "mcp": "firecrawl_scrape (screenshot)",
    "cli": "firecrawl <url> --format screenshot",
    "ui": "Playground > Scrape"
   },
   "check": "Response data.screenshot is a resolvable image URL (expires after 24h)",
   "source": "https://docs.firecrawl.dev/features/scrape#scrape-formats"
  },
  {
   "id": "cap-15",
   "group": "Scrape",
   "capability": "Generate a PDF of a page via browser action",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST /v2/scrape with actions:[{type:\"pdf\"}]",
    "mcp": null,
    "cli": null,
    "ui": null
   },
   "check": "Response actions output includes a downloadable PDF for the requested page/format",
   "source": "https://docs.firecrawl.dev/advanced-scraping-guide#actions"
  },
  {
   "id": "cap-16",
   "group": "Scrape",
   "capability": "Extract audio or video from a page (e.g. YouTube)",
   "weight": "secondary",
   "plan": "paid",
   "surfaces": {
    "api": "POST /v2/scrape with formats:[\"audio\"/\"video\"]",
    "mcp": null,
    "cli": null,
    "ui": null
   },
   "check": "Response data.video/data.audio is a signed GCS URL that resolves to the page's media (expires 1h)",
   "source": "https://docs.firecrawl.dev/features/scrape#scrape-formats; https://www.firecrawl.dev/changelog (video discovery)"
  },
  {
   "id": "cap-17",
   "group": "Change tracking",
   "capability": "Detect and diff changes in a page's content between scrapes",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST /v2/scrape with formats:[\"changeTracking\"]",
    "mcp": null,
    "cli": null,
    "ui": null
   },
   "check": "Second scrape of same URL returns changeTracking.changeStatus 'changed' with a diff after content edit",
   "source": "https://docs.firecrawl.dev/features/change-tracking"
  },
  {
   "id": "cap-18",
   "group": "Monitor",
   "capability": "Set up a scheduled monitor that watches pages/queries and alerts on matching changes",
   "weight": "secondary",
   "plan": "paid",
   "surfaces": {
    "api": "POST /v2/monitor",
    "mcp": null,
    "cli": null,
    "ui": null
   },
   "check": "GET monitor status shows scheduled checks and a check.completed webhook/email fired when content changed",
   "source": "https://www.firecrawl.dev/changelog (Introducing /monitor; Web-scale /monitor)"
  },
  {
   "id": "cap-19",
   "group": "Scrape",
   "capability": "Redact PII (names, emails, phone numbers, secrets) from scraped output",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST /v2/scrape with redactPII:true",
    "mcp": null,
    "cli": null,
    "ui": null
   },
   "check": "Response markdown has known PII patterns from the source page replaced/removed",
   "source": "https://www.firecrawl.dev/changelog (v2.11.0 is live - Automatic PII redaction)"
  },
  {
   "id": "cap-20",
   "group": "Scrape",
   "capability": "Run cache-only Lockdown Mode scrapes with zero data retention",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST /v2/scrape with lockdown:true",
    "mcp": "firecrawl_scrape (lockdown)",
    "cli": "firecrawl <url> --lockdown",
    "ui": null
   },
   "check": "Lockdown request returns only previously indexed content with no outbound fetch for uncached URLs",
   "source": "https://www.firecrawl.dev/changelog (Lockdown Mode)"
  },
  {
   "id": "cap-21",
   "group": "Alexandria",
   "capability": "Discover and call 100+ third-party data providers (company/people enrichment, financial, government data) through one connection",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "Alexandria endpoints via Firecrawl API",
    "mcp": "Alexandria tools",
    "cli": null,
    "ui": "app/alexandria"
   },
   "check": "Discovery call lists providers/tools with price; execution call returns the provider's data (e.g. Apollo person search results)",
   "source": "https://www.firecrawl.dev/changelog (People and company enrichment in Alexandria; Alexandria and the Developer Index are now in ChatGPT and Codex)"
  },
  {
   "id": "cap-22",
   "group": "Research Index",
   "capability": "Search and read full text from an index of academic/life-science papers",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "GET /v2/search/research/papers, /search_papers, /related_papers, /read_paper",
    "mcp": "Research Index tools",
    "cli": null,
    "ui": null
   },
   "check": "search_papers returns paperId/title/abstract matches; read_paper returns full text for a returned paperId",
   "source": "https://www.firecrawl.dev/changelog (Firecrawl Research Index; Life Sciences in Firecrawl Research Index)"
  },
  {
   "id": "cap-23",
   "group": "Developer Index",
   "capability": "Search a specialized index of READMEs, docs, issues, PRs, and OpenAPI specs for coding questions",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST /v2/search/developer",
    "mcp": "Developer Index tools",
    "cli": "npx firecrawl-cli setup developer-index",
    "ui": null
   },
   "check": "Response results carry stable ids, urls, and matched passages relevant to the coding query",
   "source": "https://www.firecrawl.dev/changelog (Firecrawl Developer Index)"
  },
  {
   "id": "cap-24",
   "group": "Delivery",
   "capability": "Receive real-time webhook notifications for crawl/batch/extract/agent/monitor job events",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "webhook object on POST /v2/crawl, /v2/batch/scrape, /v2/agent, /v2/monitor",
    "mcp": null,
    "cli": null,
    "ui": null
   },
   "check": "Configured HTTPS endpoint receives started/page/completed POSTs with matching job metadata",
   "source": "https://docs.firecrawl.dev/webhooks/overview"
  },
  {
   "id": "cap-25",
   "group": "Delivery",
   "capability": "Verify webhook authenticity via signed payloads",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "webhook signature header",
    "mcp": null,
    "cli": null,
    "ui": "Settings > Advanced (signing secret)"
   },
   "check": "Recomputed HMAC from the signing secret matches the signature header on a delivered webhook",
   "source": "https://docs.firecrawl.dev/webhooks/security"
  },
  {
   "id": "cap-26",
   "group": "Browser",
   "capability": "Create persistent authenticated browser profiles for pages that require login",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Browser (app/browser)"
   },
   "check": "A saved profile reused on a later session stays logged in to the target site",
   "source": "https://docs.firecrawl.dev/dashboard (Browser section)"
  },
  {
   "id": "cap-27",
   "group": "Location",
   "capability": "Scrape/map with a chosen country proxy and language/locale emulation",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "location param on /v2/scrape, /v2/map, /v2/crawl",
    "mcp": null,
    "cli": null,
    "ui": null
   },
   "check": "Response content/metadata reflects the requested country's language and locale-specific content",
   "source": "https://docs.firecrawl.dev/features/map#location-and-language"
  },
  {
   "id": "cap-28",
   "group": "Scrape",
   "capability": "Emulate a mobile device for scraping responsive/mobile-only layouts",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "mobile:true on /v2/scrape",
    "mcp": null,
    "cli": null,
    "ui": null
   },
   "check": "Mobile-layout content/screenshot differs from desktop scrape of the same URL",
   "source": "https://docs.firecrawl.dev/advanced-scraping-guide#mobile-scraping"
  },
  {
   "id": "cap-29",
   "group": "Account",
   "capability": "View activity logs of past API requests and auto-diagnose failed jobs",
   "weight": "peripheral",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Activity Logs (app/logs)"
   },
   "check": "A failed job row's Debug issue button returns a diagnosis referencing that job's error",
   "source": "https://docs.firecrawl.dev/dashboard (Activity Logs)"
  },
  {
   "id": "cap-30",
   "group": "Account",
   "capability": "Create, view, and revoke API keys",
   "weight": "peripheral",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": "firecrawl login",
    "ui": "API Keys (app/api-keys)"
   },
   "check": "A newly created key authenticates a request; a revoked key is rejected",
   "source": "https://docs.firecrawl.dev/dashboard (API Keys)"
  },
  {
   "id": "cap-31",
   "group": "Account",
   "capability": "Invite teammates and assign Admin/Member roles",
   "weight": "peripheral",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Settings > Team"
   },
   "check": "Invited member appears in team list with the assigned role's permissions enforced",
   "source": "https://docs.firecrawl.dev/dashboard (Team management & roles)"
  },
  {
   "id": "cap-32",
   "group": "Account",
   "capability": "Set a monthly pay-as-you-go credit spend limit",
   "weight": "peripheral",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Settings > Billing"
   },
   "check": "Usage page shows credit purchases stop once the configured monthly cap is reached",
   "source": "https://www.firecrawl.dev/pricing (Billing FAQ - How does pay-as-you-go work?)"
  },
  {
   "id": "cap-33",
   "group": "Enterprise",
   "capability": "Restrict API keys to an allowlist of IP addresses/CIDR ranges",
   "weight": "peripheral",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Settings"
   },
   "check": "A request from a non-allowlisted IP using the restricted key is rejected",
   "source": "https://docs.firecrawl.dev/features/ip-restrictions"
  },
  {
   "id": "cap-34",
   "group": "Enterprise",
   "capability": "Lock an API key to specific output formats and endpoints",
   "weight": "peripheral",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Settings"
   },
   "check": "A request from the restricted key to a disallowed endpoint/format is rejected server-side",
   "source": "https://docs.firecrawl.dev/features/key-restrictions"
  }
 ],
 "attempts": [
  {
   "t": "00:23",
   "cap": "discovery",
   "capability": "llms.txt / auth.md / SKILL.md",
   "task": "Fetch agent docs",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "www.firecrawl.dev/llms.txt 200 text/plain; docs.firecrawl.dev/llms.txt 200; /auth.md 200 text/markdown (ID-JAG only, no anonymous); /SKILL.md 200 text/markdown (paths A-G incl. keyless MCP/CLI tier, Stripe Projects, cli-auth browser flow)",
   "notes": ""
  },
  {
   "t": "00:23",
   "cap": "discovery",
   "capability": "robots / cards",
   "task": "robots.txt, ai-catalog, agent-card, ucp",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "robots.txt 200: 'Content-Signal: ai-train=yes, search=yes, ai-input=yes' (Cloudflare Content-signal scheme, no aipref Content-Usage); /.well-known/ai-catalog.json, agent-card.json, ucp -> 404 HTML; api.firecrawl.dev/.well-known/oauth-protected-resource 404 JSON",
   "notes": ""
  },
  {
   "t": "01:43",
   "cap": "discovery",
   "capability": "MCP server/discover",
   "task": "POST server/discover 2026-07-28 to https://mcp.firecrawl.dev/v2/mcp",
   "route": "mcp",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "HTTP 400 JSON-RPC -32000 'Unsupported protocol version: 2026-07-28 (supported versions: 2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05, 2024-10-07)' -- not -32022; legacy server",
   "notes": ""
  },
  {
   "t": "01:43",
   "cap": "discovery",
   "capability": "MCP initialize fallback",
   "task": "initialize offering 2026-07-28",
   "route": "mcp",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "200 text/event-stream; protocolVersion 2025-11-25; serverInfo firecrawl-fastmcp 3.27.3; keyless session exposes firecrawl_search, firecrawl_scrape, firecrawl_parse",
   "notes": ""
  },
  {
   "t": "01:43",
   "cap": "discovery",
   "capability": "OAuth metadata",
   "task": "PRM + AS metadata",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "www.firecrawl.dev/.well-known/oauth-protected-resource 200 JSON (resource api.firecrawl.dev); mcp.firecrawl.dev/.well-known/oauth-protected-resource/v2/mcp-oauth 200; AS metadata: client_id_metadata_document_supported true, registration_endpoint (DCR), grants authorization_code+refresh_token, S256; agent_auth block identity_assertion id-jag only. /v2/mcp-oauth 401 with WWW-Authenticate resource_metadata. Server card /v2/mcp/server-card 404",
   "notes": ""
  },
  {
   "t": "02:20",
   "cap": "signup",
   "capability": "Sign up",
   "task": "Find a documented headless sign-up route",
   "route": "none",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "auth.md: only identity_assertion ID-JAG (WorkOS, iss auth.workos.bot, Firecrawl-trusted client_id), we cannot mint one; no anonymous/verified-email registration; SKILL.md Path D = human browser sign-in; Stripe Projects needs Stripe CLI project (no Stripe account here)",
   "notes": "",
   "quality": {
    "error_legibility": "clear"
   }
  },
  {
   "t": "02:20",
   "cap": "signup",
   "capability": "Sign up",
   "task": "Create account with email+password at /signin?view=signup",
   "route": "browser",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "Form submitted; redirected to /signin/confirm-email?email=the agent's inbox. reCAPTCHA script present (invisible, visible_challenge false), let us through",
   "notes": ""
  },
  {
   "t": "08:17",
   "cap": "verify",
   "capability": "Verify email",
   "task": "Confirm signup link from inbox",
   "route": "browser",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "Mail 'Confirm Your Signup - Firecrawl' from auth@auth.firecrawl.dev arrived <1 min; link service.firecrawl.dev/auth/v1/verify?token=pkce_… (Supabase PKCE, verifier lives in the browser that signed up) -> /onboarding 'Email Verified CLAIMED'",
   "notes": "PKCE link needs the original browser; no OTP/code alternative"
  },
  {
   "t": "08:17",
   "cap": "credentials",
   "capability": "API key",
   "task": "Documented agent flow: SKILL.md Path D cli-auth (session_id + PKCE, poll /api/auth/cli/status)",
   "route": "browser",
   "documented": true,
   "result": "failed",
   "verified": false,
   "evidence": "POST /api/auth/cli/status -> {status:pending}. Opening /cli-auth?code_challenge=…#session_id=… in the signed-in browser redirects to /onboarding?redirect=…; 5-step onboarding; final 'Get Started' (with an endpoint selected) does nothing, and reopening /cli-auth loops back to onboarding step 1. Authorize page never reached.",
   "notes": "Clicked without waiting for page load; see the retry below, which completed",
   "quality": {
    "recoverable": "yes"
   }
  },
  {
   "t": "08:17",
   "cap": "credentials",
   "capability": "API key",
   "task": "Read the Default key on dashboard /app/api-keys (eye button)",
   "route": "browser",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "/app/t/<team>/api-keys lists 'Default' key fc-f02b2…b5429294 created at signup; revealed via eye icon; GET /v2/team/credit-usage with it -> 200 remainingCredits 1000",
   "notes": "Dashboard reachable directly despite unfinished onboarding"
  },
  {
   "t": "08:17",
   "cap": "first_call",
   "capability": "First API call",
   "task": "GET /v2/team/credit-usage with Bearer key",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "200 {remainingCredits:1000, planCredits:1000, billingPeriodEnd 2026-11-06}; bad token -> 401 {success:false,error:'Unauthorized: Invalid token'}",
   "notes": "",
   "quality": {
    "error_legibility": "clear",
    "docs_match": "match"
   }
  },
  {
   "t": "08:27",
   "cap": "cap-01",
   "capability": "Scrape a single URL",
   "task": "Scrape docs.firecrawl.dev/features/scrape to markdown+html",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "POST /v2/scrape 200 success true; markdown 53553 chars, html 630885 chars, metadata.statusCode 200, title 'Scrape | Firecrawl', creditsUsed 1",
   "notes": "",
   "quality": {
    "verify_route": "yes",
    "docs_match": "match"
   }
  },
  {
   "t": "08:39",
   "cap": "cap-03",
   "capability": "Map a website",
   "task": "Map docs.firecrawl.dev (limit 50)",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "POST /v2/map 200 success; 50 links[] all under docs.firecrawl.dev (e.g. /features/scrape with title/description)",
   "notes": "",
   "quality": {
    "docs_match": "match"
   }
  },
  {
   "t": "08:39",
   "cap": "cap-04",
   "capability": "Search the web",
   "task": "Search 'firecrawl changelog parse endpoint' with markdown scrape",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "POST /v2/search 200; data.web 3 results with url/title + markdown (73902, 17535, 118414 chars); creditsUsed 5",
   "notes": "",
   "quality": {
    "docs_match": "match"
   }
  },
  {
   "t": "08:39",
   "cap": "first_action",
   "capability": "First real action",
   "task": "Create a crawl job (POST /v2/crawl)",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "POST /v2/crawl 200 {success:true,id:01a11021-e3b1-…}; job readable at GET /v2/crawl/{id}",
   "notes": ""
  },
  {
   "t": "08:48",
   "cap": "cap-05",
   "capability": "Extract structured JSON",
   "task": "Extract pricing plans with a JSON schema from firecrawl.dev/pricing",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "POST /v2/scrape formats[{type:json,schema}] 200; data.json.plans = Free $0/1000, Hobby $16/5000, Standard $83/100000, Growth $333/500000, Scale $599/1000000, Enterprise",
   "notes": "",
   "quality": {
    "docs_match": "match"
   }
  },
  {
   "t": "08:54",
   "cap": "cap-06",
   "capability": "Interact via browser actions",
   "task": "scrape example.com with click + executeJavascript ('return …') + screenshot",
   "route": "api",
   "documented": true,
   "result": "failed",
   "verified": false,
   "evidence": "POST /v2/scrape actions -> 500 SCRAPE_ACTION_ERROR 'Error in action 3: Javascript execution failed … SyntaxError: Illegal return statement'",
   "notes": "Our script used a top-level return; error names the action index and cause",
   "quality": {
    "error_legibility": "clear",
    "recoverable": "yes"
   }
  },
  {
   "t": "09:07",
   "cap": "cap-06",
   "capability": "Interact via browser actions",
   "task": "Retry: click link on example.com, run JS in IIFE, screenshot",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "POST /v2/scrape actions 200; actions.javascriptReturns[0].value 'https://www.iana.org/help/example-domains | Example Domains' (click navigated); actions.screenshots[0] GCS URL -> 200 image/png 121744 bytes",
   "notes": "",
   "quality": {
    "verify_route": "yes",
    "docs_match": "match"
   }
  },
  {
   "t": "09:19",
   "cap": "cap-02",
   "capability": "Crawl a website",
   "task": "Crawl docs.firecrawl.dev/features (limit 4) and read job back",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "GET /v2/crawl/{id} 200 status completed, completed 4/total 4, data[] sourceURLs /features, /features/llm-extract, /features/ask#…, /features/pii-redaction (beyond start URL); creditsUsed 4",
   "notes": "",
   "quality": {
    "verify_route": "yes",
    "docs_match": "match"
   }
  },
  {
   "t": "09:19",
   "cap": "cap-07",
   "capability": "Agent",
   "task": "POST /v2/agent: Hobby plan price+credits from firecrawl.dev/pricing with schema",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "GET /v2/agent/{id} 200 status completed, model spark-2, data {plan:'Hobby',price_usd_month:19,credits_month:5000}; message notes $19 monthly / $16 annual (consistent with annual figure 16); creditsUsed 0",
   "notes": "",
   "quality": {
    "verify_route": "yes",
    "docs_match": "match"
   }
  },
  {
   "t": "10:26",
   "cap": "cap-08",
   "capability": "Parse a document",
   "task": "Upload a 1-page PDF to POST /v2/parse (multipart)",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "200 success; data.markdown 'AgentDrives parse test: invoice 4711 total 42 EUR' (exact text of the uploaded PDF), numPages 1, contentType application/pdf, creditsUsed 1",
   "notes": "",
   "quality": {
    "docs_match": "match"
   }
  },
  {
   "t": "10:48",
   "cap": "discovery",
   "capability": "MCP tools/list",
   "task": "tools/list keyless vs Bearer key on /v2/mcp",
   "route": "mcp",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "No Mcp-Session-Id issued (stateless in practice). Keyless: firecrawl_scrape, firecrawl_search, firecrawl_parse. With Authorization: Bearer key: 27 tools (scrape, map, search, find_tools, crawl, agent, interact, parse, monitor_* x8, research_* x4, developer_search, credit_usage…); no billing/upgrade tool",
   "notes": ""
  },
  {
   "t": "10:48",
   "cap": "cap-01",
   "capability": "Scrape a single URL",
   "task": "MCP firecrawl_scrape keyless on example.com",
   "route": "mcp",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "tools/call result content[0].text JSON with markdown of example.com, no key",
   "notes": "keyless free tier via official MCP"
  },
  {
   "t": "10:48",
   "cap": "cap-03",
   "capability": "Map a website",
   "task": "MCP firecrawl_map with key on www.firecrawl.dev limit 10",
   "route": "mcp",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "tools/call result: id + links[] under www.firecrawl.dev",
   "notes": ""
  },
  {
   "t": "11:02",
   "cap": "cap-10",
   "capability": "Question format",
   "task": "Ask 'How many credits does the Free plan include?' about firecrawl.dev/pricing",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "POST /v2/scrape formats[{type:question}] 200; data.answer '1,000 credits / month' (matches extraction and credit-usage planCredits 1000)",
   "notes": ""
  },
  {
   "t": "11:02",
   "cap": "cap-11",
   "capability": "Highlights",
   "task": "Highlights for 'screenshot expiry' on docs.firecrawl.dev/features/scrape",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "200; data.highlights = string with the exact source line '- Screenshot (`screenshot`, …): screenshot URLs expire after 24 hours'",
   "notes": "highlights came back as a single markdown string, not an array"
  },
  {
   "t": "11:24",
   "cap": "cap-09",
   "capability": "Batch scrape",
   "task": "Batch-scrape example.com + iana example-domains page",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "POST /v2/batch/scrape 200 id; GET /v2/batch/scrape/{id} status completed 2/2, data sourceURLs both submitted URLs",
   "notes": "",
   "quality": {
    "verify_route": "yes"
   }
  },
  {
   "t": "11:24",
   "cap": "cap-13",
   "capability": "deterministicJson",
   "task": "deterministicJson schema (title/price/availability) on two books.toscrape.com product pages",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "200 data.json {title:'A Light in the Attic',price:'£51.77',availability:'In stock (22 available)'}; second page same fields {'Tipping the Velvet','£53.74','In stock (20 available)'} in 3.0 s; creditsUsed 10 each",
   "notes": "consistent fields across pages; we did not measure an LLM-json baseline for cost/speed"
  },
  {
   "t": "11:24",
   "cap": "cap-12",
   "capability": "Product format",
   "task": "formats:['product'] on books.toscrape.com 'A Light in the Attic' product page",
   "route": "api",
   "documented": true,
   "result": "failed",
   "verified": false,
   "evidence": "200 but data.product absent; data.warning 'No product found on this page; it does not appear to be a product page.' (page has title, price £51.77, availability)",
   "notes": "",
   "quality": {
    "error_legibility": "clear"
   }
  },
  {
   "t": "11:39",
   "cap": "cap-12",
   "capability": "Product format",
   "task": "Retry formats:['product'] on scrapeme.live/shop/Bulbasaur/",
   "route": "api",
   "documented": true,
   "result": "partial",
   "verified": false,
   "evidence": "200; metadata title 'Bulbasaur: ScrapeMe', sourceURL /shop/Bulbasaur/, but data.product.title 'Pidgeot', url scrapeme.live/shop/Pidgeot/, price 185 GBP, '90 in stock'a different product than the page",
   "notes": "schema-less product extraction returned populated fields but for the wrong product (likely a related-products block)",
   "quality": {
    "error_legibility": "silent"
   }
  },
  {
   "t": "11:49",
   "cap": "cap-14",
   "capability": "Screenshot",
   "task": "Full-page screenshot of example.com",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "POST /v2/scrape formats[{type:screenshot,fullPage:true}] 200; data.screenshot GCS signed URL -> 200 image/png 82244 bytes",
   "notes": ""
  },
  {
   "t": "12:00",
   "cap": "cap-15",
   "capability": "PDF action",
   "task": "actions:[{type:pdf,format:A4}] on example.com",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "200; actions.pdfs[0] GCS URL -> 200 application/pdf 51018 bytes, starts %PDF-1.4",
   "notes": ""
  },
  {
   "t": "12:11",
   "cap": "cap-28",
   "capability": "Mobile emulation",
   "task": "mobile:true vs default on example.com, read viewport via executeJavascript",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "mobile:true -> innerWidth 360; default -> 1920 (UA string unchanged: Linux desktop Chrome/154)",
   "notes": "viewport emulated; UA not switched to a mobile UA"
  },
  {
   "t": "12:11",
   "cap": "cap-27",
   "capability": "Location/language",
   "task": "location {country:DE, languages:[de-DE]} on example.com, read navigator.language + timezone",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "DE -> lang 'de-DE', tz 'Europe/Berlin'; default -> 'en-US', 'America/New_York'",
   "notes": ""
  },
  {
   "t": "12:42",
   "cap": "cap-19",
   "capability": "Redact PII",
   "task": "redactPII:true on firecrawl.dev/privacy-policy vs plain scrape",
   "route": "api",
   "documented": true,
   "result": "partial",
   "verified": false,
   "evidence": "200; output has <PRIVATE_PERSON> x2 and <PRIVATE_DATE>; but 'Alexandria' (a product name) was tagged PRIVATE_PERSON, a heading was replaced, and the email help@firecrawl.com stayed unredacted (also in raw scrape)",
   "notes": "redaction ran, but missed an email and redacted non-PII"
  },
  {
   "t": "12:42",
   "cap": "cap-17",
   "capability": "Change tracking",
   "task": "Second scrape of httpbin.org/uuid (new UUID each load) with changeTracking git-diff",
   "route": "api",
   "documented": true,
   "result": "failed",
   "verified": false,
   "evidence": "first call 200 changeStatus 'new'; second call 429 'Rate limit exceeded. Consumed (req/min): 11, Remaining (req/min): 0 … retry after 16s, resets at …'",
   "notes": "free plan scrape rate limit ~10 req/min; error names wait time",
   "quality": {
    "error_legibility": "clear",
    "recoverable": "yes"
   }
  },
  {
   "t": "13:16",
   "cap": "cap-17",
   "capability": "Change tracking",
   "task": "Retry after 25 s: third scrape of httpbin.org/uuid with changeTracking git-diff",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "200 changeTracking.changeStatus 'changed', previousScrapeAt 07:37:44, diff.text unified diff '- \"uuid\": \"ccc17a80…\" / + \"uuid\": \"3861c9a5…\"'",
   "notes": "",
   "quality": {
    "verify_route": "yes"
   }
  },
  {
   "t": "13:32",
   "cap": "cap-20",
   "capability": "Lockdown mode",
   "task": "lockdown:true on cached example.com and on an uncached example.com path",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "cached URL -> 200 with markdown; uncached https://example.com/agentdrives-uncached-<ts> -> 404 SCRAPE_LOCKDOWN_CACHE_MISS 'Lockdown mode only serves previously cached responses and never makes outbound requests…'",
   "notes": "",
   "quality": {
    "error_legibility": "clear"
   }
  },
  {
   "t": "13:50",
   "cap": "cap-16",
   "capability": "Audio extraction",
   "task": "formats:['audio'] on a YouTube video (jNQXAC9IVRw)",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "200 on the free plan; data.audio signed GCS URL youtube-jNQXAC9IVRw.mp3 -> ranged GET 206 audio/mpeg; creditsUsed 5",
   "notes": "capability map lists this as paid; it worked on the free plan"
  },
  {
   "t": "13:50",
   "cap": "cap-18",
   "capability": "Monitor",
   "task": "Create monitor with schedule as string and email as array",
   "route": "api",
   "documented": true,
   "result": "failed",
   "verified": false,
   "evidence": "POST /v2/monitor 400 BAD_REQUEST details: path schedule 'expected object, received string'; path notification.email 'expected object, received array'",
   "notes": "our body was wrong; the error lists each field path",
   "quality": {
    "error_legibility": "clear",
    "recoverable": "yes"
   }
  },
  {
   "t": "15:11",
   "cap": "cap-22",
   "capability": "Research Index",
   "task": "search CRISPR base-editing off-target papers, then read top paper with a query",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "GET /v2/search/research/papers?query=… 200 results with paperId/title/abstract (top: 'Decoding the role of chromatin context… EGOLD', PMC13172344); GET /v2/search/research/papers/{id}?query=chromatin%20accessibility 200 paper metadata + passages",
   "notes": "first try with &limit=3 -> 400 'Unrecognized key: \"limit\"'",
   "quality": {
    "error_legibility": "clear"
   }
  },
  {
   "t": "15:11",
   "cap": "cap-23",
   "capability": "Developer Index",
   "task": "POST /v2/search/developer 'How do I set a webhook on a Firecrawl crawl job in the Python SDK?'",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "200 results with ids (web:…, pull_request:firecrawl/firecrawl#2705), urls, passages ('To set up a webhook, pass a webhook parameter when starting a crawl…')",
   "notes": ""
  },
  {
   "t": "15:48",
   "cap": "cap-22",
   "capability": "Research Index",
   "task": "read_paper full text for top two papers (API query passages, MCP firecrawl_research_read_paper)",
   "route": "api",
   "documented": true,
   "result": "partial",
   "verified": false,
   "evidence": "GET /v2/search/research/papers/{id}?query=… 200 with paper metadata but passages [] for both papers; MCP read_paper -> '(no full-text passages available for this paper)'",
   "notes": "search works; full text not returned for the papers tried"
  },
  {
   "t": "15:48",
   "cap": "cap-21",
   "capability": "Alexandria",
   "task": "Discover a company-enrichment tool and run apollo companies/enrich for firecrawl.dev",
   "route": "api",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "POST /v2/search sources:[alexandria] 200 tools (apollo companies/enrich, bulk-enrich, datalegion…), creditsUsed 0; POST /v2/scrape {alexandria:{provider:apollo,capability:companies/enrich}} -> 403 THIRD_PARTY_DATA_TERMS_REQUIRED 'An organization admin must accept the apollo provider's terms (version F-1.0.0)… https://www.firecrawl.dev/app/alexandria/apollo'",
   "notes": "Firecrawl's SKILL.md says a data request does not authorize the agent to accept these terms; left for a human admin (web page only)",
   "quality": {
    "error_legibility": "clear",
    "recoverable": "no"
   }
  },
  {
   "t": "16:00",
   "cap": "cap-18",
   "capability": "Monitor",
   "task": "Create hourly monitor on httpbin.org/uuid with goal + email to our inbox, run twice, read checks",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "POST /v2/monitor 200 (cron '0 * * * *'); POST /v2/monitor/{id}/run x2; GET /v2/monitor/{id}/checks: check 1 completed new:1, check 2 completed changed:1, notificationStatus.email success; inbox got 'Monitor changes detected: AgentDrives test monitor' from notifications@notifications.firecrawl.dev",
   "notes": "worked on the free plan (map lists paid); /run hit 429 once ('Consumed (req/min): 3 … retry after 38s')",
   "quality": {
    "verify_route": "yes",
    "docs_match": "match"
   }
  },
  {
   "t": "16:16",
   "cap": "cap-24",
   "capability": "Webhooks",
   "task": "Crawl with webhook to an HTTPS endpoint we own",
   "route": "api",
   "documented": true,
   "result": "skipped",
   "verified": false,
   "evidence": "Not tried: we have no public HTTPS receiver of our own in this drive and will not send job data to a third-party bin",
   "notes": "webhook object documented on /v2/crawl, /v2/batch/scrape, /v2/agent, /v2/monitor"
  },
  {
   "t": "16:16",
   "cap": "cap-25",
   "capability": "Webhook signatures",
   "task": "Verify signed webhook payload",
   "route": "api",
   "documented": true,
   "result": "skipped",
   "verified": false,
   "evidence": "Not tried: depends on delivery",
   "notes": ""
  },
  {
   "t": "16:53",
   "cap": "cap-29",
   "capability": "Diagnose failed jobs",
   "task": "POST /v2/support/ask about the earlier SCRAPE_ACTION_ERROR",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "200 answer: 'executeJavascript wraps your script inside an async IIFE … a bare top-level return is a SyntaxError (Illegal return statement). Rewrite … e.g. document.title;'names the exact error we hit",
   "notes": "documented in SKILL.md Path E; the activity-log list itself is dashboard-only (not tried)"
  },
  {
   "t": "20:32",
   "cap": "cap-30",
   "capability": "API keys",
   "task": "Create key 'agentdrives-temp' in dashboard, use it, revoke it, use it again",
   "route": "browser",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "Create dialog -> new key fc-cae32…08dd97a3 listed; GET /v2/team/credit-usage with it 200; '…' menu > Revoke > 'Delete API key?' > Delete; key gone from list; same call -> 401 'Unauthorized: Invalid token'",
   "notes": "no documented API for key management; menu also offers Rename and Set limit"
  },
  {
   "t": "21:23",
   "cap": "credentials",
   "capability": "API key",
   "task": "Retry documented cli-auth flow, waiting for page hydration before each click",
   "route": "browser",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "Onboarding 5 steps completed -> /cli-auth shows 'Authorize'/'Cancel'; after Authorize page says 'You're all set! Authorized for team: Personal'; POST /api/auth/cli/status -> {status:complete, teamName:Personal, apiKey: fc-f02b2… (the existing Default key)}; key works on /v2/team/credit-usage 200",
   "notes": "The first try's clicks ran before each page finished loading; waiting for network idle, the same flow completed. Authorize needs a signed-in browser session."
  },
  {
   "t": "25:51",
   "cap": "discovery",
   "capability": "Markdown docs",
   "task": "Accept: text/markdown on docs page, .md URL, OpenAPI",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "docs.firecrawl.dev/features/scrape with Accept: text/markdown -> 200 content-type text/markdown, vary includes Accept; /features/scrape.md -> 200 text/markdown; www.firecrawl.dev with Accept: text/markdown -> text/html. OpenAPI docs.firecrawl.dev/api-reference/v2-openapi.json: openapi '3.0.0', 44 paths / 64 operations, no x-payment-info",
   "notes": ""
  },
  {
   "t": "25:51",
   "cap": "pay",
   "capability": "Pay step",
   "task": "Probe 402s, subdomains, registries, docs for agent payment",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "Keyless POST /v2/crawl and /v2/agent -> 401 with WWW-Authenticate Bearer resource_metadata (no 402, no PAYMENT-REQUIRED); x402./mpp./agents.firecrawl.dev do not resolve/connect; x402 Bazaar lists only third-party resellers (stableenrich.dev/api/firecrawl/search, vaaya.ai, api.kadec0.xyz); mpp.dev lists 'firecrawl' with integration third-party, serviceUrl firecrawl.mpp.tempo.xyz (POST /v2/scrape -> 404); first-party: Stripe Projects (docs: firecrawl/api free, upgrade firecrawl/hobby|standard|growth via 'stripe projects upgrade firecrawl', paid with a Shared Payment Token on the Stripe account's payment method; docs tell agents to leave paid upgrades to the human). Dashboard Billing: Free plan, 'Payment method None, Add a card'; pricing 'Subscribe' click did not navigate in our agent's browser",
   "notes": "Not confirmed end-to-end: we have no Stripe account or card"
  },
  {
   "t": "25:51",
   "cap": "cap-31",
   "capability": "Team invite",
   "task": "Invite our own second inbox the agent's inbox as Member in Settings > Team",
   "route": "browser",
   "documented": true,
   "result": "partial",
   "verified": false,
   "evidence": "'Invitation sent'; Pending Invitations lists an inbox@ 'Expires in 6 days'; invite mail 'You've been invited to join a Firecrawl team' arrived in an inbox inbox",
   "notes": "not accepted (would need a second account), so role enforcement not checked; role selector showed only 'Member'"
  },
  {
   "t": "25:51",
   "cap": "cap-26",
   "capability": "Browser profiles",
   "task": "Persistent authenticated browser profiles",
   "route": "none",
   "documented": true,
   "result": "skipped",
   "verified": false,
   "evidence": "UI-only per capability map; not tried for time and because it needs a login on a third-party site",
   "notes": ""
  },
  {
   "t": "25:51",
   "cap": "cap-32",
   "capability": "Spend limit",
   "task": "Monthly pay-as-you-go cap",
   "route": "browser",
   "documented": true,
   "result": "plan_gated",
   "verified": false,
   "evidence": "Billing tab: 'Smart Upgrade … we start a monthly Hobby subscription for 19 USD, and from then on pay-as-you-go adds credits at 5 USD per 1,000, up to the monthly cap you set'needs a paid subscription/card (Payment method: None)",
   "notes": ""
  },
  {
   "t": "25:51",
   "cap": "cap-33",
   "capability": "IP restrictions",
   "task": "Allowlist IPs on keys",
   "route": "none",
   "documented": true,
   "result": "plan_gated",
   "verified": false,
   "evidence": "docs/features/ip-restrictions.md: 'IP Restrictions are an enterprise feature and are gated per organization.'",
   "notes": ""
  },
  {
   "t": "25:51",
   "cap": "cap-34",
   "capability": "Key restrictions",
   "task": "Lock key to endpoints/formats",
   "route": "none",
   "documented": true,
   "result": "plan_gated",
   "verified": false,
   "evidence": "docs/features/key-restrictions.md: 'Key Restrictions are an enterprise feature and are gated per organization.'",
   "notes": ""
  },
  {
   "t": "27:28",
   "cap": "cap-29",
   "capability": "Activity logs",
   "task": "GET /v2/team/activity (documented in OpenAPI)",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "200 data[] of our recent jobs with id, endpoint (scrape, research_paper_read…), api_version v2, created_at, target",
   "notes": "",
   "quality": {
    "docs_match": "match"
   }
  },
  {
   "t": "27:28",
   "cap": "delete",
   "capability": "Delete account",
   "task": "Find a documented API/CLI route to delete the account",
   "route": "none",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "OpenAPI v2 paths include /team/activity, credit-usage, queue-status… but no account/team deletion; docs/SKILL.md name none. Dashboard Settings > Account has 'Delete Account'",
   "notes": ""
  },
  {
   "t": "27:28",
   "cap": "cancel",
   "capability": "Cancel plan",
   "task": "Cancel/downgrade",
   "route": "none",
   "documented": true,
   "result": "skipped",
   "verified": false,
   "evidence": "No paid plan was started. Documented routes: 'stripe projects upgrade firecrawl' -> free or 'stripe projects remove firecrawl' (cancels plan; account and key stay), or dashboard Billing",
   "notes": ""
  }
 ],
 "stale": false,
 "icon": "/logos/firecrawl.png",
 "monitored": false,
 "verdict": "Runs on its own, L4, once an agent has a key. Signup stops our agent cold for headless use: auth.md offers only WorkOS ID-JAG, no anonymous path, so a browser filled the web form and an invisible reCAPTCHA let it through. From there work ran clean: scrape, crawl, map, search, extract and parse all completed, and scrape, search and parse even work keyless through MCP or the API without any account. Paying stays undocumented for a first-party agent: no 402 anywhere, and upgrading runs through Stripe Projects against an account we didn't have. Deleting the account also needs the dashboard, and login simply stopped working afterward, with no confirmation the deletion took effect.",
 "page": "https://agentdrives.com/tools/firecrawl?via=api"
}