Firecrawl API Tutorial: Scrape, Crawl, Map — 2026 Guide
This guide walks the REST API you will actually call in production. Firecrawl’s base URL is https://api.firecrawl.dev/v2, centered on /scrape, /crawl, and /map. Authenticate with a Bearer token and JSON request bodies. Budget 1 credit per scraped page and 1 credit per map call (same cost no matter how many links you get back).
Get Your API Key
- Sign up at firecrawl.dev.
- Open the dashboard and copy your API key (starts with
fc-). - Set
FIRECRAWL_API_KEYin your environment or pass it to the SDK.
Never commit API keys. Use environment variables in production.
Scrape Endpoint
Scrape a single URL. Base URL: POST https://api.firecrawl.dev/v2/scrape
from firecrawl import Firecrawl
app = Firecrawl(api_key="fc-YOUR-API-KEY")
doc = app.scrape("https://example.com", formats=["markdown", "links"])
print(doc.get("markdown", "")[:500])
print(doc.get("links", [])[:5])
import Firecrawl from '@mendable/firecrawl-js';
const app = new Firecrawl({ apiKey: "fc-YOUR-API-KEY" });
const doc = await app.scrape("https://example.com", { formats: ["markdown", "links"] });
console.log(doc.markdown?.slice(0, 500));
Formats: markdown, html, links, screenshots, extract. Set onlyMainContent: true (default) to strip nav and footer. Cost: 1 credit per page.
Crawl Endpoint
Crawl multiple pages from a start URL. Use include/exclude patterns to scope.
result = app.crawl(
"https://example.com/docs",
limit=100,
includePaths=["/docs/*"],
excludePaths=["/docs/archive/*"],
scrapeOptions={"formats": ["markdown"]}
)
Crawl is asynchronous. Use the returned job ID to poll for completion or configure webhooks. Each crawled page consumes 1 credit.
Map Endpoint
Discover all URLs on a domain without full extraction. One request returns up to 100,000 links; cost is 1 credit regardless of count.
| Parameter | Default | Description |
|---|---|---|
url | required | Base URL to map |
limit | 5000 | Max links (max 100,000) |
sitemap | include | skip, include, or only |
search | — | Filter by keyword relevance |
mapped = app.map_url("https://example.com", limit=1000, search="docs")
for link in mapped.get("links", [])[:10]:
print(link["url"], link.get("title", ""))
Response shape: { success: true, links: [{ url, title?, description? }] }. See our map endpoint guide for details.
Authentication and Rate Limits
- Header:
Authorization: Bearer fc-YOUR-API-KEY - Free: 500 credits one-time, 2 concurrent requests
- Hobby ($16/mo): 3,000 credits, 5 concurrent
- Standard ($83/mo): 100,000 credits, 50 concurrent
See Firecrawl pricing for full tiers.
Response Format
Typical scrape response:
{
"success": true,
"data": {
"markdown": "# Example Domain\n\n...",
"metadata": {
"title": "Example Domain",
"sourceURL": "https://example.com",
"statusCode": 200
}
}
}
SDKs return the data object directly. Handle success: false and check for error field on failures.
Endpoint Strategy Summary
| Endpoint | Best for | Credits |
|---|---|---|
/scrape | Single pages, validation loops | 1/page |
/map | URL discovery, crawl planning | 1/request |
/crawl | Multi-page extraction | 1/page |
On unfamiliar sites, /map helps you scope /crawl so you do not burn credits blindly. When you already know the URLs, /scrape is the direct tool.
Try the Firecrawl MCP server to connect Firecrawl to Claude or Cursor for agent-driven scraping.
Begin with `/scrape` on a small, known URL list. Confirm markdown and links look right, then add `/map` and `/crawl` when you are ready to widen scope.
Markdown fits RAG and chunking pipelines. For fixed columns and dashboards, prefer structured extraction with an explicit schema.
Retry with exponential backoff, validate fields after each run, and log job metadata. Pair that with URL discovery (`/map`) before large crawls so you are not guessing paths in production.
Yes—run /crawl for multi-page jobs, or fire multiple /scrape calls with a concurrency cap your plan allows. See the Firecrawl batch scraping guide on this site for patterns.




