firecrawl-performance-tuning
Provides strategies to improve Firecrawl scraping speed and reduce credit usage through batching and optimal format selection.
Install
mkdir -p .claude/skills/firecrawl-performance-tuning && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/3378" && unzip -o skill.zip -d .claude/skills/firecrawl-performance-tuning && rm skill.zipInstalls to .claude/skills/firecrawl-performance-tuning
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Optimize Firecrawl scraping performance with caching, batch scraping,Key capabilities
- →Minimize data formats requested for faster scrapes
- →Tune `waitFor` parameters for dynamic JavaScript-heavy pages
- →Implement caching mechanisms for scraped content
- →Utilize batch scraping for multiple URLs
- →Map URLs before crawling to save credits
How it works
The skill provides strategies to optimize Firecrawl API performance by selecting efficient data formats, tuning wait times for dynamic content, caching results, and using batch processing for multiple URLs.
Inputs & outputs
When to use firecrawl-performance-tuning
- →Benchmark scraping operation latency
- →Optimize data format requests
- →Implement batch scraping pipelines
- →Tune scraping parameters for high-throughput
About this skill
Firecrawl Performance Tuning
Overview
Optimize Firecrawl API performance by choosing efficient scraping modes, caching results, using batch endpoints, and minimizing unnecessary rendering. Key levers: format selection (markdown vs HTML vs screenshot), waitFor tuning, onlyMainContent, and batch vs individual scraping.
Latency Benchmarks
| Operation | Typical | With JS Wait | With Screenshot |
|---|---|---|---|
| scrapeUrl (markdown) | 2-5s | 5-10s | 8-15s |
| scrapeUrl (extract) | 3-8s | 8-15s | N/A |
| crawlUrl (10 pages) | 20-40s | 40-80s | N/A |
| mapUrl | 1-3s | N/A | N/A |
| batchScrapeUrls (10) | 10-20s | 20-40s | N/A |
Instructions
Step 1: Minimize Formats (Biggest Win)
import FirecrawlApp from "@mendable/firecrawl-js";
const firecrawl = new FirecrawlApp({
apiKey: process.env.FIRECRAWL_API_KEY!,
});
// SLOW: requesting everything
const slow = await firecrawl.scrapeUrl(url, {
formats: ["markdown", "html", "links", "screenshot"],
// screenshot + full HTML = 3-5x slower
});
// FAST: request only what you need
const fast = await firecrawl.scrapeUrl(url, {
formats: ["markdown"], // markdown only = fastest
onlyMainContent: true, // skip nav/footer/sidebar
});
Step 2: Tune waitFor for JS-Heavy Pages
// Default: no JS wait (fastest, works for static sites)
const staticResult = await firecrawl.scrapeUrl("https://docs.example.com", {
formats: ["markdown"],
// No waitFor needed — content is in initial HTML
});
// SPA/dynamic pages: add minimal wait
const spaResult = await firecrawl.scrapeUrl("https://app.example.com", {
formats: ["markdown"],
waitFor: 3000, // 3s — enough for most SPAs
onlyMainContent: true,
});
// Heavy interactive page: use actions instead of long wait
const heavyResult = await firecrawl.scrapeUrl("https://dashboard.example.com", {
formats: ["markdown"],
actions: [
{ type: "wait", selector: ".data-table" }, // wait for specific element
{ type: "scroll", direction: "down" }, // trigger lazy loading
],
});
Step 3: Cache Scraped Content
import { LRUCache } from "lru-cache";
import { createHash } from "crypto";
const scrapeCache = new LRUCache<string, any>({
max: 500, // max 500 cached pages
ttl: 3600000, // 1 hour TTL
});
async function cachedScrape(url: string) {
const key = createHash("md5").update(url).digest("hex");
const cached = scrapeCache.get(key);
if (cached) {
console.log(`Cache hit: ${url}`);
return cached;
}
const result = await firecrawl.scrapeUrl(url, {
formats: ["markdown"],
onlyMainContent: true,
});
if (result.success) {
scrapeCache.set(key, result);
}
return result;
}
// Typical savings: 50-80% credit reduction for repeated scrapes
Step 4: Use Batch Scrape for Multiple URLs
// SLOW: sequential individual scrapes
const urls = ["https://a.com", "https://b.com", "https://c.com"];
for (const url of urls) {
await firecrawl.scrapeUrl(url, { formats: ["markdown"] }); // 3 API calls
}
// FAST: single batch scrape call
const batchResult = await firecrawl.batchScrapeUrls(urls, {
formats: ["markdown"],
onlyMainContent: true,
});
// 1 API call, internally parallelized
Step 5: Map Before Crawl (Save Credits)
// EXPENSIVE: crawl everything, filter later
await firecrawl.crawlUrl("https://docs.example.com", { limit: 1000 });
// CHEAPER: map first (1 credit), then scrape only what you need
const map = await firecrawl.mapUrl("https://docs.example.com");
const apiDocs = (map.links || []).filter(url =>
url.includes("/api/") || url.includes("/reference/")
);
console.log(`Map: ${map.links?.length} total, ${apiDocs.length} relevant`);
// Batch scrape only relevant URLs
const result = await firecrawl.batchScrapeUrls(apiDocs.slice(0, 50), {
formats: ["markdown"],
});
Step 6: Measure Scrape Performance
async function timedScrape(url: string) {
const start = Date.now();
const result = await firecrawl.scrapeUrl(url, { formats: ["markdown"] });
const duration = Date.now() - start;
console.log({
url,
durationMs: duration,
contentLength: result.markdown?.length || 0,
success: result.success,
charsPerSecond: Math.round((result.markdown?.length || 0) / (duration / 1000)),
});
return result;
}
Error Handling
| Issue | Cause | Solution |
|---|---|---|
| Scrape > 10s | Screenshot or full HTML requested | Use formats: ["markdown"] only |
| Empty content | waitFor too short for SPA | Increase or use actions with selector |
| High credit burn | Scraping same URLs repeatedly | Implement URL-based caching |
| Batch timeout | Too many URLs in one batch | Split into chunks of 50 |
| Cache stale data | TTL too long | Reduce TTL or add cache invalidation |
Examples
Performance Comparison Script
const url = "https://docs.firecrawl.dev";
// Compare different format configurations
for (const formats of [["markdown"], ["markdown", "html"], ["markdown", "html", "screenshot"]]) {
const start = Date.now();
await firecrawl.scrapeUrl(url, { formats: formats as any, onlyMainContent: true });
console.log(`${formats.join(",")}: ${Date.now() - start}ms`);
}
Resources
Next Steps
For cost optimization, see firecrawl-cost-tuning.
When not to use it
- →When requesting screenshots or full HTML formats
- →When `waitFor` is too short for Single Page Applications
- →When caching stale data due to long TTL
Limitations
- →Scrapes may exceed 10 seconds if full HTML or screenshots are requested
- →Empty content can result if `waitFor` is too short for SPAs
- →High credit consumption can occur from repeatedly scraping the same URLs
How it compares
This skill focuses on optimizing Firecrawl API calls for speed and cost, offering specific techniques like format minimization and batching, which is more efficient than making unoptimized individual requests.
Compared to similar skills
firecrawl-performance-tuning side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| firecrawl-performance-tuning (this skill) | 1 | 25d | Review | Intermediate |
| deepgram-performance-tuning | 3 | 25d | Review | Intermediate |
| graphql | 6 | 6mo | No flags | Advanced |
| guidewire-sdk-patterns | 2 | 25d | Review | Advanced |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by jeremylongshore
View all by jeremylongshore →You might also like
deepgram-performance-tuning
jeremylongshore
Optimize Deepgram API performance for faster transcription and lower latency. Use when improving transcription speed, reducing latency, or optimizing audio processing pipelines. Trigger with phrases like "deepgram performance", "speed up deepgram", "optimize transcription", "deepgram latency", "deepgram faster".
graphql
davila7
GraphQL gives clients exactly the data they need - no more, no less. One endpoint, typed schema, introspection. But the flexibility that makes it powerful also makes it dangerous. Without proper controls, clients can craft queries that bring down your server. This skill covers schema design, resolvers, DataLoader for N+1 prevention, federation for microservices, and client integration with Apollo/urql. Key insight: GraphQL is a contract. The schema is the API documentation. Design it carefully.
guidewire-sdk-patterns
jeremylongshore
Master Guidewire SDK patterns including Digital SDK, REST API Client, and Gosu best practices. Use when implementing integrations, building frontends with Jutro, or writing server-side Gosu code. Trigger with phrases like "guidewire sdk", "digital sdk", "jutro sdk", "guidewire patterns", "gosu best practices", "rest api client".
groq-performance-tuning
jeremylongshore
Optimize Groq API performance with caching, batching, and connection pooling. Use when experiencing slow API responses, implementing caching strategies, or optimizing request throughput for Groq integrations. Trigger with phrases like "groq performance", "optimize groq", "groq latency", "groq caching", "groq slow", "groq batch".
openrouter-streaming-setup
jeremylongshore
Implement streaming responses with OpenRouter. Use when building real-time chat interfaces or reducing time-to-first-token. Trigger with phrases like 'openrouter streaming', 'openrouter sse', 'stream response', 'real-time openrouter'.
perplexity-multi-env-setup
jeremylongshore
Configure Perplexity across development, staging, and production environments. Use when setting up multi-environment deployments, configuring per-environment secrets, or implementing environment-specific Perplexity configurations. Trigger with phrases like "perplexity environments", "perplexity staging", "perplexity dev prod", "perplexity environment setup", "perplexity config by env".