技能创建器
skill-creator
创建、改进和评估自定义技能,把专业流程转化为可重复使用的 AI 能力。
firecrawl【数据与研究】Convert any website into clean, structured data with Firecrawl — API-first web scraping service. Use when someone asks to "turn a website into markdown", "scrape website for LLM", "Firecrawl", "extract website content as clean text", "crawl and convert to structured data", or "scrape website for RAG". Covers single-page scraping, full-site crawling, …
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
Firecrawl is a web data API that turns URLs into LLM-ready content: markdown, HTML, screenshots or structured JSON. It renders JavaScript, handles proxies and anti-bot measures, and parses web-hosted PDFs and DOCX files. The v2 API (https://api.firecrawl.dev/v2/...) has these endpoints: scrape, crawl, map, search, batch scrape, interact (click and type on a scraped page) and agent (describe the data you need, no URLs required; it replaces the old /extract). The core is open source under AGPL-3.0 (SDKs are MIT) and there is a hosted cloud service. Latest releases checked: API/server v2.11.0 (June 2026), npm firecrawl 4.42.x.
npm install firecrawl # Node.js (same code as the older @mendable/firecrawl-js)
pip install firecrawl-py # Python
export FIRECRAWL_API_KEY="fc-..." # key from firecrawl.dev; SDKs read this variable
Scrape and search also work without a key at a low per-IP daily limit; crawl, map and batch need a key. Both SDKs expose one Firecrawl class. The v1 method names (scrapeUrl, crawlUrl, mapUrl, jsonOptions, formats: ["extract"]) are gone in the v2 client; if code uses them, migrate.
// scrape.ts
import { Firecrawl } from "firecrawl";
const firecrawl = new Firecrawl({ apiKey: process.env.FIRECRAWL_API_KEY });
const doc = await firecrawl.scrape("https://docs.stripe.com/payments/checkout", {
formats: ["markdown", "links"],
onlyMainContent: true,
});
console.log(doc.markdown); // clean markdown
console.log(doc.metadata?.title, doc.metadata?.sourceURL, doc.metadata?.statusCode);
Python: doc = firecrawl.scrape(url, formats=["markdown"]), then doc.markdown (options are snake_case, e.g. only_main_content). From a shell: firecrawl scrape https://firecrawl.dev after npm install -g firecrawl and firecrawl login.
crawl() submits the job and polls until it finishes; use startCrawl() plus getCrawlStatus() to poll yourself, or a webhook for big jobs.
const job = await firecrawl.crawl("https://docs.stripe.com/payments", {
limit: 100, // always set it: the default is 10,000 pages
includePaths: ["^/payments/.*"],
scrapeOptions: { formats: ["markdown"] },
});
for (const page of job.data) {
console.log(`${page.metadata?.title}: ${page.markdown?.length} chars`);
}
To list URLs without scraping them (1 credit per call) use firecrawl.map("https://docs.stripe.com", { search: "webhooks" }). For many known URLs use batchScrape([...], { options: { formats: ["markdown"] } }).
For fields from one page, put a json format (schema and/or prompt) into formats; the result is in doc.json. This costs 4 extra credits per page.
import { z } from "zod";
const Product = z.object({
name: z.string(),
price: z.number(),
currency: z.string(),
inStock: z.boolean(),
features: z.array(z.string()),
});
const doc = await firecrawl.scrape("https://www.allbirds.com/products/mens-tree-runners", {
formats: [{ type: "json", schema: Product, prompt: "Extract the product details" }],
});
console.log(doc.json); // { name: "Men's Tree Runners", price: 100, currency: "USD", ... }
For several URLs, unknown URLs, or research-style questions use the agent: await firecrawl.agent({ prompt: "Find the pricing plans for Notion", schema }) (Python: app.agent(prompt=..., schema=Model)); effort is low, medium or high.
Self-host from source with Docker Compose (the old single docker run mendableai/firecrawl image does not exist). Check out an exact release tag, then:
git clone https://github.com/firecrawl/firecrawl.git && cd firecrawl
git checkout v2.11.0
docker compose up -d # API on http://localhost:3002
Point the SDK at it with new Firecrawl({ apiUrl: "http://localhost:3002" }) (or FIRECRAWL_API_URL). The default stack has no authentication (USE_DB_AUTHENTICATION=false), publishes only port 3002, and has no AI provider: set an OpenAI-compatible or Ollama endpoint in .env for JSON extraction. Read SELF_HOST.md before exposing it beyond a trusted network. Some cloud-only features (Fire-engine, advanced anti-bot) are not included.
Run the MCP server with npx -y firecrawl-mcp@3.27.3 and env FIRECRAWL_API_KEY, or install the CLI skill with npx -y firecrawl-cli@1.25.3 init --all. Pin the versions as shown and raise them deliberately; @latest runs whatever was published last.
User prompt: "I want a chatbot that answers questions about our product documentation at docs.northwind.dev."
import { Firecrawl } from "firecrawl";
import { ChromaClient } from "chromadb";
const firecrawl = new Firecrawl({ apiKey: process.env.FIRECRAWL_API_KEY });
const collection = await new ChromaClient().getOrCreateCollection({ name: "northwind-docs" });
const job = await firecrawl.crawl("https://docs.northwind.dev", {
limit: 500,
scrapeOptions: { formats: ["markdown"], onlyMainContent: true },
});
for (const page of job.data) {
const url = page.metadata?.sourceURL ?? "unknown";
const md = page.markdown ?? "";
const chunks = md.match(/[\s\S]{1,1200}/g) ?? []; // naive 1200-char chunks
if (chunks.length === 0) continue;
await collection.add({
ids: chunks.map((_, i) => `${url}#${i}`),
documents: chunks,
metadatas: chunks.map(() => ({ source: url, title: page.metadata?.title ?? "" })),
});
}
Result: up to 500 pages cost 500 credits; the vector store now has chunks tagged with their source URL, ready for retrieval. Prefer heading-based chunking over fixed-size when quality matters.
User prompt: "Tell me when the pricing page of linear.app changes."
import difflib, os, pathlib
from firecrawl import Firecrawl
app = Firecrawl(api_key=os.environ["FIRECRAWL_API_KEY"])
new = app.scrape("https://linear.app/pricing", formats=["markdown"], only_main_content=True).markdown
snapshot = pathlib.Path("pricing.md")
if snapshot.exists():
diff = list(difflib.unified_diff(snapshot.read_text().splitlines(), new.splitlines(), lineterm=""))
print("\n".join(diff) if diff else "No change")
snapshot.write_text(new)
Run it from cron or a CI schedule. Result: the first run saves pricing.md; later runs print a unified diff of changed lines, or "No change". Firecrawl also has a hosted monitor feature in newer SDKs if you want scheduling handled for you.
scrape for one page, map to find URLs, crawl for a whole section, batch scrape for a known list, agent when you do not know where the data lives.limit on crawls and restrict with includePaths / excludePaths: the default is 10,000 pages and each page costs 1 credit.metadata.statusCode.onlyMainContent gives the cleanest LLM input; request only the formats you need.checkPromptInjection: true on a JSON format adds an optional guard.