supabase
Handles the full Supabase workflow from schema changes to deployment, with built-in security guardrails that catch common traps like RLS...
firecrawl-rate-limits
Implement Firecrawl rate limiting, backoff, and request queuing patterns.
Full skill instructions
Firecrawl enforces rate limits per API key measured in requests per minute and concurrent connections. When exceeded, the API returns 429 Too Many Requests with a Retry-After header. This skill covers backoff strategies, request queuing, and proactive throttling.
| Plan | Scrape RPM | Crawl Concurrency | Credits/Month |
|---|---|---|---|
| Free | 10 | 2 | 500 |
| Hobby | 20 | 3 | 3,000 |
| Standard | 50 | 5 | 50,000 |
| Growth | 100 | 10 | 500,000 |
| Scale | 500+ | 50+ | Custom |
Concurrent crawl jobs count against concurrency limits. If the queue is full, new jobs are rejected with 429.
import FirecrawlApp from "@mendable/firecrawl-js";
const firecrawl = new FirecrawlApp({
apiKey: process.env.FIRECRAWL_API_KEY!,
});
async function withBackoff<T>(
operation: () => Promise<T>,
config = { maxRetries: 5, baseDelayMs: 1000, maxDelayMs: 32000 }
): Promise<T> {
for (let attempt = 0; attempt <= config.maxRetries; attempt++) {
try {
return await operation();
} catch (error: any) {
if (attempt === config.maxRetries) throw error;
const status = error.statusCode || error.status;
// Only retry on 429 (rate limit) and 5xx (server error)
if (status && status !== 429 && status < 500) throw error;
// Exponential delay with random jitter to prevent thundering herd
const exponentialDelay = config.baseDelayMs * Math.pow(2, attempt);
const jitter = Math.random() * 500;
const delay = Math.min(exponentialDelay + jitter, config.maxDelayMs);
console.warn(`Rate limited (${status}). Retry ${attempt + 1}/${config.maxRetries} in ${delay.toFixed(0)}ms`);
await new Promise(r => setTimeout(r, delay));
}
}
throw new Error("Unreachable");
}
// Usage
const result = await withBackoff(() =>
firecrawl.scrapeUrl("https://example.com", { formats: ["markdown"] })
);
import PQueue from "p-queue";
// Limit to 5 concurrent requests, max 10 per second
const scrapeQueue = new PQueue({
concurrency: 5,
interval: 1000,
intervalCap: 10,
});
async function queuedScrape(url: string) {
return scrapeQueue.add(() =>
withBackoff(() =>
firecrawl.scrapeUrl(url, { formats: ["markdown"] })
)
);
}
// Scrape many URLs respecting rate limits
const urls = ["https://a.com", "https://b.com", "https://c.com"];
const results = await Promise.all(urls.map(url => queuedScrape(url)));
console.log(`Queue: ${scrapeQueue.pending} pending, ${scrapeQueue.size} queued`);
class RateLimitTracker {
private requestTimes: number[] = [];
private windowMs: number;
private maxRequests: number;
constructor(maxRequests = 50, windowMs = 60000) {
this.maxRequests = maxRequests;
this.windowMs = windowMs;
}
async waitIfNeeded(): Promise<void> {
const now = Date.now();
this.requestTimes = this.requestTimes.filter(t => now - t < this.windowMs);
if (this.requestTimes.length >= this.maxRequests) {
const oldestInWindow = this.requestTimes[0];
const waitMs = this.windowMs - (now - oldestInWindow) + 100;
console.log(`Proactive throttle: waiting ${waitMs}ms to stay under ${this.maxRequests} RPM`);
await new Promise(r => setTimeout(r, waitMs));
}
this.requestTimes.push(Date.now());
}
}
const throttle = new RateLimitTracker(50, 60000); // 50 requests per minute
async function throttledScrape(url: string) {
await throttle.waitIfNeeded();
return firecrawl.scrapeUrl(url, { formats: ["markdown"] });
}
// batchScrapeUrls is more efficient than individual scrapes
// It handles internal rate limiting and is cheaper on credits
const urls = [
"https://example.com/page1",
"https://example.com/page2",
"https://example.com/page3",
];
// Single API call instead of 3 separate scrapes
const batchResult = await firecrawl.batchScrapeUrls(urls, {
formats: ["markdown"],
});
console.log(`Batch scraped ${batchResult.data?.length} pages`);
| Header | Description | Action |
|---|---|---|
Retry-After | Seconds to wait | Honor this exact value |
X-RateLimit-Limit | Max requests per window | Use for proactive throttling |
X-RateLimit-Remaining | Remaining in window | Slow down when < 5 |
X-RateLimit-Reset | Reset timestamp | Wait until this time |
class RateLimitMonitor {
private remaining = Infinity;
private resetAt = new Date();
update(status: number, headers: Record<string, string>) {
if (headers["x-ratelimit-remaining"]) {
this.remaining = parseInt(headers["x-ratelimit-remaining"]);
}
if (headers["x-ratelimit-reset"]) {
this.resetAt = new Date(parseInt(headers["x-ratelimit-reset"]) * 1000);
}
if (this.remaining < 5) {
console.warn(`Low rate limit: ${this.remaining} remaining, resets at ${this.resetAt.toISOString()}`);
}
}
}
For security configuration, see firecrawl-security-basics.
Handles the full Supabase workflow from schema changes to deployment, with built-in security guardrails that catch common traps like RLS...
Comprehensive guides and best practices for Neon Serverless Postgres, covering setup, connection methods, authentication, and platform APIs.
Guide for setting up and using Firebase Authentication. Use this skill when the user's app requires user sign-in, user management, or secure data access using auth rules.
A skill to evaluate how secure Firestore security rules are. Use this when Firestore security rules are updated to ensure that the generated rules are extremely secure and robust.
Official skill for integrating Firebase AI Logic (Gemini API) into web applications. Covers setup, multimodal inference, structured output, and security.
Complete Better Auth server and client setup with database adapters, session management, plugins, and security configuration.
Deploy and manage projects on Vercel using token-based authentication. Use when working with Vercel CLI using access tokens rather than interactive login — e.g. "deploy to vercel", "set up vercel", "add environment variables to vercel".
Complete Cloudflare platform integration with decision trees for compute, storage, AI, networking, security, and infrastructure-as-code.
Run Azure compliance and security audits with azqr plus Key Vault expiration checks. Covers best-practice assessment, resource review, policy/compliance validation, and security posture checks. WHEN: compliance scan, security audit, BEFORE running azqr (compliance cli tool), Azure best practices, Key Vault expiration check, expired certificates, expiring secrets, orphaned resources, compliance assessment.
Send, read, and manage Gmail messages, drafts, labels, and account settings.
Comprehensive website auditing across 230+ rules in 21 categories including SEO, performance, security, and accessibility.
Shared authentication, CLI syntax, and output formatting patterns for gws Google Workspace commands.
Discover your celebrity doppelgänger with StarByFace!
GeoSpy: Pricing, Features, FAQs, and Alternatives for AI Teams
Detect AI-generated voices to protect against audio fraud.
Ensure Your Content's Originality with AI Plagiarism Checker
Upscale images by 400% without quality loss
Protect your social media from copyright disputes
Accurately Detect AI-Generated Content with TheChecker.AI
Chrome extension that detects and flags AI-generated content