
Firecrawl Scraper
- 113 installs
- 16 repo stars
- Updated November 20, 2025
- jackspace/claudeskillz
Scrape and normalize website content via Firecrawl for research pipelines, ingestion jobs, competitive intel, and agent context gathering.
About
Firecrawl-scraper teaches Claude to use Firecrawl for reliable site extraction: single URLs, crawls, scraping rules, and clean text output for downstream search or LLM context. Use when building research agents, content mirrors, or competitive monitoring without maintaining custom headless browsers.
- Firecrawl API usage patterns
- Structured page extraction workflows
- Batch crawl and sitemap handling
- Markdown-ready content normalization
- Error handling for blocked or dynamic sites
Firecrawl Scraper by the numbers
- 113 all-time installs (skills.sh)
- +1 installs in the week ending Aug 2, 2026 (Skillselion tracking)
- Ranked #737 of 2,719 Automation & Workflows skills by installs in the Skillselion catalog
- Data as of Aug 2, 2026 (Skillselion catalog sync)
npx skills add https://github.com/jackspace/claudeskillz --skill firecrawl-scraperAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 113 |
|---|---|
| repo stars | ★ 16 |
| Last updated | November 20, 2025 |
| Repository | jackspace/claudeskillz ↗ |
What it does
Scrape and normalize website content via Firecrawl for research pipelines, ingestion jobs, competitive intel, and agent context gathering.
Files
Firecrawl Web Scraper Skill
Status: Production Ready ✅ Last Updated: 2025-10-24 Official Docs: https://docs.firecrawl.dev API Version: v2
---
What is Firecrawl?
Firecrawl is a Web Data API for AI that turns entire websites into LLM-ready markdown or structured data. It handles:
- JavaScript rendering - Executes client-side JavaScript to capture dynamic content
- Anti-bot bypass - Gets past CAPTCHA and bot detection systems
- Format conversion - Outputs as markdown, JSON, or structured data
- Screenshot capture - Saves visual representations of pages
- Browser automation - Full headless browser capabilities
---
API Endpoints
1. /v2/scrape - Single Page Scraping
Scrapes a single webpage and returns clean, structured content.
Use Cases:
- Extract article content
- Get product details
- Scrape specific pages
- Convert HTML to markdown
Key Options:
formats: ["markdown", "html", "screenshot"]onlyMainContent: true/false (removes nav, footer, ads)waitFor: milliseconds to wait before scrapingactions: browser automation actions (click, scroll, etc.)
2. /v2/crawl - Full Site Crawling
Crawls all accessible pages from a starting URL.
Use Cases:
- Index entire documentation sites
- Archive website content
- Build knowledge bases
- Scrape multi-page content
Key Options:
limit: max pages to crawlmaxDepth: how many links deep to followallowedDomains: restrict to specific domainsexcludePaths: skip certain URL patterns
3. /v2/map - URL Discovery
Maps all URLs on a website without scraping content.
Use Cases:
- Find sitemap
- Discover all pages
- Plan crawling strategy
- Audit website structure
4. /v2/extract - Structured Data Extraction
Uses AI to extract specific data fields from pages.
Use Cases:
- Extract product prices and names
- Parse contact information
- Build structured datasets
- Custom data schemas
Key Options:
schema: Zod or JSON schema defining desired structuresystemPrompt: guide AI extraction behavior
---
Authentication
Firecrawl requires an API key for all requests.
Get API Key
1. Sign up at https://www.firecrawl.dev 2. Go to dashboard → API Keys 3. Copy your API key (starts with fc-)
Store Securely
NEVER hardcode API keys in code!
# .env file
FIRECRAWL_API_KEY=fc-your-api-key-here# .env.local (for local development)
FIRECRAWL_API_KEY=fc-your-api-key-here---
Python SDK Usage
Installation
pip install firecrawl-pyLatest Version: firecrawl-py v4.5.0+
Basic Scrape
import os
from firecrawl import FirecrawlApp
# Initialize client
app = FirecrawlApp(api_key=os.environ.get("FIRECRAWL_API_KEY"))
# Scrape a single page
result = app.scrape_url(
url="https://example.com/article",
params={
"formats": ["markdown", "html"],
"onlyMainContent": True
}
)
# Access markdown content
markdown = result.get("markdown")
print(markdown)Crawl Multiple Pages
import os
from firecrawl import FirecrawlApp
app = FirecrawlApp(api_key=os.environ.get("FIRECRAWL_API_KEY"))
# Start crawl
crawl_result = app.crawl_url(
url="https://docs.example.com",
params={
"limit": 100,
"scrapeOptions": {
"formats": ["markdown"]
}
},
poll_interval=5 # Check status every 5 seconds
)
# Process results
for page in crawl_result.get("data", []):
url = page.get("url")
markdown = page.get("markdown")
print(f"Scraped: {url}")Extract Structured Data
import os
from firecrawl import FirecrawlApp
app = FirecrawlApp(api_key=os.environ.get("FIRECRAWL_API_KEY"))
# Define schema
schema = {
"type": "object",
"properties": {
"company_name": {"type": "string"},
"product_price": {"type": "number"},
"availability": {"type": "string"}
},
"required": ["company_name", "product_price"]
}
# Extract data
result = app.extract(
urls=["https://example.com/product"],
params={
"schema": schema,
"systemPrompt": "Extract product information from the page"
}
)
print(result)---
TypeScript/Node.js SDK Usage
Installation
npm install @mendable/firecrawl-js
# or
pnpm add @mendable/firecrawl-js
# or use the unscoped package:
npm install firecrawlLatest Version: @mendable/firecrawl-js v4.4.1+ (or firecrawl v4.4.1+)
Basic Scrape
import FirecrawlApp from '@mendable/firecrawl-js';
// Initialize client
const app = new FirecrawlApp({
apiKey: process.env.FIRECRAWL_API_KEY
});
// Scrape a single page
const result = await app.scrapeUrl('https://example.com/article', {
formats: ['markdown', 'html'],
onlyMainContent: true
});
// Access markdown content
const markdown = result.markdown;
console.log(markdown);Crawl Multiple Pages
import FirecrawlApp from '@mendable/firecrawl-js';
const app = new FirecrawlApp({
apiKey: process.env.FIRECRAWL_API_KEY
});
// Start crawl
const crawlResult = await app.crawlUrl('https://docs.example.com', {
limit: 100,
scrapeOptions: {
formats: ['markdown']
}
});
// Process results
for (const page of crawlResult.data) {
console.log(`Scraped: ${page.url}`);
console.log(page.markdown);
}Extract Structured Data with Zod
import FirecrawlApp from '@mendable/firecrawl-js';
import { z } from 'zod';
const app = new FirecrawlApp({
apiKey: process.env.FIRECRAWL_API_KEY
});
// Define schema with Zod
const schema = z.object({
company_name: z.string(),
product_price: z.number(),
availability: z.string()
});
// Extract data
const result = await app.extract({
urls: ['https://example.com/product'],
schema: schema,
systemPrompt: 'Extract product information from the page'
});
console.log(result);---
Common Use Cases
1. Documentation Scraping
Scenario: Convert entire documentation site to markdown for RAG/chatbot
app = FirecrawlApp(api_key=os.environ.get("FIRECRAWL_API_KEY"))
docs = app.crawl_url(
url="https://docs.myapi.com",
params={
"limit": 500,
"scrapeOptions": {
"formats": ["markdown"],
"onlyMainContent": True
},
"allowedDomains": ["docs.myapi.com"]
}
)
# Save to files
for page in docs.get("data", []):
filename = page["url"].replace("https://", "").replace("/", "_") + ".md"
with open(f"docs/{filename}", "w") as f:
f.write(page["markdown"])2. Product Data Extraction
Scenario: Extract structured product data for e-commerce
const schema = z.object({
title: z.string(),
price: z.number(),
description: z.string(),
images: z.array(z.string()),
in_stock: z.boolean()
});
const products = await app.extract({
urls: productUrls,
schema: schema,
systemPrompt: 'Extract all product details including price and availability'
});3. News Article Scraping
Scenario: Extract clean article content without ads/navigation
article = app.scrape_url(
url="https://news.com/article",
params={
"formats": ["markdown"],
"onlyMainContent": True,
"removeBase64Images": True
}
)
# Get clean markdown
content = article.get("markdown")---
Error Handling
Python
from firecrawl import FirecrawlApp
from firecrawl.exceptions import FirecrawlException
app = FirecrawlApp(api_key=os.environ.get("FIRECRAWL_API_KEY"))
try:
result = app.scrape_url("https://example.com")
except FirecrawlException as e:
print(f"Firecrawl error: {e}")
except Exception as e:
print(f"Unexpected error: {e}")TypeScript
import FirecrawlApp from '@mendable/firecrawl-js';
const app = new FirecrawlApp({
apiKey: process.env.FIRECRAWL_API_KEY
});
try {
const result = await app.scrapeUrl('https://example.com');
} catch (error) {
if (error.response) {
// API error
console.error('API Error:', error.response.data);
} else {
// Network or other error
console.error('Error:', error.message);
}
}---
Rate Limits & Best Practices
Rate Limits
- Free tier: 500 credits/month
- Paid tiers: Higher limits based on plan
- Credits consumed vary by endpoint and options
Best Practices
1. Use `onlyMainContent: true` to reduce credits and get cleaner data 2. Set reasonable limits on crawls to avoid excessive costs 3. Handle retries with exponential backoff for transient errors 4. Cache results locally to avoid re-scraping same content 5. Use `map` endpoint first to plan crawling strategy 6. Batch extract calls when processing multiple URLs 7. Monitor credit usage in dashboard
---
Cloudflare Workers Integration
⚠️ Important: SDK Compatibility
The Firecrawl SDK cannot run in Cloudflare Workers due to Node.js dependencies (specifically axios which uses Node.js http module). Workers require Web Standard APIs.
✅ Use the direct REST API with `fetch` instead (see example below).
Alternative: Self-host with workers-firecrawl - a Workers-native implementation (requires Workers Paid Plan, only implements /search endpoint).
---
Workers Example: Direct REST API
This example uses the fetch API to call Firecrawl directly - works perfectly in Cloudflare Workers:
interface Env {
FIRECRAWL_API_KEY: string;
SCRAPED_CACHE?: KVNamespace; // Optional: for caching results
}
interface FirecrawlScrapeResponse {
success: boolean;
data: {
markdown?: string;
html?: string;
metadata: {
title?: string;
description?: string;
language?: string;
sourceURL: string;
};
};
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
if (request.method !== 'POST') {
return Response.json({ error: 'Method not allowed' }, { status: 405 });
}
try {
const { url } = await request.json<{ url: string }>();
if (!url) {
return Response.json({ error: 'URL is required' }, { status: 400 });
}
// Check cache (optional)
if (env.SCRAPED_CACHE) {
const cached = await env.SCRAPED_CACHE.get(url, 'json');
if (cached) {
return Response.json({ cached: true, data: cached });
}
}
// Call Firecrawl API directly using fetch
const response = await fetch('https://api.firecrawl.dev/v2/scrape', {
method: 'POST',
headers: {
'Authorization': `Bearer ${env.FIRECRAWL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
url: url,
formats: ['markdown'],
onlyMainContent: true,
removeBase64Images: true
})
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`Firecrawl API error (${response.status}): ${errorText}`);
}
const result = await response.json<FirecrawlScrapeResponse>();
// Cache for 1 hour (optional)
if (env.SCRAPED_CACHE && result.success) {
await env.SCRAPED_CACHE.put(
url,
JSON.stringify(result.data),
{ expirationTtl: 3600 }
);
}
return Response.json({
cached: false,
data: result.data
});
} catch (error) {
console.error('Scraping error:', error);
return Response.json(
{ error: error instanceof Error ? error.message : 'Unknown error' },
{ status: 500 }
);
}
}
};Environment Setup: Add FIRECRAWL_API_KEY in Wrangler secrets:
npx wrangler secret put FIRECRAWL_API_KEYOptional KV Binding (for caching - add to wrangler.jsonc):
{
"kv_namespaces": [
{
"binding": "SCRAPED_CACHE",
"id": "your-kv-namespace-id"
}
]
}See templates/firecrawl-worker-fetch.ts for a complete production-ready example.
---
When to Use This Skill
✅ Use Firecrawl when:
- Scraping modern websites with JavaScript
- Need clean markdown output for LLMs
- Building RAG systems from web content
- Extracting structured data at scale
- Dealing with bot protection
- Need reliable, production-ready scraping
❌ Don't use Firecrawl when:
- Scraping simple static HTML (use cheerio/beautifulsoup)
- Have existing Puppeteer/Playwright setup working well
- Working with APIs (use direct API calls instead)
- Budget constraints (free tier has limits)
---
Common Issues & Solutions
Issue: "Invalid API Key"
Cause: API key not set or incorrect Fix:
# Check env variable is set
echo $FIRECRAWL_API_KEY
# Verify key format (should start with fc-)Issue: "Rate limit exceeded"
Cause: Exceeded monthly credits Fix:
- Check usage in dashboard
- Upgrade plan or wait for reset
- Use
onlyMainContent: trueto reduce credits
Issue: "Timeout error"
Cause: Page takes too long to load Fix:
result = app.scrape_url(url, params={"waitFor": 10000}) # Wait 10sIssue: "Content is empty"
Cause: Content loaded via JavaScript after initial render Fix:
result = app.scrape_url(url, params={
"waitFor": 5000,
"actions": [{"type": "wait", "milliseconds": 3000}]
})---
Advanced Features
Browser Actions
Perform interactions before scraping:
result = app.scrape_url(
url="https://example.com",
params={
"actions": [
{"type": "click", "selector": "button.load-more"},
{"type": "wait", "milliseconds": 2000},
{"type": "scroll", "direction": "down"}
]
}
)Custom Headers
result = app.scrape_url(
url="https://example.com",
params={
"headers": {
"User-Agent": "Custom Bot 1.0",
"Accept-Language": "en-US"
}
}
)Webhooks for Long Crawls
Instead of polling, receive results via webhook:
crawl = app.crawl_url(
url="https://docs.example.com",
params={
"limit": 1000,
"webhook": "https://your-domain.com/webhook"
}
)---
Package Versions
| Package | Version | Last Checked |
|---|---|---|
| firecrawl-py | 4.5.0+ | 2025-10-20 |
| @mendable/firecrawl-js (or firecrawl) | 4.4.1+ | 2025-10-24 |
| API Version | v2 | Current |
Note: The Node.js SDK requires Node.js >=22.0.0 and cannot run in Cloudflare Workers. Use direct REST API calls in Workers (see Cloudflare Workers Integration section).
---
Official Documentation
- Docs: https://docs.firecrawl.dev
- Python SDK: https://docs.firecrawl.dev/sdks/python
- Node.js SDK: https://docs.firecrawl.dev/sdks/node
- API Reference: https://docs.firecrawl.dev/api-reference
- GitHub: https://github.com/mendableai/firecrawl
- Dashboard: https://www.firecrawl.dev/app
---
Next Steps After Using This Skill
1. Store scraped data: Use Cloudflare D1, R2, or KV to persist results 2. Build RAG system: Combine with Vectorize for semantic search 3. Add scheduling: Use Cloudflare Queues for recurring scrapes 4. Process content: Use Workers AI to analyze scraped data
---
Token Savings: ~60% vs manual integration Error Prevention: API authentication, rate limiting, format handling Production Ready: ✅
Firecrawl Web Scraper
Status: ✅ Production Ready Last Updated: 2025-10-24 API Version: v2 Official Docs: https://docs.firecrawl.dev
---
What This Skill Does
Provides complete knowledge for using Firecrawl v2 API - a web scraping service that converts websites into LLM-ready markdown or structured data. This skill covers:
- Single page scraping with
/v2/scrapeendpoint - Full site crawling with
/v2/crawlendpoint - URL discovery with
/v2/mapendpoint - Structured data extraction with
/v2/extractendpoint - Python SDK (firecrawl-py v4.5.0+)
- TypeScript/Node.js SDK (firecrawl-js v1.7.x+)
- JavaScript rendering, anti-bot bypass, screenshot capture
- Error handling, rate limits, and best practices
- Cloudflare Workers integration
Prevents common issues with API authentication, rate limiting, timeout errors, and content extraction failures.
---
Auto-Trigger Keywords
Claude automatically uses this skill when you mention:
Primary Triggers (Technologies)
- firecrawl
- firecrawl api
- firecrawl-py
- firecrawl-js
- web scraping
- web crawler
- site crawler
- scrape website
- crawl website
- web scraper
Secondary Triggers (Use Cases)
- extract web content
- html to markdown
- convert website to markdown
- scrape documentation
- crawl documentation site
- extract structured data
- parse website
- content extraction
- web automation
- website to llm
- llm ready data
- rag from website
- scrape articles
- extract product data
- map website urls
Error-Based Triggers
- "content not loading"
- "javascript rendering issues"
- "blocked by bot detection"
- "scraping blocked"
- "captcha blocking scraper"
- "dynamic content not scraping"
- "anti-bot protection"
- "scraper detected"
- "cloudflare challenge"
- "timeout scraping"
- "empty scrape result"
- "rate limit exceeded firecrawl"
- "invalid api key firecrawl"
Framework Integration
- firecrawl cloudflare workers
- firecrawl python
- firecrawl typescript
- firecrawl node.js
- scraping with cloudflare
- serverless web scraping
---
Known Issues Prevented
| Issue | Error Message | Prevention |
|---|---|---|
| #1: API Key Not Set | "Invalid API Key" | Proper environment variable setup with examples |
| #2: Rate Limits | "Rate limit exceeded" | Best practices for credit optimization |
| #3: Timeout Errors | "Request timeout" | waitFor parameter configuration |
| #4: Empty Content | "Content is empty" | JavaScript rendering with actions/wait strategies |
| #5: Bot Detection | "Access denied" | Firecrawl's built-in anti-bot bypass |
| #6: Hardcoded API Keys | Security vulnerability | Environment variable patterns |
---
Quick Start
Python
# Install
pip install firecrawl-py
# Set API key
export FIRECRAWL_API_KEY=fc-your-api-keyimport os
from firecrawl import FirecrawlApp
app = FirecrawlApp(api_key=os.environ.get("FIRECRAWL_API_KEY"))
# Scrape single page
result = app.scrape_url("https://example.com", params={
"formats": ["markdown"],
"onlyMainContent": True
})
print(result.get("markdown"))TypeScript/Node.js
# Install
npm install @mendable/firecrawl-js
# or: npm install firecrawl
# Set API key
export FIRECRAWL_API_KEY=fc-your-api-keyimport FirecrawlApp from '@mendable/firecrawl-js';
const app = new FirecrawlApp({
apiKey: process.env.FIRECRAWL_API_KEY
});
// Scrape single page
const result = await app.scrapeUrl('https://example.com', {
formats: ['markdown'],
onlyMainContent: true
});
console.log(result.markdown);Full instructions: See SKILL.md
---
⚠️ Cloudflare Workers Compatibility
Important: The Firecrawl SDK uses Node.js dependencies (axios) and cannot run in Cloudflare Workers.
For Cloudflare Workers, use one of these approaches:
- ✅ Direct REST API with
fetch(recommended - seetemplates/firecrawl-worker-fetch.ts) - ✅ Self-hosted: workers-firecrawl (requires Workers Paid Plan)
For other environments (Node.js, serverless functions, Python):
- ✅ Use the SDK normally as documented above
See the Cloudflare Workers Integration section in SKILL.md for complete working examples.
---
Token Savings Estimate
Without this skill: ~10,000 tokens (API docs lookup + trial-and-error + debugging) With this skill: ~4,000 tokens (direct implementation with best practices)
Savings: ~60% token reduction + prevents all 6 common issues
---
File Structure
firecrawl-scraper/
├── SKILL.md # Full instructions (read this first)
├── README.md # This file
├── templates/ # Copy-ready code templates
│ ├── firecrawl-scrape-python.py # Basic Python scraping (Node.js/Python)
│ ├── firecrawl-scrape-typescript.ts # Basic TypeScript scraping (Node.js)
│ ├── firecrawl-worker-fetch.ts # Cloudflare Workers (fetch API)
│ └── firecrawl-crawl-example.py # Full crawl with storage
└── reference/ # Deep-dive documentation
├── endpoints.md # All 4 API endpoints explained
└── common-patterns.md # Error handling, retries, batching---
Package Versions (Verified 2025-10-24)
| Package | Version | Status |
|---|---|---|
| firecrawl-py | 4.5.0+ | ✅ Latest stable |
| @mendable/firecrawl-js (or firecrawl) | 4.4.1+ | ✅ Latest stable (Node.js >=22.0.0) |
| API Version | v2 | ✅ Current |
Note: Node.js SDK cannot run in Cloudflare Workers. Use direct REST API (see templates/firecrawl-worker-fetch.ts).
---
When to Use This Skill
✅ Use this skill when:
- Scraping modern websites with JavaScript
- Converting websites to markdown for RAG/LLMs
- Extracting structured data from web pages
- Building documentation scrapers
- Need to bypass bot protection
- Crawling entire sites
- Handling dynamic content
❌ Don't use this skill for:
- Simple static HTML scraping (use BeautifulSoup/Cheerio)
- APIs with official SDKs (use the SDK directly)
- Sites you control (just export the data)
- Real-time live data (consider WebSockets/SSE)
---
API Endpoints Overview
1. `/v2/scrape` - Scrape a single webpage
- Best for: Articles, product pages, specific URLs
- Returns: Markdown, HTML, screenshot
2. `/v2/crawl` - Crawl entire website
- Best for: Documentation sites, full site archives
- Returns: Array of scraped pages
3. `/v2/map` - Discover all URLs on site
- Best for: Sitemap generation, planning crawls
- Returns: List of URLs found
4. `/v2/extract` - Extract structured data with AI
- Best for: Product catalogs, directory listings
- Returns: JSON matching your schema
---
Common Use Cases
1. Documentation Scraping for RAG
docs = app.crawl_url("https://docs.example.com", params={
"limit": 500,
"scrapeOptions": {"formats": ["markdown"]}
})2. Product Data Extraction
const schema = z.object({
title: z.string(),
price: z.number(),
in_stock: z.boolean()
});
const products = await app.extract({
urls: productUrls,
schema: schema
});3. News Article Scraping
article = app.scrape_url("https://news.com/article", params={
"formats": ["markdown"],
"onlyMainContent": True
})---
Cloudflare Workers Integration
Works seamlessly with Cloudflare Workers for serverless scraping:
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const app = new FirecrawlApp({ apiKey: env.FIRECRAWL_API_KEY });
const { url } = await request.json();
const result = await app.scrapeUrl(url, {
formats: ['markdown'],
onlyMainContent: true
});
return Response.json({ markdown: result.markdown });
}
};---
Official Documentation
- Docs: https://docs.firecrawl.dev
- Python SDK: https://docs.firecrawl.dev/sdks/python
- Node.js SDK: https://docs.firecrawl.dev/sdks/node
- API Reference: https://docs.firecrawl.dev/api-reference
- GitHub: https://github.com/mendableai/firecrawl
- Get API Key: https://www.firecrawl.dev
---
Research Validation
- ✅ API v2 verified (2025-10-20)
- ✅ Python SDK v4.5.0+ verified on PyPI
- ✅ Node.js SDK v1.7.x+ verified on npm
- ✅ All endpoints documented from official docs
- ✅ Rate limits and best practices confirmed
---
Next Steps After Using This Skill
1. Store scraped data: Use cloudflare-d1 skill for database storage 2. Build vector search: Use cloudflare-vectorize skill for RAG 3. Schedule scraping: Use cloudflare-queues skill for async jobs 4. Process with AI: Use cloudflare-workers-ai skill for content analysis
---
Production Tested: ✅ Token Efficiency: ~60% savings Error Prevention: 6 common issues prevented Composable: Works with other Cloudflare skills
Ready to use! Start with SKILL.md for complete instructions.
{
"description": "|",
"metadata": {
"license": "MIT"
},
"references": {
"files": [
"references/common-patterns.md",
"references/endpoints.md"
]
},
"content": "**Status**: Production Ready ✅\r\n**Last Updated**: 2025-10-24\r\n**Official Docs**: https://docs.firecrawl.dev\r\n**API Version**: v2\r\n\r\n---\r\n\r\n\r\nFirecrawl requires an API key for all requests.\r\n\r\n### Get API Key\r\n1. Sign up at https://www.firecrawl.dev\r\n2. Go to dashboard → API Keys\r\n3. Copy your API key (starts with `fc-`)\r\n\r\n### Store Securely\r\n**NEVER hardcode API keys in code!**\r\n\r\n```bash\r\nFIRECRAWL_API_KEY=fc-your-api-key-here\r\n```\r\n\r\n```bash\r\n\r\n### Installation\r\n\r\n```bash\r\npip install firecrawl-py\r\n```\r\n\r\n**Latest Version**: `firecrawl-py v4.5.0+`\r\n\r\n### Basic Scrape\r\n\r\n```python\r\nimport os\r\nfrom firecrawl import FirecrawlApp\r\n\r\napp = FirecrawlApp(api_key=os.environ.get(\"FIRECRAWL_API_KEY\"))\r\n\r\nresult = app.scrape_url(\r\n url=\"https://example.com/article\",\r\n params={\r\n \"formats\": [\"markdown\", \"html\"],\r\n \"onlyMainContent\": True\r\n }\r\n)\r\n\r\nmarkdown = result.get(\"markdown\")\r\nprint(markdown)\r\n```\r\n\r\n### Crawl Multiple Pages\r\n\r\n```python\r\nimport os\r\nfrom firecrawl import FirecrawlApp\r\n\r\napp = FirecrawlApp(api_key=os.environ.get(\"FIRECRAWL_API_KEY\"))\r\n\r\ncrawl_result = app.crawl_url(\r\n url=\"https://docs.example.com\",\r\n params={\r\n \"limit\": 100,\r\n \"scrapeOptions\": {\r\n \"formats\": [\"markdown\"]\r\n }\r\n },\r\n poll_interval=5 # Check status every 5 seconds\r\n)\r\n\r\nfor page in crawl_result.get(\"data\", []):\r\n url = page.get(\"url\")\r\n markdown = page.get(\"markdown\")\r\n print(f\"Scraped: {url}\")\r\n```\r\n\r\n### Extract Structured Data\r\n\r\n```python\r\nimport os\r\nfrom firecrawl import FirecrawlApp\r\n\r\napp = FirecrawlApp(api_key=os.environ.get(\"FIRECRAWL_API_KEY\"))\r\n\r\nschema = {\r\n \"type\": \"object\",\r\n \"properties\": {\r\n \"company_name\": {\"type\": \"string\"},\r\n \"product_price\": {\"type\": \"number\"},\r\n \"availability\": {\"type\": \"string\"}\r\n },\r\n \"required\": [\"company_name\", \"product_price\"]\r\n}\r\n\r\n\r\n### Installation\r\n\r\n```bash\r\nnpm install @mendable/firecrawl-js\r\npnpm add @mendable/firecrawl-js\r\n\r\n### 1. Documentation Scraping\r\n\r\n**Scenario**: Convert entire documentation site to markdown for RAG/chatbot\r\n\r\n```python\r\napp = FirecrawlApp(api_key=os.environ.get(\"FIRECRAWL_API_KEY\"))\r\n\r\ndocs = app.crawl_url(\r\n url=\"https://docs.myapi.com\",\r\n params={\r\n \"limit\": 500,\r\n \"scrapeOptions\": {\r\n \"formats\": [\"markdown\"],\r\n \"onlyMainContent\": True\r\n },\r\n \"allowedDomains\": [\"docs.myapi.com\"]\r\n }\r\n)\r\n\r\nfor page in docs.get(\"data\", []):\r\n filename = page[\"url\"].replace(\"https://\", \"\").replace(\"/\", \"_\") + \".md\"\r\n with open(f\"docs/{filename}\", \"w\") as f:\r\n f.write(page[\"markdown\"])\r\n```\r\n\r\n### 2. Product Data Extraction\r\n\r\n**Scenario**: Extract structured product data for e-commerce\r\n\r\n```typescript\r\nconst schema = z.object({\r\n title: z.string(),\r\n price: z.number(),\r\n description: z.string(),\r\n images: z.array(z.string()),\r\n in_stock: z.boolean()\r\n});\r\n\r\nconst products = await app.extract({\r\n urls: productUrls,\r\n schema: schema,\r\n systemPrompt: 'Extract all product details including price and availability'\r\n});\r\n```\r\n\r\n### 3. News Article Scraping\r\n\r\n**Scenario**: Extract clean article content without ads/navigation\r\n\r\n```python\r\narticle = app.scrape_url(\r\n url=\"https://news.com/article\",\r\n params={\r\n \"formats\": [\"markdown\"],\r\n \"onlyMainContent\": True,\r\n \"removeBase64Images\": True\r\n }\r\n)\r\n\r\n\r\n### Issue: \"Invalid API Key\"\r\n**Cause**: API key not set or incorrect\r\n**Fix**:\r\n```bash\r\necho $FIRECRAWL_API_KEY",
"name": "firecrawl-scraper",
"id": "firecrawl-scraper",
"sections": {
"Authentication": "FIRECRAWL_API_KEY=fc-your-api-key-here\r\n```\r\n\r\n---",
"API Endpoints": "### 1. `/v2/scrape` - Single Page Scraping\r\nScrapes a single webpage and returns clean, structured content.\r\n\r\n**Use Cases**:\r\n- Extract article content\r\n- Get product details\r\n- Scrape specific pages\r\n- Convert HTML to markdown\r\n\r\n**Key Options**:\r\n- `formats`: [\"markdown\", \"html\", \"screenshot\"]\r\n- `onlyMainContent`: true/false (removes nav, footer, ads)\r\n- `waitFor`: milliseconds to wait before scraping\r\n- `actions`: browser automation actions (click, scroll, etc.)\r\n\r\n### 2. `/v2/crawl` - Full Site Crawling\r\nCrawls all accessible pages from a starting URL.\r\n\r\n**Use Cases**:\r\n- Index entire documentation sites\r\n- Archive website content\r\n- Build knowledge bases\r\n- Scrape multi-page content\r\n\r\n**Key Options**:\r\n- `limit`: max pages to crawl\r\n- `maxDepth`: how many links deep to follow\r\n- `allowedDomains`: restrict to specific domains\r\n- `excludePaths`: skip certain URL patterns\r\n\r\n### 3. `/v2/map` - URL Discovery\r\nMaps all URLs on a website without scraping content.\r\n\r\n**Use Cases**:\r\n- Find sitemap\r\n- Discover all pages\r\n- Plan crawling strategy\r\n- Audit website structure\r\n\r\n### 4. `/v2/extract` - Structured Data Extraction\r\nUses AI to extract specific data fields from pages.\r\n\r\n**Use Cases**:\r\n- Extract product prices and names\r\n- Parse contact information\r\n- Build structured datasets\r\n- Custom data schemas\r\n\r\n**Key Options**:\r\n- `schema`: Zod or JSON schema defining desired structure\r\n- `systemPrompt`: guide AI extraction behavior\r\n\r\n---",
"Cloudflare Workers Integration": "### ⚠️ Important: SDK Compatibility\r\n\r\n**The Firecrawl SDK cannot run in Cloudflare Workers** due to Node.js dependencies (specifically `axios` which uses Node.js `http` module). Workers require Web Standard APIs.\r\n\r\n**✅ Use the direct REST API with `fetch` instead** (see example below).\r\n\r\n**Alternative**: Self-host with [workers-firecrawl](https://github.com/G4brym/workers-firecrawl) - a Workers-native implementation (requires Workers Paid Plan, only implements `/search` endpoint).\r\n\r\n---\r\n\r\n### Workers Example: Direct REST API\r\n\r\nThis example uses the `fetch` API to call Firecrawl directly - works perfectly in Cloudflare Workers:\r\n\r\n```typescript\r\ninterface Env {\r\n FIRECRAWL_API_KEY: string;\r\n SCRAPED_CACHE?: KVNamespace; // Optional: for caching results\r\n}\r\n\r\ninterface FirecrawlScrapeResponse {\r\n success: boolean;\r\n data: {\r\n markdown?: string;\r\n html?: string;\r\n metadata: {\r\n title?: string;\r\n description?: string;\r\n language?: string;\r\n sourceURL: string;\r\n };\r\n };\r\n}\r\n\r\nexport default {\r\n async fetch(request: Request, env: Env): Promise<Response> {\r\n if (request.method !== 'POST') {\r\n return Response.json({ error: 'Method not allowed' }, { status: 405 });\r\n }\r\n\r\n try {\r\n const { url } = await request.json<{ url: string }>();\r\n\r\n if (!url) {\r\n return Response.json({ error: 'URL is required' }, { status: 400 });\r\n }\r\n\r\n // Check cache (optional)\r\n if (env.SCRAPED_CACHE) {\r\n const cached = await env.SCRAPED_CACHE.get(url, 'json');\r\n if (cached) {\r\n return Response.json({ cached: true, data: cached });\r\n }\r\n }\r\n\r\n // Call Firecrawl API directly using fetch\r\n const response = await fetch('https://api.firecrawl.dev/v2/scrape', {\r\n method: 'POST',\r\n headers: {\r\n 'Authorization': `Bearer ${env.FIRECRAWL_API_KEY}`,\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({\r\n url: url,\r\n formats: ['markdown'],\r\n onlyMainContent: true,\r\n removeBase64Images: true\r\n })\r\n });\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text();\r\n throw new Error(`Firecrawl API error (${response.status}): ${errorText}`);\r\n }\r\n\r\n const result = await response.json<FirecrawlScrapeResponse>();\r\n\r\n // Cache for 1 hour (optional)\r\n if (env.SCRAPED_CACHE && result.success) {\r\n await env.SCRAPED_CACHE.put(\r\n url,\r\n JSON.stringify(result.data),\r\n { expirationTtl: 3600 }\r\n );\r\n }\r\n\r\n return Response.json({\r\n cached: false,\r\n data: result.data\r\n });\r\n\r\n } catch (error) {\r\n console.error('Scraping error:', error);\r\n return Response.json(\r\n { error: error instanceof Error ? error.message : 'Unknown error' },\r\n { status: 500 }\r\n );\r\n }\r\n }\r\n};\r\n```\r\n\r\n**Environment Setup**: Add `FIRECRAWL_API_KEY` in Wrangler secrets:\r\n\r\n```bash\r\nnpx wrangler secret put FIRECRAWL_API_KEY\r\n```\r\n\r\n**Optional KV Binding** (for caching - add to `wrangler.jsonc`):\r\n\r\n```jsonc\r\n{\r\n \"kv_namespaces\": [\r\n {\r\n \"binding\": \"SCRAPED_CACHE\",\r\n \"id\": \"your-kv-namespace-id\"\r\n }\r\n ]\r\n}\r\n```\r\n\r\nSee `templates/firecrawl-worker-fetch.ts` for a complete production-ready example.\r\n\r\n---",
"Advanced Features": "### Browser Actions\r\n\r\nPerform interactions before scraping:\r\n\r\n```python\r\nresult = app.scrape_url(\r\n url=\"https://example.com\",\r\n params={\r\n \"actions\": [\r\n {\"type\": \"click\", \"selector\": \"button.load-more\"},\r\n {\"type\": \"wait\", \"milliseconds\": 2000},\r\n {\"type\": \"scroll\", \"direction\": \"down\"}\r\n ]\r\n }\r\n)\r\n```\r\n\r\n### Custom Headers\r\n\r\n```python\r\nresult = app.scrape_url(\r\n url=\"https://example.com\",\r\n params={\r\n \"headers\": {\r\n \"User-Agent\": \"Custom Bot 1.0\",\r\n \"Accept-Language\": \"en-US\"\r\n }\r\n }\r\n)\r\n```\r\n\r\n### Webhooks for Long Crawls\r\n\r\nInstead of polling, receive results via webhook:\r\n\r\n```python\r\ncrawl = app.crawl_url(\r\n url=\"https://docs.example.com\",\r\n params={\r\n \"limit\": 1000,\r\n \"webhook\": \"https://your-domain.com/webhook\"\r\n }\r\n)\r\n```\r\n\r\n---",
"TypeScript/Node.js SDK Usage": "npm install firecrawl\r\n```\r\n\r\n**Latest Version**: `@mendable/firecrawl-js v4.4.1+` (or `firecrawl v4.4.1+`)\r\n\r\n### Basic Scrape\r\n\r\n```typescript\r\nimport FirecrawlApp from '@mendable/firecrawl-js';\r\n\r\n// Initialize client\r\nconst app = new FirecrawlApp({\r\n apiKey: process.env.FIRECRAWL_API_KEY\r\n});\r\n\r\n// Scrape a single page\r\nconst result = await app.scrapeUrl('https://example.com/article', {\r\n formats: ['markdown', 'html'],\r\n onlyMainContent: true\r\n});\r\n\r\n// Access markdown content\r\nconst markdown = result.markdown;\r\nconsole.log(markdown);\r\n```\r\n\r\n### Crawl Multiple Pages\r\n\r\n```typescript\r\nimport FirecrawlApp from '@mendable/firecrawl-js';\r\n\r\nconst app = new FirecrawlApp({\r\n apiKey: process.env.FIRECRAWL_API_KEY\r\n});\r\n\r\n// Start crawl\r\nconst crawlResult = await app.crawlUrl('https://docs.example.com', {\r\n limit: 100,\r\n scrapeOptions: {\r\n formats: ['markdown']\r\n }\r\n});\r\n\r\n// Process results\r\nfor (const page of crawlResult.data) {\r\n console.log(`Scraped: ${page.url}`);\r\n console.log(page.markdown);\r\n}\r\n```\r\n\r\n### Extract Structured Data with Zod\r\n\r\n```typescript\r\nimport FirecrawlApp from '@mendable/firecrawl-js';\r\nimport { z } from 'zod';\r\n\r\nconst app = new FirecrawlApp({\r\n apiKey: process.env.FIRECRAWL_API_KEY\r\n});\r\n\r\n// Define schema with Zod\r\nconst schema = z.object({\r\n company_name: z.string(),\r\n product_price: z.number(),\r\n availability: z.string()\r\n});\r\n\r\n// Extract data\r\nconst result = await app.extract({\r\n urls: ['https://example.com/product'],\r\n schema: schema,\r\n systemPrompt: 'Extract product information from the page'\r\n});\r\n\r\nconsole.log(result);\r\n```\r\n\r\n---",
"Package Versions": "| Package | Version | Last Checked |\r\n|---------|---------|--------------|\r\n| firecrawl-py | 4.5.0+ | 2025-10-20 |\r\n| @mendable/firecrawl-js (or firecrawl) | 4.4.1+ | 2025-10-24 |\r\n| API Version | v2 | Current |\r\n\r\n**Note**: The Node.js SDK requires Node.js >=22.0.0 and cannot run in Cloudflare Workers. Use direct REST API calls in Workers (see Cloudflare Workers Integration section).\r\n\r\n---",
"Next Steps After Using This Skill": "1. **Store scraped data**: Use Cloudflare D1, R2, or KV to persist results\r\n2. **Build RAG system**: Combine with Vectorize for semantic search\r\n3. **Add scheduling**: Use Cloudflare Queues for recurring scrapes\r\n4. **Process content**: Use Workers AI to analyze scraped data\r\n\r\n---\r\n\r\n**Token Savings**: ~60% vs manual integration\r\n**Error Prevention**: API authentication, rate limiting, format handling\r\n**Production Ready**: ✅",
"Error Handling": "### Python\r\n\r\n```python\r\nfrom firecrawl import FirecrawlApp\r\nfrom firecrawl.exceptions import FirecrawlException\r\n\r\napp = FirecrawlApp(api_key=os.environ.get(\"FIRECRAWL_API_KEY\"))\r\n\r\ntry:\r\n result = app.scrape_url(\"https://example.com\")\r\nexcept FirecrawlException as e:\r\n print(f\"Firecrawl error: {e}\")\r\nexcept Exception as e:\r\n print(f\"Unexpected error: {e}\")\r\n```\r\n\r\n### TypeScript\r\n\r\n```typescript\r\nimport FirecrawlApp from '@mendable/firecrawl-js';\r\n\r\nconst app = new FirecrawlApp({\r\n apiKey: process.env.FIRECRAWL_API_KEY\r\n});\r\n\r\ntry {\r\n const result = await app.scrapeUrl('https://example.com');\r\n} catch (error) {\r\n if (error.response) {\r\n // API error\r\n console.error('API Error:', error.response.data);\r\n } else {\r\n // Network or other error\r\n console.error('Error:', error.message);\r\n }\r\n}\r\n```\r\n\r\n---",
"When to Use This Skill": "✅ **Use Firecrawl when:**\r\n- Scraping modern websites with JavaScript\r\n- Need clean markdown output for LLMs\r\n- Building RAG systems from web content\r\n- Extracting structured data at scale\r\n- Dealing with bot protection\r\n- Need reliable, production-ready scraping\r\n\r\n❌ **Don't use Firecrawl when:**\r\n- Scraping simple static HTML (use cheerio/beautifulsoup)\r\n- Have existing Puppeteer/Playwright setup working well\r\n- Working with APIs (use direct API calls instead)\r\n- Budget constraints (free tier has limits)\r\n\r\n---",
"Common Use Cases": "content = article.get(\"markdown\")\r\n```\r\n\r\n---",
"Common Issues & Solutions": "```\r\n\r\n### Issue: \"Rate limit exceeded\"\r\n**Cause**: Exceeded monthly credits\r\n**Fix**:\r\n- Check usage in dashboard\r\n- Upgrade plan or wait for reset\r\n- Use `onlyMainContent: true` to reduce credits\r\n\r\n### Issue: \"Timeout error\"\r\n**Cause**: Page takes too long to load\r\n**Fix**:\r\n```python\r\nresult = app.scrape_url(url, params={\"waitFor\": 10000}) # Wait 10s\r\n```\r\n\r\n### Issue: \"Content is empty\"\r\n**Cause**: Content loaded via JavaScript after initial render\r\n**Fix**:\r\n```python\r\nresult = app.scrape_url(url, params={\r\n \"waitFor\": 5000,\r\n \"actions\": [{\"type\": \"wait\", \"milliseconds\": 3000}]\r\n})\r\n```\r\n\r\n---",
"Official Documentation": "- **Docs**: https://docs.firecrawl.dev\r\n- **Python SDK**: https://docs.firecrawl.dev/sdks/python\r\n- **Node.js SDK**: https://docs.firecrawl.dev/sdks/node\r\n- **API Reference**: https://docs.firecrawl.dev/api-reference\r\n- **GitHub**: https://github.com/mendableai/firecrawl\r\n- **Dashboard**: https://www.firecrawl.dev/app\r\n\r\n---",
"Rate Limits & Best Practices": "### Rate Limits\r\n- **Free tier**: 500 credits/month\r\n- **Paid tiers**: Higher limits based on plan\r\n- Credits consumed vary by endpoint and options\r\n\r\n### Best Practices\r\n\r\n1. **Use `onlyMainContent: true`** to reduce credits and get cleaner data\r\n2. **Set reasonable limits** on crawls to avoid excessive costs\r\n3. **Handle retries** with exponential backoff for transient errors\r\n4. **Cache results** locally to avoid re-scraping same content\r\n5. **Use `map` endpoint first** to plan crawling strategy\r\n6. **Batch extract calls** when processing multiple URLs\r\n7. **Monitor credit usage** in dashboard\r\n\r\n---",
"What is Firecrawl?": "Firecrawl is a **Web Data API for AI** that turns entire websites into LLM-ready markdown or structured data. It handles:\r\n\r\n- **JavaScript rendering** - Executes client-side JavaScript to capture dynamic content\r\n- **Anti-bot bypass** - Gets past CAPTCHA and bot detection systems\r\n- **Format conversion** - Outputs as markdown, JSON, or structured data\r\n- **Screenshot capture** - Saves visual representations of pages\r\n- **Browser automation** - Full headless browser capabilities\r\n\r\n---",
"Python SDK Usage": "result = app.extract(\r\n urls=[\"https://example.com/product\"],\r\n params={\r\n \"schema\": schema,\r\n \"systemPrompt\": \"Extract product information from the page\"\r\n }\r\n)\r\n\r\nprint(result)\r\n```\r\n\r\n---"
}
}---
name: firecrawl-scraper
description: |
Complete knowledge domain for Firecrawl v2 API - web scraping and crawling that converts websites into LLM-ready markdown or structured data.
Use when: scraping websites, crawling entire sites, extracting web content, converting HTML to markdown, building web scrapers, handling dynamic JavaScript content, bypassing anti-bot protection, extracting structured data from web pages, or when encountering "content not loading", "JavaScript rendering issues", or "blocked by bot detection".
Keywords: firecrawl, firecrawl api, web scraping, web crawler, scrape website, crawl website, extract content, html to markdown, site crawler, content extraction, web automation, firecrawl-py, firecrawl-js, llm ready data, structured data extraction, bot bypass, javascript rendering, scraping api, crawling api, map urls, batch scraping
license: MIT
---
# Firecrawl Web Scraper Skill
**Status**: Production Ready ✅
**Last Updated**: 2025-10-24
**Official Docs**: https://docs.firecrawl.dev
**API Version**: v2
---
## What is Firecrawl?
Firecrawl is a **Web Data API for AI** that turns entire websites into LLM-ready markdown or structured data. It handles:
- **JavaScript rendering** - Executes client-side JavaScript to capture dynamic content
- **Anti-bot bypass** - Gets past CAPTCHA and bot detection systems
- **Format conversion** - Outputs as markdown, JSON, or structured data
- **Screenshot capture** - Saves visual representations of pages
- **Browser automation** - Full headless browser capabilities
---
## API Endpoints
### 1. `/v2/scrape` - Single Page Scraping
Scrapes a single webpage and returns clean, structured content.
**Use Cases**:
- Extract article content
- Get product details
- Scrape specific pages
- Convert HTML to markdown
**Key Options**:
- `formats`: ["markdown", "html", "screenshot"]
- `onlyMainContent`: true/false (removes nav, footer, ads)
- `waitFor`: milliseconds to wait before scraping
- `actions`: browser automation actions (click, scroll, etc.)
### 2. `/v2/crawl` - Full Site Crawling
Crawls all accessible pages from a starting URL.
**Use Cases**:
- Index entire documentation sites
- Archive website content
- Build knowledge bases
- Scrape multi-page content
**Key Options**:
- `limit`: max pages to crawl
- `maxDepth`: how many links deep to follow
- `allowedDomains`: restrict to specific domains
- `excludePaths`: skip certain URL patterns
### 3. `/v2/map` - URL Discovery
Maps all URLs on a website without scraping content.
**Use Cases**:
- Find sitemap
- Discover all pages
- Plan crawling strategy
- Audit website structure
### 4. `/v2/extract` - Structured Data Extraction
Uses AI to extract specific data fields from pages.
**Use Cases**:
- Extract product prices and names
- Parse contact information
- Build structured datasets
- Custom data schemas
**Key Options**:
- `schema`: Zod or JSON schema defining desired structure
- `systemPrompt`: guide AI extraction behavior
---
## Authentication
Firecrawl requires an API key for all requests.
### Get API Key
1. Sign up at https://www.firecrawl.dev
2. Go to dashboard → API Keys
3. Copy your API key (starts with `fc-`)
### Store Securely
**NEVER hardcode API keys in code!**
```bash
# .env file
FIRECRAWL_API_KEY=fc-your-api-key-here
```
```bash
# .env.local (for local development)
FIRECRAWL_API_KEY=fc-your-api-key-here
```
---
## Python SDK Usage
### Installation
```bash
pip install firecrawl-py
```
**Latest Version**: `firecrawl-py v4.5.0+`
### Basic Scrape
```python
import os
from firecrawl import FirecrawlApp
# Initialize client
app = FirecrawlApp(api_key=os.environ.get("FIRECRAWL_API_KEY"))
# Scrape a single page
result = app.scrape_url(
url="https://example.com/article",
params={
"formats": ["markdown", "html"],
"onlyMainContent": True
}
)
# Access markdown content
markdown = result.get("markdown")
print(markdown)
```
### Crawl Multiple Pages
```python
import os
from firecrawl import FirecrawlApp
app = FirecrawlApp(api_key=os.environ.get("FIRECRAWL_API_KEY"))
# Start crawl
crawl_result = app.crawl_url(
url="https://docs.example.com",
params={
"limit": 100,
"scrapeOptions": {
"formats": ["markdown"]
}
},
poll_interval=5 # Check status every 5 seconds
)
# Process results
for page in crawl_result.get("data", []):
url = page.get("url")
markdown = page.get("markdown")
print(f"Scraped: {url}")
```
### Extract Structured Data
```python
import os
from firecrawl import FirecrawlApp
app = FirecrawlApp(api_key=os.environ.get("FIRECRAWL_API_KEY"))
# Define schema
schema = {
"type": "object",
"properties": {
"company_name": {"type": "string"},
"product_price": {"type": "number"},
"availability": {"type": "string"}
},
"required": ["company_name", "product_price"]
}
# Extract data
result = app.extract(
urls=["https://example.com/product"],
params={
"schema": schema,
"systemPrompt": "Extract product information from the page"
}
)
print(result)
```
---
## TypeScript/Node.js SDK Usage
### Installation
```bash
npm install @mendable/firecrawl-js
# or
pnpm add @mendable/firecrawl-js
# or use the unscoped package:
npm install firecrawl
```
**Latest Version**: `@mendable/firecrawl-js v4.4.1+` (or `firecrawl v4.4.1+`)
### Basic Scrape
```typescript
import FirecrawlApp from '@mendable/firecrawl-js';
// Initialize client
const app = new FirecrawlApp({
apiKey: process.env.FIRECRAWL_API_KEY
});
// Scrape a single page
const result = await app.scrapeUrl('https://example.com/article', {
formats: ['markdown', 'html'],
onlyMainContent: true
});
// Access markdown content
const markdown = result.markdown;
console.log(markdown);
```
### Crawl Multiple Pages
```typescript
import FirecrawlApp from '@mendable/firecrawl-js';
const app = new FirecrawlApp({
apiKey: process.env.FIRECRAWL_API_KEY
});
// Start crawl
const crawlResult = await app.crawlUrl('https://docs.example.com', {
limit: 100,
scrapeOptions: {
formats: ['markdown']
}
});
// Process results
for (const page of crawlResult.data) {
console.log(`Scraped: ${page.url}`);
console.log(page.markdown);
}
```
### Extract Structured Data with Zod
```typescript
import FirecrawlApp from '@mendable/firecrawl-js';
import { z } from 'zod';
const app = new FirecrawlApp({
apiKey: process.env.FIRECRAWL_API_KEY
});
// Define schema with Zod
const schema = z.object({
company_name: z.string(),
product_price: z.number(),
availability: z.string()
});
// Extract data
const result = await app.extract({
urls: ['https://example.com/product'],
schema: schema,
systemPrompt: 'Extract product information from the page'
});
console.log(result);
```
---
## Common Use Cases
### 1. Documentation Scraping
**Scenario**: Convert entire documentation site to markdown for RAG/chatbot
```python
app = FirecrawlApp(api_key=os.environ.get("FIRECRAWL_API_KEY"))
docs = app.crawl_url(
url="https://docs.myapi.com",
params={
"limit": 500,
"scrapeOptions": {
"formats": ["markdown"],
"onlyMainContent": True
},
"allowedDomains": ["docs.myapi.com"]
}
)
# Save to files
for page in docs.get("data", []):
filename = page["url"].replace("https://", "").replace("/", "_") + ".md"
with open(f"docs/{filename}", "w") as f:
f.write(page["markdown"])
```
### 2. Product Data Extraction
**Scenario**: Extract structured product data for e-commerce
```typescript
const schema = z.object({
title: z.string(),
price: z.number(),
description: z.string(),
images: z.array(z.string()),
in_stock: z.boolean()
});
const products = await app.extract({
urls: productUrls,
schema: schema,
systemPrompt: 'Extract all product details including price and availability'
});
```
### 3. News Article Scraping
**Scenario**: Extract clean article content without ads/navigation
```python
article = app.scrape_url(
url="https://news.com/article",
params={
"formats": ["markdown"],
"onlyMainContent": True,
"removeBase64Images": True
}
)
# Get clean markdown
content = article.get("markdown")
```
---
## Error Handling
### Python
```python
from firecrawl import FirecrawlApp
from firecrawl.exceptions import FirecrawlException
app = FirecrawlApp(api_key=os.environ.get("FIRECRAWL_API_KEY"))
try:
result = app.scrape_url("https://example.com")
except FirecrawlException as e:
print(f"Firecrawl error: {e}")
except Exception as e:
print(f"Unexpected error: {e}")
```
### TypeScript
```typescript
import FirecrawlApp from '@mendable/firecrawl-js';
const app = new FirecrawlApp({
apiKey: process.env.FIRECRAWL_API_KEY
});
try {
const result = await app.scrapeUrl('https://example.com');
} catch (error) {
if (error.response) {
// API error
console.error('API Error:', error.response.data);
} else {
// Network or other error
console.error('Error:', error.message);
}
}
```
---
## Rate Limits & Best Practices
### Rate Limits
- **Free tier**: 500 credits/month
- **Paid tiers**: Higher limits based on plan
- Credits consumed vary by endpoint and options
### Best Practices
1. **Use `onlyMainContent: true`** to reduce credits and get cleaner data
2. **Set reasonable limits** on crawls to avoid excessive costs
3. **Handle retries** with exponential backoff for transient errors
4. **Cache results** locally to avoid re-scraping same content
5. **Use `map` endpoint first** to plan crawling strategy
6. **Batch extract calls** when processing multiple URLs
7. **Monitor credit usage** in dashboard
---
## Cloudflare Workers Integration
### ⚠️ Important: SDK Compatibility
**The Firecrawl SDK cannot run in Cloudflare Workers** due to Node.js dependencies (specifically `axios` which uses Node.js `http` module). Workers require Web Standard APIs.
**✅ Use the direct REST API with `fetch` instead** (see example below).
**Alternative**: Self-host with [workers-firecrawl](https://github.com/G4brym/workers-firecrawl) - a Workers-native implementation (requires Workers Paid Plan, only implements `/search` endpoint).
---
### Workers Example: Direct REST API
This example uses the `fetch` API to call Firecrawl directly - works perfectly in Cloudflare Workers:
```typescript
interface Env {
FIRECRAWL_API_KEY: string;
SCRAPED_CACHE?: KVNamespace; // Optional: for caching results
}
interface FirecrawlScrapeResponse {
success: boolean;
data: {
markdown?: string;
html?: string;
metadata: {
title?: string;
description?: string;
language?: string;
sourceURL: string;
};
};
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
if (request.method !== 'POST') {
return Response.json({ error: 'Method not allowed' }, { status: 405 });
}
try {
const { url } = await request.json<{ url: string }>();
if (!url) {
return Response.json({ error: 'URL is required' }, { status: 400 });
}
// Check cache (optional)
if (env.SCRAPED_CACHE) {
const cached = await env.SCRAPED_CACHE.get(url, 'json');
if (cached) {
return Response.json({ cached: true, data: cached });
}
}
// Call Firecrawl API directly using fetch
const response = await fetch('https://api.firecrawl.dev/v2/scrape', {
method: 'POST',
headers: {
'Authorization': `Bearer ${env.FIRECRAWL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
url: url,
formats: ['markdown'],
onlyMainContent: true,
removeBase64Images: true
})
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`Firecrawl API error (${response.status}): ${errorText}`);
}
const result = await response.json<FirecrawlScrapeResponse>();
// Cache for 1 hour (optional)
if (env.SCRAPED_CACHE && result.success) {
await env.SCRAPED_CACHE.put(
url,
JSON.stringify(result.data),
{ expirationTtl: 3600 }
);
}
return Response.json({
cached: false,
data: result.data
});
} catch (error) {
console.error('Scraping error:', error);
return Response.json(
{ error: error instanceof Error ? error.message : 'Unknown error' },
{ status: 500 }
);
}
}
};
```
**Environment Setup**: Add `FIRECRAWL_API_KEY` in Wrangler secrets:
```bash
npx wrangler secret put FIRECRAWL_API_KEY
```
**Optional KV Binding** (for caching - add to `wrangler.jsonc`):
```jsonc
{
"kv_namespaces": [
{
"binding": "SCRAPED_CACHE",
"id": "your-kv-namespace-id"
}
]
}
```
See `templates/firecrawl-worker-fetch.ts` for a complete production-ready example.
---
## When to Use This Skill
✅ **Use Firecrawl when:**
- Scraping modern websites with JavaScript
- Need clean markdown output for LLMs
- Building RAG systems from web content
- Extracting structured data at scale
- Dealing with bot protection
- Need reliable, production-ready scraping
❌ **Don't use Firecrawl when:**
- Scraping simple static HTML (use cheerio/beautifulsoup)
- Have existing Puppeteer/Playwright setup working well
- Working with APIs (use direct API calls instead)
- Budget constraints (free tier has limits)
---
## Common Issues & Solutions
### Issue: "Invalid API Key"
**Cause**: API key not set or incorrect
**Fix**:
```bash
# Check env variable is set
echo $FIRECRAWL_API_KEY
# Verify key format (should start with fc-)
```
### Issue: "Rate limit exceeded"
**Cause**: Exceeded monthly credits
**Fix**:
- Check usage in dashboard
- Upgrade plan or wait for reset
- Use `onlyMainContent: true` to reduce credits
### Issue: "Timeout error"
**Cause**: Page takes too long to load
**Fix**:
```python
result = app.scrape_url(url, params={"waitFor": 10000}) # Wait 10s
```
### Issue: "Content is empty"
**Cause**: Content loaded via JavaScript after initial render
**Fix**:
```python
result = app.scrape_url(url, params={
"waitFor": 5000,
"actions": [{"type": "wait", "milliseconds": 3000}]
})
```
---
## Advanced Features
### Browser Actions
Perform interactions before scraping:
```python
result = app.scrape_url(
url="https://example.com",
params={
"actions": [
{"type": "click", "selector": "button.load-more"},
{"type": "wait", "milliseconds": 2000},
{"type": "scroll", "direction": "down"}
]
}
)
```
### Custom Headers
```python
result = app.scrape_url(
url="https://example.com",
params={
"headers": {
"User-Agent": "Custom Bot 1.0",
"Accept-Language": "en-US"
}
}
)
```
### Webhooks for Long Crawls
Instead of polling, receive results via webhook:
```python
crawl = app.crawl_url(
url="https://docs.example.com",
params={
"limit": 1000,
"webhook": "https://your-domain.com/webhook"
}
)
```
---
## Package Versions
| Package | Version | Last Checked |
|---------|---------|--------------|
| firecrawl-py | 4.5.0+ | 2025-10-20 |
| @mendable/firecrawl-js (or firecrawl) | 4.4.1+ | 2025-10-24 |
| API Version | v2 | Current |
**Note**: The Node.js SDK requires Node.js >=22.0.0 and cannot run in Cloudflare Workers. Use direct REST API calls in Workers (see Cloudflare Workers Integration section).
---
## Official Documentation
- **Docs**: https://docs.firecrawl.dev
- **Python SDK**: https://docs.firecrawl.dev/sdks/python
- **Node.js SDK**: https://docs.firecrawl.dev/sdks/node
- **API Reference**: https://docs.firecrawl.dev/api-reference
- **GitHub**: https://github.com/mendableai/firecrawl
- **Dashboard**: https://www.firecrawl.dev/app
---
## Next Steps After Using This Skill
1. **Store scraped data**: Use Cloudflare D1, R2, or KV to persist results
2. **Build RAG system**: Combine with Vectorize for semantic search
3. **Add scheduling**: Use Cloudflare Queues for recurring scrapes
4. **Process content**: Use Workers AI to analyze scraped data
---
**Token Savings**: ~60% vs manual integration
**Error Prevention**: API authentication, rate limiting, format handling
**Production Ready**: ✅