| name | firecrawl |
| description | Scrape and crawl websites for AI with Firecrawl — scrape single URLs to clean Markdown/HTML, crawl entire sites with depth/path filters, extract structured data with LLM schema, use map to discover all URLs, and batch scrape multiple pages in parallel. |
| triggers | ["firecrawl","fire crawl","firecrawl scrape","firecrawl crawl","firecrawl extract","web scraping ai","scrape to markdown","crawl website ai","firecrawl map","firecrawl batch","structured data extraction web","web scraping llm"] |
| do_not_use_for | ["General web crawling without AI parsing — use Playwright or Puppeteer instead","Web automation (clicking, forms) — use browser-use instead","Simple fetch/parse — use BeautifulSoup + requests instead"] |
| see_also | ["crawl4ai","browser-use"] |
Firecrawl — Web Scraping for AI
Source: mendableai/firecrawl (AGPL-3.0) — turn websites into LLM-ready data
Why Firecrawl
- Returns clean Markdown (not raw HTML) — ready for LLM context
- Handles JavaScript-rendered pages (headless browser under the hood)
- Built-in LLM extraction with Pydantic schema
- Crawl entire sites, map all URLs, batch scrape in parallel
- Managed API or self-hosted Docker
Install
pip install firecrawl-py
npm install @mendable/firecrawl-js
Scrape a Single URL
from firecrawl import FirecrawlApp
app = FirecrawlApp(api_key="fc-your-api-key")
result = app.scrape_url(
"https://docs.anthropic.com/en/docs/about-claude/models",
params={"formats": ["markdown"]},
)
print(result["markdown"])
print(result["metadata"]["title"])
print(result["metadata"]["description"])
result = app.scrape_url(
"https://example.com",
params={"formats": ["markdown", "html"]},
)
Crawl an Entire Website
from firecrawl import FirecrawlApp
app = FirecrawlApp(api_key="fc-your-api-key")
crawl_job = app.async_crawl_url(
"https://docs.example.com",
params={
"limit": 100,
"maxDepth": 3,
"includePaths": ["/docs/.*"],
"excludePaths": ["/blog/.*"],
"formats": ["markdown"],
"onlyMainContent": True,
},
)
job_id = crawl_job["id"]
import time
while True:
status = app.check_crawl_status(job_id)
if status["status"] == "completed":
break
print(f"Crawled: {status['completed']}/{status['total']}")
time.sleep(5)
pages = status["data"]
for page in pages:
print(page["url"], len(page["markdown"]))
Structured Data Extraction (LLM-powered)
from firecrawl import FirecrawlApp
from pydantic import BaseModel
app = FirecrawlApp(api_key="fc-your-api-key")
class ProductInfo(BaseModel):
name: str
price: float
rating: float
reviews_count: int
in_stock: bool
features: list[str]
result = app.scrape_url(
"https://www.amazon.com/dp/B08N5WRWNW",
params={
"formats": ["extract"],
"extract": {
"schema": ProductInfo.model_json_schema(),
"systemPrompt": "Extract product information accurately.",
},
},
)
product = ProductInfo(**result["extract"])
print(product.name, product.price, product.rating)
Map — Discover All URLs
from firecrawl import FirecrawlApp
app = FirecrawlApp(api_key="fc-your-api-key")
map_result = app.map_url(
"https://docs.example.com",
params={
"search": "authentication",
"limit": 500,
},
)
urls = map_result["links"]
print(f"Found {len(urls)} URLs")
for url in urls[:10]:
print(url)
Batch Scrape (Multiple URLs in Parallel)
from firecrawl import FirecrawlApp
app = FirecrawlApp(api_key="fc-your-api-key")
urls = [
"https://docs.example.com/page-1",
"https://docs.example.com/page-2",
"https://docs.example.com/page-3",
]
batch_job = app.async_batch_scrape_urls(
urls,
params={"formats": ["markdown"], "onlyMainContent": True},
)
status = app.check_batch_scrape_status(batch_job["id"])
results = status["data"]
Webhook (Push Results)
from firecrawl import FirecrawlApp
app = FirecrawlApp(api_key="fc-your-api-key")
crawl_job = app.async_crawl_url(
"https://docs.example.com",
params={
"limit": 200,
"webhook": {
"url": "https://your-server.com/webhook/firecrawl",
"headers": {"Authorization": "Bearer your-token"},
"events": ["completed", "page"],
},
},
)
With LangChain
from langchain_community.document_loaders import FireCrawlLoader
loader = FireCrawlLoader(
api_key="fc-your-api-key",
url="https://docs.example.com",
mode="crawl",
params={"limit": 50, "formats": ["markdown"]},
)
docs = loader.load()
for doc in docs[:3]:
print(doc.metadata["url"])
print(doc.page_content[:200])
Self-Hosted (Docker)
git clone https://github.com/mendableai/firecrawl
cd firecrawl
cp apps/api/.env.example apps/api/.env
docker compose up -d
app = FirecrawlApp(api_key="test", api_url="http://localhost:3002")
JavaScript (Node.js)
import FirecrawlApp from "@mendable/firecrawl-js";
import { z } from "zod";
const app = new FirecrawlApp({ apiKey: "fc-your-api-key" });
const scrapeResult = await app.scrapeUrl("https://example.com", {
formats: ["markdown"],
});
console.log(scrapeResult.markdown);
const schema = z.object({
company_mission: z.string(),
founding_year: z.number(),
team_size: z.number(),
});
const extractResult = await app.scrapeUrl("https://example.com/about", {
formats: ["extract"],
extract: { schema },
});
console.log(extractResult.extract);
Anti-Fake-Pass Checks