Crawl4AI vs Firecrawl
In short
Crawl4AI vs Firecrawl: both are research tools on Scriptiii AI Tools. Crawl4AI pricing: Free. Free to use. (reported by the maker) Firecrawl pricing: Free. Free to use. (reported by the maker) Both have 0 upvotes.
- Crawl4AI
- Free. Free to use. (reported by the maker)
- Firecrawl
- Free. Free to use. (reported by the maker)
- Upvotes
- 0 vs 0
| Field | Crawl4AI | Firecrawl |
|---|---|---|
| Page | Crawl4AI | Firecrawl |
| Pricing (maker-reported) | Free. Free to use. | Free. Free to use. |
| Upvotes | 0 | 0 |
| Best for | ai-agents, tool, web-data | ai-agents, tool, web-data |
| Tagline | Open-source web crawler and scraper that produces LLM-ready Markdown. | Web data API that turns websites into LLM-ready Markdown or structured data. |
| Website | Visit Crawl4AI | Visit Firecrawl |
Pricing and pricing details come from the maker's submission. They are not independently verified.
Crawl4AI
Crawl4AI
Crawl4AI Cloud is a hosted web scraping, extraction, and search API for AI agents and data pipelines. Turn pages into clean Markdown for RAG, extract structured JSON, or search the live web with one API key. Crawl4AI runs the browsers and manages the proxies.
Get a free API key · 1,000 free credits every month. No credit card required.
Try a URL in the playground · Set up Crawl4AI Cloud in Claude Code, Cursor, or Codex
This repository is home to the Apache-2.0 crawler that powers Crawl4AI Cloud. Run it yourself with Python or Docker.
Cloud quickstart
Hosted API base URL: https://api.crawl4ai.com.
Cloud API reference · Agent setup and MCP
Set CRAWL4AI_KEY to your API key, then scrape a page as Markdown:
curl -s https://api.crawl4ai.com/scrape \
-H "Authorization: Bearer $CRAWL4AI_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://news.ycombinator.com"}' | jq -r .markdown
Python 3
import json
import os
from urllib.request import Request, urlopen
request = Request(
"https://api.crawl4ai.com/scrape",
data=json.dumps({"url": "https://news.ycombinator.com"}).encode("utf-8"),
headers={
"Authorization": f"Bearer {os.environ['CRAWL4AI_KEY']}",
"Content-Type": "application/json",
},
method="POST",
)
with urlopen(request) as response:
print(json.load(response)["markdown"])
Node.js (18+)
async function main() {
const key = process.env.CRAWL4AI_KEY;
if (!key) throw new Error("Set CRAWL4AI_KEY first.");
const response = await fetch("https://api.crawl4ai.com/scrape", {
method: "POST",
headers: {
Authorization: `Bearer ${key}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ url: "https://news.ycombinator.com" }),
});
if (!response.ok) {
throw new Error(`Scrape failed (HTTP ${response.status}): ${await response.text()}`);
}
const { markdown } = await response.json();
console.log(markdown);
}
main().catch((error) => {
console.error(error.message);
process.exitCode = 1;
});
Example Markdown output (illustrative excerpt):
## Hacker News
1. [Example story title](https://example.com/story)
2. [Another story title](https://example.com/another-story)
The same key works for /extract, /search, /serp, /answer and many URLs at once (/scrape/batch, /scrape/jobs). Pay as you go: live prices.
For Claude Code, connect to the hosted MCP server:
claude mcp add --transport http crawl4ai https://api.crawl4ai.com/mcp \
--header "Authorization: Bearer $CRAWL4AI_KEY"
Run Crawl4AI yourself
Latest: v0.9.5 (14 Oct 2026) · all releases →
pip install -U crawl4ai
crawl4ai-setup # installs the browser, once
import asyncio
from crawl4ai import AsyncWebCrawler
async def main():
async with AsyncWebCrawler() as crawler:
result = await crawler.arun(url="https://news.ycombinator.com")
print(result.markdown)
asyncio.run(main())
Docker server, CLI and every option: Installation · Self-hosted docs
Which one?
| ☁️ Crawl4AI Cloud | 🐍 Library | 🐳 Your own server | |
|---|---|---|---|
| Runs the browsers | we do | you, in your Python process | you, in Docker on your machine |
| JS-heavy pages and bot walls | handled for you, automatically | your settings, your proxies | your settings, your proxies |
| Web search | /search, /serp and /answer | – | – |
| Price | 1,000 free credits a month; plans from $10 | Free, Apache-2.0. You cover infrastructure. | Free, Apache-2.0. You cover hosting. |
🤓 My Personal Story
I grew up on an Amstrad, thanks to my dad, and never stopped building. In grad school I specialized in NLP and built crawlers for research. That’s where I learned how much extraction matters.
In 2023, I needed web-to-Markdown. The “open source” option wanted an account, API token, and $16, and still under-delivered. I went turbo anger mode, built Crawl4AI in days, and it went viral.
I made it open source for availability, anyone can use it without a gate. Now I’m building the platform for affordability, anyone can run serious crawls without breaking the bank. If that resonates, join in, send feedback, or just crawl something amazing.
That platform is live now: Crawl4AI Cloud.
Why developers pick Crawl4AI
- LLM-ready output: smart Markdown with headings, tables, code and citation hints
- Fast in practice: async browser pool, caching, minimal hops
- Full control: sessions, proxies, cookies, user scripts, hooks
- Adaptive intelligence: learns site patterns, explores only what matters
- Deploy anywhere: run locally with Python or the CLI, secure your Docker server with a self-managed token, or use a Crawl4AI Cloud API key.
✨ Features
📝 Markdown generation
- 🧹 Clean Markdown: headings, lists, tables and code blocks, in a structure an LLM reads well.
- 🎯 Fit Markdown: filters remove menus, footers and boilerplate:
PruningContentFilterLXML,BM25ContentFilter(for a query) andLLMContentFilter. - 🔗 Citations: page links become a numbered reference list.
- 🛠️ Your own strategy: plug in a custom Markdown generator.
☁️ Same in the cloud: POST /scrape returns this Markdown, with no browser to run. Docs →
📊 Structured data extraction
- 🔎 CSS and XPath schemas: fast extraction with no LLM (
JsonCssExtractionStrategy,JsonXPathExtractionStrategy,RegexExtractionStrategy). - 🪄 Schema generator: describe what you want once;
generate_schemawrites a reusable schema. - 🤖 LLM extraction: any LLM provider, open-source or hosted, into a typed JSON schema (
LLMExtractionStrategy). - 🧱 Chunking: topic, regex and sentence chunking for long pages.
- 🌌 Cosine similarity: find the chunks that match a query (
CosineStrategy).
☁️ Same in the cloud: POST /extract, with no LLM key of your own. Docs →
🌐 Browser control
- 🖥️ Your own browser: persistent profiles with saved logins, cookies and settings.
- 🔄 Remote browsers: connect over the Chrome DevTools Protocol (CDP).
- 🔒 Sessions: keep a browser state across multi-step crawls.
- 🧩 Proxies: with authentication and rotation.
- 🕶️ Stealth mode:
enable_stealth, and an undetected-browser adapter for sites that detect automation. - ⚙️ Full control: headers, cookies, user agents, viewport.
- 🌍 Chromium, Firefox and WebKit.
🔎 Crawling and scraping
- 🕸️ Deep crawl: BFS, DFS and best-first strategies, with crash recovery (
resume_state) for long crawls. - 🧠 Adaptive crawling:
AdaptiveCrawlerstops when it has learned enough to answer your query. - 🌱 URL discovery:
AsyncUrlSeeder(sitemaps, Common Crawl) andDomainMapper;prefetch=Truefinds URLs 5 to 10 times faster. - 🚀 Dynamic pages: run JavaScript, wait for elements, scroll the full page (
scan_full_page) for infinite scroll and lazy images. - 📸 Screenshots and PDFs of any page.
- 🖼️ Media and links: images, audio, video,
srcset, internal and external links, iframes, metadata. - 📂 Raw HTML and local files:
raw:andfile://. - 🛠️ Hooks at every step of a crawl.
- 💾 Caching to skip repeated fetches.
- ⚡ Many URLs at once:
arun_manywith a memory-adaptive dispatcher.
☁️ Same in the cloud: up to 50 URLs in one streamed call, or 10,000 in a background job. Docs →
🐳 Self-hosting (Docker)
- 🔐 Secure by default: every endpoint needs your
CRAWL4AI_API_TOKEN. - 🧰 REST API:
/md,/html,/crawl,/crawl/stream,/screenshot,/pdf,/execute_js. - 🤖 MCP: connect Claude Code and other agents to your own server.
- 📊 Monitoring dashboard and playground, a browser pool with pre-warmed pages.
- 🏗️ AMD64 and ARM64 images.
☁️ Rather not run a server? The cloud is the same idea, hosted. Get a key →
☁️ What the cloud adds
- 🔍 Web search API:
GET /search, browser-free, ranked and cleaned. Docs → - 📊 SERP API:
GET /serp, Google's results page as data: true ranks, every block, localised to a place. Beta. Docs → - 💬 Answers:
GET /answergives a direct answer to a question (experimental). Docs → - 🧪 Extraction without your own LLM key:
POST /extract. Docs → - 🧗 JS-heavy pages and bot walls: handled automatically; you never pick an engine. Docs →
- 🤝 MCP for your agent: one line in Claude Code, Codex, Cursor or OpenCode. Docs →
🛠️ Installation
🐍 pip
pip install -U crawl4ai
crawl4ai-setup # installs and sets up the browser
crawl4ai-doctor # checks the installation
If the browser setup fails, install it by hand:
python -m playwright install --with-deps chromium
Pre-release versions: pip install crawl4ai --pre
Development install, for contributors:
git clone https://github.com/unclecode/crawl4ai.git
cd crawl4ai
pip install -e ".[all]" # or: pip install -e . (the core only)
🐳 Docker server
The server needs a token. Without one it answers only inside its container.
export CRAWL4AI_API_TOKEN="$(openssl rand -hex 32)"
docker run -d -p 11235:11235 --name crawl4ai --shm-size=1g \
-e CRAWL4AI_API_TOKEN="$CRAWL4AI_API_TOKEN" \
unclecode/crawl4ai:latest
Test it (allow about 10 seconds for the start):
curl -s http://localhost:11235/md \
-H "Authorization: Bearer $CRAWL4AI_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"url": "https://news.ycombinator.com"}' | jq -r .markdown
The dashboard is at http://localhost:11235/dashboard, the playground at http://localhost:11235/playground. LLM keys, MCP and every setting: Self-hosting guide.
⌨️ Command line (`crwl`)
## A page as Markdown
crwl https://news.ycombinator.com -o markdown
## Deep crawl, breadth first, at most 10 pages
crwl https://docs.crawl4ai.com --deep-crawl bfs --max-pages 10
## Ask a question about a page (needs an LLM key: crwl config)
crwl https://www.example.com/products -q "Extract all product prices"
🔬 Advanced usage examples
More in docs/examples.
📝 Clean and fit Markdown
import asyncio
from crawl4ai import AsyncWebCrawler, BrowserConfig, CrawlerRunConfig, CacheMode
from crawl4ai.content_filter_strategy import PruningContentFilterLXML
from crawl4ai.markdown_generation_strategy import DefaultMarkdownGenerator
async def main():
run_config = CrawlerRunConfig(
cache_mode=CacheMode.BYPASS,
markdown_generator=DefaultMarkdownGenerator(
content_filter=PruningContentFilterLXML(threshold=0.48, threshold_type="fixed", min_word_threshold=0)
),
)
async with AsyncWebCrawler(config=BrowserConfig(headless=True)) as crawler:
result = await crawler.arun(url="https://en.wikipedia.org/wiki/Web_crawler", config=run_config)
print(len(result.markdown.raw_markdown), "characters of raw Markdown")
print(len(result.markdown.fit_markdown), "characters after the filter")
asyncio.run(main())
🖥️ A JavaScript page and structured data, without an LLM
import asyncio, json
from crawl4ai import AsyncWebCrawler, BrowserConfig, CrawlerRunConfig, CacheMode, JsonCssExtractionStrategy
schema = {
"name": "Quotes",
"baseSelector": "div.quote",
"fields": [
{"name": "text", "selector": "span.text", "type": "text"},
{"name": "author", "selector": "small.author", "type": "text"},
{"name": "tags", "selector": "a.tag", "type": "list", "fields": [{"name": "tag", "type": "text"}]},
],
}
async def main():
run_config = CrawlerRunConfig(
extraction_strategy=JsonCssExtractionStrategy(schema),
scan_full_page=True, # scroll to the end, so the page loads every quote
scroll_delay=0.5,
cache_mode=CacheMode.BYPASS,
)
async with AsyncWebCrawler(config=BrowserConfig(headless=True)) as crawler:
result = await crawler.arun(url="https://quotes.toscrape.com/scroll", config=run_config)
quotes = json.loads(result.extracted_content)
print(f"Extracted {len(quotes)} quotes")
print(json.dumps(quotes[0], indent=2))
asyncio.run(main())
📚 Structured data with an LLM
import os, asyncio
from pydantic import BaseModel, Field
from crawl4ai import AsyncWebCrawler, CrawlerRunConfig, CacheMode, LLMConfig, LLMExtractionStrategy
class ModelFee(BaseModel):
model_name: str = Field(..., description="Name of the model.")
input_fee: str = Field(..., description="Fee for input tokens.")
output_fee: str = Field(..., description="Fee for output tokens.")
async def main():
run_config = CrawlerRunConfig(
cache_mode=CacheMode.BYPASS,
extraction_strategy=LLMExtractionStrategy(
# any provider LiteLLM supports, e.g. "ollama/llama3.3" with api_token="no-token"
llm_config=LLMConfig(provider="openai/gpt-4o-mini", api_token=os.getenv("OPENAI_API_KEY")),
schema=ModelFee.model_json_schema(),
extraction_type="schema",
instruction="Extract every model name with its input and output token fee.",
),
)
async with AsyncWebCrawler() as crawler:
result = await crawler.arun(url="https://openai.com/api/pricing/", config=run_config)
print(result.extracted_content)
asyncio.run(main())
🤖 Your own browser with a saved profile
import os, asyncio
from pathlib import Path
from crawl4ai import AsyncWebCrawler, BrowserConfig, CrawlerRunConfig, CacheMode
async def main():
user_data_dir = os.path.join(Path.home(), ".crawl4ai", "browser_profile")
os.makedirs(user_data_dir, exist_ok=True)
browser_config = BrowserConfig(headless=True, user_data_dir=user_data_dir, use_persistent_context=True)
run_config = CrawlerRunConfig(cache_mode=CacheMode.BYPASS, magic=True)
async with AsyncWebCrawler(config=browser_config) as crawler:
result = await crawler.arun(url="ADDRESS_OF_A_CHALLENGING_WEBSITE", config=run_config)
print(result.success, len(result.markdown))
asyncio.run(main())
📖 Documentation
- Library docs, guides and API reference: docs.crawl4ai.com
- Cloud docs: crawl4ai.com/docs
- Release notes: releases · Roadmap: ROADMAP.md
🤝 Contributing
We welcome contributions from the open-source community. Check out our contribution guidelines for more information.
📄 License & Attribution
This project is licensed under the Apache License 2.0, attribution is recommended via the badges below. See the Apache 2.0 License file for details.
Attribution Requirements
When using Crawl4AI, you must include one of the following attribution methods:
📈 1. Badge Attribution (Recommended)
Add one of these badges to your README, documentation, or website:| Theme | Badge |
|---|---|
| Disco Theme (Animated) | |
| Night Theme (Dark with Neon) | |
| Dark Theme (Classic) | |
| Light Theme (Classic) |
HTML code for adding the badges:
<a href="https://github.com/unclecode/crawl4ai">
<img src="https://raw.githubusercontent.com/unclecode/crawl4ai/main/docs/assets/powered-by-disco.svg" alt="Powered by Crawl4AI" width="200"/>
</a>
<a href="https://github.com/unclecode/crawl4ai">
<img src="https://raw.githubusercontent.com/unclecode/crawl4ai/main/docs/assets/powered-by-night.svg" alt="Powered by Crawl4AI" width="200"/>
</a>
<a href="https://github.com/unclecode/crawl4ai">
<img src="https://raw.githubusercontent.com/unclecode/crawl4ai/main/docs/assets/powered-by-dark.svg" alt="Powered by Crawl4AI" width="200"/>
</a>
<a href="https://github.com/unclecode/crawl4ai">
<img src="https://raw.githubusercontent.com/unclecode/crawl4ai/main/docs/assets/powered-by-light.svg" alt="Powered by Crawl4AI" width="200"/>
</a>
<a href="https://github.com/unclecode/crawl4ai">
</a>
📖 2. Text Attribution
Add this line to your documentation: ``` This project uses Crawl4AI (https://github.com/unclecode/crawl4ai) for web data extraction. ```📚 Citation
If you use Crawl4AI in your research or project, please cite:
@software{crawl4ai2024,
author = {UncleCode},
title = {Crawl4AI: Open-source LLM Friendly Web Crawler & Scraper},
year = {2024},
publisher = {GitHub},
journal = {GitHub Repository},
howpublished = {\url{https://github.com/unclecode/crawl4ai}},
commit = {Please use the commit hash you're working with}
}
Text citation format:
UncleCode. (2024). Crawl4AI: Open-source LLM Friendly Web Crawler & Scraper [Computer software].
GitHub. https://github.com/unclecode/crawl4ai
🗾 Mission
Our mission is to unlock the value of personal and enterprise data by turning digital footprints into structured, useful assets. Crawl4AI gives individuals and organizations open-source tools to extract and structure data, and a fair way to benefit from it. Full mission statement →
💖 Support Crawl4AI
- ⭐ Star the repo: it helps more people find it.
- ☁️ Use the cloud: crawl4ai.com. It funds the library.
- 💝 Sponsor on GitHub: github.com/sponsors/unclecode
- 🏢 Companies: the sponsor tiers and benefits are in SPONSORS.md.
🌟 Current Sponsors
🤝 Strategic Partners
These companies provide core infrastructure and technology that power Crawl4AI’s capabilities — from web access and proxy networks to AI tooling and data pipelines.
| Company | About |
|---|---|
| Massive provides a web access API for AI agents and data pipelines. Partnership details. |
🏢 Enterprise Sponsors
Our enterprise sponsors support Crawl4AI and help scale it to power production-grade data pipelines.
💼 Become a Strategic Partner or Sponsor
Interested in partnering with Crawl4AI?
Whether you’re a proxy provider, AI infrastructure company, cloud platform, or an organization looking to support the Crawl4AI ecosystem, we’d love to hear from you.
📩 Contact: hello@crawl4ai.com
🧑🤝 Individual Sponsors
A heartfelt thanks to our individual supporters! Every contribution helps us keep our opensource mission alive and thriving!
Want to join them? Sponsor Crawl4AI →
📧 Contact
Discord · X @unclecode · GitHub @unclecode · hello@crawl4ai.com
- Building crawlers or AI agents for a living? DM me on X. I want to work with people like you, and we are hiring.
- From a company? We have an enterprise offer and we tailor it to your business. See our security and compliance page for current details. Write to hello@crawl4ai.com.
Happy crawling! 🕸️🚀
Star History
Firecrawl
🔥 Firecrawl
The API to search, scrape, and interact with the web at scale. Firecrawl is the context API for AI agents. 🔥 Open source and available as a hosted service.
Pst. Hey, you, join our stargazers :)
Why Firecrawl?
- Industry-leading reliability: Covers 96% of the web, including JS-heavy pages — no proxy headaches, just clean data (see benchmarks)
- Blazingly fast: P95 latency of 3.4s across millions of pages, built for real-time agents and dynamic apps
- LLM-ready output: Clean markdown, structured JSON, screenshots, and more — spend fewer tokens, build better AI apps
- We handle the hard stuff: Rotating proxies, orchestration, rate limits, JS-blocked content, and more — zero configuration
- Agent ready: Connect Firecrawl to any AI agent or MCP client with a single command
- Document parsing: Turn PDFs, DOCX, and other documents into clean Markdown or structured JSON
- Actions: Click, scroll, write, wait, and press before extracting content
- Open source: Developed transparently and collaboratively — join our community
Feature Overview
Core Endpoints
| Feature | Description |
|---|---|
| Search | Search the web and get full page content from results |
| Scrape | Convert any URL to markdown, HTML, screenshots, or structured JSON |
| Interact | Scrape a page, then interact with it using AI prompts or code |
More
| Feature | Description |
|---|---|
| Parse | Turn PDFs, DOCX, and other documents into clean Markdown or structured JSON |
| Agent | Automated data gathering, just describe what you need |
| Crawl | Scrape all URLs of a website with a single request |
| Map | Discover all URLs on a website instantly |
| Batch Scrape | Scrape thousands of URLs asynchronously |
| Monitor | Get notified when content on a website changes |
Quick Start
Sign up at firecrawl.dev to get your API key. Try the playground to test it out.
Search
Search the web and get full content from results.
from firecrawl import Firecrawl
app = Firecrawl(api_key="fc-YOUR_API_KEY")
search_result = app.search("firecrawl", limit=5)
Node.js / cURL / CLI
Node.js
import { Firecrawl } from 'firecrawl';
const app = new Firecrawl({apiKey: "fc-YOUR_API_KEY"});
app.search("firecrawl", { limit: 5 })
cURL
curl -X POST 'https://api.firecrawl.dev/v2/search' \
-H 'Authorization: Bearer fc-YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"query": "firecrawl",
"limit": 5
}'
CLI
firecrawl search "firecrawl" --limit 5
Output:
[
{
"url": "https://firecrawl.dev",
"title": "Firecrawl",
"markdown": "Turn websites into..."
},
{
"url": "https://docs.firecrawl.dev",
"title": "Firecrawl Docs",
"markdown": "# Getting Started..."
}
]
Scrape
Get LLM-ready context from any website — markdown, JSON, screenshots, and more.
from firecrawl import Firecrawl
app = Firecrawl(api_key="fc-YOUR_API_KEY")
result = app.scrape('firecrawl.dev')
Node.js / cURL / CLI
Node.js
import { Firecrawl } from 'firecrawl';
const app = new Firecrawl({ apiKey: "fc-YOUR_API_KEY" });
app.scrape('firecrawl.dev')
cURL
curl -X POST 'https://api.firecrawl.dev/v2/scrape' \
-H 'Authorization: Bearer fc-YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"url": "firecrawl.dev"
}'
CLI
firecrawl scrape https://firecrawl.dev
firecrawl https://firecrawl.dev --only-main-content
Output:
## Firecrawl
Firecrawl helps AI agents search, scrape, and interact with the web.
## Features
- Search: Find information across the web
- Scrape: Clean data from any page
- Interact: Click, navigate, and operate pages
- Agent: Autonomous data gathering
Interact
Scrape a page, then interact with it using AI prompts or code.
from firecrawl import Firecrawl
app = Firecrawl(api_key="fc-YOUR_API_KEY")
result = app.scrape("https://amazon.com")
scrape_id = result.metadata.scrape_id
app.interact(scrape_id, prompt="Search for 'mechanical keyboard'")
app.interact(scrape_id, prompt="Click the first result")
Node.js / cURL / CLI
Node.js
import { Firecrawl } from 'firecrawl';
const app = new Firecrawl({apiKey: "fc-YOUR_API_KEY"});
const result = await app.scrape("https://amazon.com");
await app.interact(result.metadata.scrapeId, {
prompt: "Search for 'mechanical keyboard'"
});
await app.interact(result.metadata.scrapeId, {
prompt: "Click the first result"
});
cURL
## 1. Scrape the page
curl -X POST 'https://api.firecrawl.dev/v2/scrape' \
-H 'Authorization: Bearer fc-YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"url": "https://amazon.com"}'
## 2. Interact with the page (use scrapeId from step 1)
curl -X POST 'https://api.firecrawl.dev/v2/scrape/SCRAPE_ID/interact' \
-H 'Authorization: Bearer fc-YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"prompt": "Search for mechanical keyboard"}'
CLI
firecrawl scrape https://amazon.com
firecrawl interact exec --prompt "Search for 'mechanical keyboard'"
firecrawl interact exec --prompt "Click the first result"
Output:
{
"success": true,
"output": "Keyboard available at $100",
"liveViewUrl": "https://liveview.firecrawl.dev/..."
}
Power Your Agent
Connect Firecrawl to any AI agent or MCP client in minutes.
Skill
Give your agent easy access to real-time web data with one command.
npx -y firecrawl-cli@latest init --all --browser
Restart your agent after installing. Works with Claude Code, Antigravity, OpenCode, and more.
MCP
Connect any MCP-compatible client to the web in seconds.
{
"mcpServers": {
"firecrawl-mcp": {
"command": "npx",
"args": ["-y", "firecrawl-mcp"],
"env": {
"FIRECRAWL_API_KEY": "fc-YOUR_API_KEY"
}
}
}
}
Agent Onboarding
Are you an AI agent? Fetch this skill to sign up your user, get an API key, and start building with Firecrawl.
curl -s https://firecrawl.dev/agent-onboarding/SKILL.md
See the Skill + CLI documentation for all available commands. For MCP, see firecrawl-mcp-server.
More Endpoints
Agent
The easiest way to get data from the web. Describe what you need, and our AI agent searches, navigates, and retrieves it. No URLs required.
Agent is the evolution of our /extract endpoint: faster, more reliable, and doesn't require you to know the URLs upfront.
curl -X POST 'https://api.firecrawl.dev/v2/agent' \
-H 'Authorization: Bearer fc-YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"prompt": "Find the pricing plans for Notion"
}'
Response:
{
"success": true,
"data": {
"result": "Notion offers the following pricing plans:\n\n1. Free - $0/month...\n2. Plus - $10/seat/month...\n3. Business - $18/seat/month...",
"sources": ["https://www.notion.so/pricing"]
}
}
Agent with Structured Output
Use a schema to get structured data:
from firecrawl import Firecrawl
from pydantic import BaseModel, Field
from typing import List, Optional
app = Firecrawl(api_key="fc-YOUR_API_KEY")
class Founder(BaseModel):
name: str = Field(description="Full name of the founder")
role: Optional[str] = Field(None, description="Role or position")
class FoundersSchema(BaseModel):
founders: List[Founder] = Field(description="List of founders")
result = app.agent(
prompt="Find the founders of Firecrawl",
schema=FoundersSchema
)
print(result.data)
{
"founders": [
{"name": "Eric Ciarla", "role": "Co-founder"},
{"name": "Nicolas Camara", "role": "Co-founder"},
{"name": "Caleb Peffer", "role": "Co-founder"}
]
}
Agent with URLs (Optional)
Focus the agent on specific pages:
result = app.agent(
urls=["https://docs.firecrawl.dev", "https://firecrawl.dev/pricing"],
prompt="Compare the features and pricing information"
)
Effort Selection
Set how much reasoning the agent spends on the task:
| Effort | Best For |
|---|---|
low | Simple lookups on one site |
medium | Multi-step tasks on a few pages |
high | Deep research, complex navigation, critical data |
result = app.agent(
prompt="Compare enterprise features across Firecrawl, Apify, and ScrapingBee",
effort="high"
)
Every effort level runs the spark-2 model. Effort changes the reasoning
budget, not the model.
Model
Every agent run executes on spark-2, the default, so you don't need to set
model. The retired spark-1-pro and spark-1-mini names are still accepted
for backwards compatibility, but they are deprecated and run spark-2.
Learn more about Spark models in our Agent documentation.
Crawl
Crawl an entire website and get content from all pages.
curl -X POST 'https://api.firecrawl.dev/v2/crawl' \
-H 'Authorization: Bearer fc-YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"url": "https://docs.firecrawl.dev",
"limit": 100,
"scrapeOptions": {
"formats": ["markdown"]
}
}'
Returns a job ID:
{
"success": true,
"id": "123-456-789",
"url": "https://api.firecrawl.dev/v2/crawl/123-456-789"
}
Check Crawl Status
curl -X GET 'https://api.firecrawl.dev/v2/crawl/123-456-789' \
-H 'Authorization: Bearer fc-YOUR_API_KEY'
{
"status": "completed",
"total": 50,
"completed": 50,
"creditsUsed": 50,
"data": [
{
"markdown": "# Page Title\n\nContent...",
"metadata": {"title": "Page Title", "sourceURL": "https://..."}
}
]
}
Note: The SDKs handle polling automatically for a better developer experience.
Map
Discover all URLs on a website instantly.
curl -X POST 'https://api.firecrawl.dev/v2/map' \
-H 'Authorization: Bearer fc-YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"url": "https://firecrawl.dev"}'
Response:
{
"success": true,
"links": [
{"url": "https://firecrawl.dev", "title": "Firecrawl", "description": "The context API for AI agents"},
{"url": "https://firecrawl.dev/pricing", "title": "Pricing", "description": "Firecrawl pricing plans"},
{"url": "https://firecrawl.dev/blog", "title": "Blog", "description": "Firecrawl blog"}
]
}
Map with Search
Find specific URLs within a site:
from firecrawl import Firecrawl
app = Firecrawl(api_key="fc-YOUR_API_KEY")
result = app.map("https://firecrawl.dev", search="pricing")
## Returns URLs ordered by relevance to "pricing"
Batch Scrape
Scrape multiple URLs at once:
from firecrawl import Firecrawl
app = Firecrawl(api_key="fc-YOUR_API_KEY")
job = app.batch_scrape([
"https://firecrawl.dev",
"https://docs.firecrawl.dev",
"https://firecrawl.dev/pricing"
], formats=["markdown"])
for doc in job.data:
print(doc.metadata.source_url)
SDKs
Our SDKs provide a convenient way to use all Firecrawl features and automatically handle polling for async operations.
Python
Install the SDK:
pip install firecrawl
from firecrawl import Firecrawl
app = Firecrawl(api_key="fc-YOUR_API_KEY")
## Scrape a single URL
doc = app.scrape("https://firecrawl.dev", formats=["markdown"])
print(doc.markdown)
## Use the Agent for autonomous data gathering
result = app.agent(prompt="Find the founders of Stripe")
print(result.data)
## Crawl a website (automatically waits for completion)
docs = app.crawl("https://docs.firecrawl.dev", limit=50)
for doc in docs.data:
print(doc.metadata.source_url, doc.markdown[:100])
## Search the web
results = app.search("best AI data tools 2024", limit=10)
print(results)
Node.js
Install the SDK:
npm install firecrawl
import { Firecrawl } from 'firecrawl';
const app = new Firecrawl({ apiKey: 'fc-YOUR_API_KEY' });
// Scrape a single URL
const doc = await app.scrape('https://firecrawl.dev', { formats: ['markdown'] });
console.log(doc.markdown);
// Use the Agent for autonomous data gathering
const result = await app.agent({ prompt: 'Find the founders of Stripe' });
console.log(result.data);
// Crawl a website (automatically waits for completion)
const docs = await app.crawl('https://docs.firecrawl.dev', { limit: 50 });
docs.data.forEach(doc => {
console.log(doc.metadata.sourceURL, doc.markdown.substring(0, 100));
});
// Search the web
const results = await app.search('best AI data tools 2024', { limit: 10 });
results.data.web.forEach(result => {
console.log(`${result.title}: ${result.url}`);
});
Go
Install the SDK:
go get github.com/firecrawl/firecrawl/apps/go-sdk
package main
import (
"context"
"fmt"
"log"
firecrawl "github.com/firecrawl/firecrawl/apps/go-sdk"
"github.com/firecrawl/firecrawl/apps/go-sdk/option"
)
func main() {
// Create a client (reads FIRECRAWL_API_KEY from environment)
client, err := firecrawl.NewClient(option.WithAPIKey("fc-YOUR_API_KEY"))
if err != nil {
log.Fatal(err)
}
ctx := context.Background()
// Scrape a single URL
doc, err := client.Scrape(ctx, "https://firecrawl.dev", &firecrawl.ScrapeOptions{
Formats: []string{"markdown"},
})
if err != nil {
log.Fatal(err)
}
fmt.Println(doc.Markdown)
// Use the Agent for autonomous data gathering
agent, err := client.Agent(ctx, &firecrawl.AgentOptions{
Prompt: "Find the founders of Stripe",
})
if err != nil {
log.Fatal(err)
}
fmt.Println(agent.Data)
// Crawl a website (automatically waits for completion)
job, err := client.Crawl(ctx, "https://docs.firecrawl.dev", &firecrawl.CrawlOptions{
Limit: firecrawl.Int(50),
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Crawled %d pages\n", len(job.Data))
// Search the web
results, err := client.Search(ctx, "best AI data tools 2024", &firecrawl.SearchOptions{
Limit: firecrawl.Int(10),
})
if err != nil {
log.Fatal(err)
}
fmt.Println(results)
}
Java
Add the dependency (Gradle/Maven):
repositories {
mavenCentral()
maven { url 'https://jitpack.io' }
}
dependencies {
implementation 'com.github.firecrawl:firecrawl-java-sdk:2.0'
}
import dev.firecrawl.client.FirecrawlClient;
import dev.firecrawl.model.*;
FirecrawlClient client = new FirecrawlClient(
System.getenv("FIRECRAWL_API_KEY"), null, null
);
// Scrape a single URL
ScrapeParams scrapeParams = new ScrapeParams();
scrapeParams.setFormats(new String[]{"markdown"});
FirecrawlDocument doc = client.scrapeURL("https://firecrawl.dev", scrapeParams);
System.out.println(doc.getMarkdown());
// Use the Agent for autonomous data gathering
AgentParams agentParams = new AgentParams("Find the founders of Stripe");
AgentResponse start = client.createAgent(agentParams);
AgentStatusResponse result = client.getAgentStatus(start.getId());
System.out.println(result.getData());
// Crawl a website (polls until completion)
CrawlParams crawlParams = new CrawlParams();
crawlParams.setLimit(50);
CrawlStatusResponse job = client.crawlURL("https://docs.firecrawl.dev", crawlParams, null, 10);
for (FirecrawlDocument page : job.getData()) {
System.out.println(page.getMetadata().get("sourceURL"));
}
// Search the web
SearchParams searchParams = new SearchParams("best AI data tools 2024");
searchParams.setLimit(10);
SearchResponse results = client.search(searchParams);
for (SearchResult r : results.getResults()) {
System.out.println(r.getTitle() + ": " + r.getUrl());
}
Elixir
Add the dependency:
def deps do
[
{:firecrawl, "~> 1.0"}
]
end
## Scrape a URL
{:ok, response} = Firecrawl.scrape_and_extract_from_url(
url: "https://firecrawl.dev",
formats: ["markdown"]
)
## Crawl a website
{:ok, response} = Firecrawl.crawl_urls(
url: "https://docs.firecrawl.dev",
limit: 50
)
## Search the web
{:ok, response} = Firecrawl.search_and_scrape(
query: "best AI data tools 2024",
limit: 10
)
## Map URLs
{:ok, response} = Firecrawl.map_urls(url: "https://example.com")
Rust
Add the dependency:
[dependencies]
firecrawl = "2"
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
use firecrawl::{Client, ScrapeOptions, Format, CrawlOptions};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new("fc-YOUR_API_KEY")?;
// Scrape a URL
let document = client.scrape("https://firecrawl.dev", None).await?;
println!("{:?}", document.markdown);
// Crawl a website
let options = CrawlOptions {
limit: Some(50),
..Default::default()
};
let result = client.crawl("https://docs.firecrawl.dev", options).await?;
println!("Crawled {} pages", result.data.len());
// Search the web
let response = client.search("best web scraping tools 2024", None).await?;
println!("{:?}", response.data);
Ok(())
}
Ruby
Install the SDK:
gem install firecrawl-sdk
require "firecrawl"
client = Firecrawl::Client.new(api_key: "fc-YOUR_API_KEY")
## Scrape a single URL
doc = client.scrape("https://firecrawl.dev",
Firecrawl::Models::ScrapeOptions.new(formats: ["markdown"]))
puts doc.markdown
## Use the Agent for autonomous data gathering
result = client.agent(
Firecrawl::Models::AgentOptions.new(prompt: "Find the founders of Stripe"))
puts result.data
## Crawl a website (automatically waits for completion)
job = client.crawl("https://docs.firecrawl.dev",
Firecrawl::Models::CrawlOptions.new(limit: 50))
job.data.each { |d| puts d.metadata.source_url }
## Search the web
results = client.search("best AI data tools 2024",
Firecrawl::Models::SearchOptions.new(limit: 10))
puts results
.NET
Install the SDK:
dotnet add package firecrawl-sdk
using Firecrawl;
using Firecrawl.Models;
var client = new FirecrawlClient("fc-YOUR_API_KEY");
// Scrape a single URL
var doc = await client.ScrapeAsync("https://firecrawl.dev",
new ScrapeOptions { Formats = new List<object> { "markdown" } });
Console.WriteLine(doc.Markdown);
// Crawl a website (automatically waits for completion)
var job = await client.CrawlAsync("https://docs.firecrawl.dev",
new CrawlOptions { Limit = 50 });
Console.WriteLine($"Crawled {job.Data.Count} pages");
// Search the web
var results = await client.SearchAsync("best AI data tools 2024",
new SearchOptions { Limit = 10 });
Console.WriteLine(results);
PHP
Install the SDK:
composer require firecrawl/firecrawl-sdk
<?php
use Firecrawl\Client\FirecrawlClient;
use Firecrawl\Models\ScrapeOptions;
use Firecrawl\Models\CrawlOptions;
use Firecrawl\Models\SearchOptions;
$client = FirecrawlClient::create(apiKey: 'fc-YOUR_API_KEY');
// Scrape a single URL
$doc = $client->scrape('https://firecrawl.dev', ScrapeOptions::with(
formats: ['markdown'],
));
echo $doc->getMarkdown();
// Crawl a website (automatically waits for completion)
$job = $client->crawl('https://docs.firecrawl.dev', CrawlOptions::with(limit: 50));
foreach ($job->getData() as $page) {
echo $page->getMetadata()['sourceURL'] . "\n";
}
// Search the web
$results = $client->search('best AI data tools 2024', SearchOptions::with(limit: 10));
print_r($results);
Integrations
Agents & AI Tools
- Firecrawl Skills Catalog — install with
npx skills add firecrawl/skills - Firecrawl CLI
- Firecrawl MCP
The build skills (integrating Firecrawl into product code) are authored in this repo under skills/ and mirrored into the catalog by CI. Contributing skills? CLI skills (including the research/developer index skills) → PR firecrawl/cli. Build/SDK skills → PR this repo (skills/). Workflow skills → PR firecrawl/firecrawl-workflows. The catalog (firecrawl/skills) is read-only — never PR it directly.
Platforms
Missing your favorite tool? Open an issue and let us know!
Resources
Open Source vs Cloud
Firecrawl is open source under the AGPL-3.0 license. The cloud version at firecrawl.dev includes additional features:
To run locally, see the Contributing Guide. To self-host, see Self-Hosting Guide.
Contributing
We love contributions! Please read our Contributing Guide before submitting a pull request.
Contributors
License
This project is primarily licensed under the GNU Affero General Public License v3.0 (AGPL-3.0). The SDKs and some UI components are licensed under the MIT License. See the LICENSE files in specific directories for details.
It is the sole responsibility of end users to respect websites' policies when scraping. Users are advised to adhere to applicable privacy policies and terms of use. By default, Firecrawl respects robots.txt directives. By using Firecrawl, you agree to comply with these conditions.
Questions
- Do Crawl4AI and Firecrawl list the same price?
- Both listings report Free. Free to use. Pricing is reported by the maker and is not independently verified.
- Which has more upvotes, Crawl4AI or Firecrawl?
- Both have 0 upvotes.
- What does each maker say Crawl4AI and Firecrawl are for?
- Crawl4AI: Open-source web crawler and scraper that produces LLM-ready Markdown. Firecrawl: Web data API that turns websites into LLM-ready Markdown or structured data.
Crawl4AI alternatives·Firecrawl alternatives·All research tools
