Agent skill

Firecrawl Webhooks Skill

Receive and verify Firecrawl webhooks. Use when setting up Firecrawl webhook handlers, debugging X-Firecrawl-Signature verification, or handling crawl, batch scrape, extract, agent, and monitor events like crawl.page, crawl.completed, batch_scrape.completed, and extract.completed.

Install this skill

npx skills add hookdeck/webhook-skills --skill firecrawl-webhooks


When to Use This Skill

  • How do I receive Firecrawl webhooks?
  • How do I verify the X-Firecrawl-Signature header?
  • Why is my Firecrawl webhook signature verification failing?
  • How do I handle crawl.page and crawl.completed events instead of polling?
  • How do I handle batch_scrape, extract, agent, or monitor webhook events?

Verification (core)

Firecrawl signs the raw request body with HMAC-SHA256, keyed with your account webhook secret, and sends the hex digest in X-Firecrawl-Signature as sha256=<hex>. There is no timestamp or message ID in the signed content, and one account-wide secret signs every webhook. Read the raw body (any content type) and compare timing-safe.

Node:

const crypto = require('crypto');

function verify(rawBody, signatureHeader, secret) {
  const [algo, sig] = (signatureHeader || '').split('=');
  if (algo !== 'sha256' || !sig) return false;
  const expected = crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
  try {
    return crypto.timingSafeEqual(Buffer.from(sig.toLowerCase()), Buffer.from(expected));
  } catch {
    return false;
  }
}

Python:

import hmac, hashlib

def verify(raw_body: bytes, signature_header: str, secret: str) -> bool:
    algo, _, sig = (signature_header or "").partition("=")
    if algo != "sha256" or not sig:
        return False
    expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(sig.encode(), expected.encode())

In Express use express.raw({ type: '*/*' }) on the route so verification works whatever Content-Type arrives. Firecrawl has no SDK helper for webhook verification, so verification is manual in every framework.

For complete handlers with route wiring, event dispatch, and tests, see:

Common Event Types

The payload's type field carries the event name:

EventDescription
crawl.startedCrawl job begins processing
crawl.pageA page was scraped during a crawl (data holds the page)
crawl.completedCrawl finished and all pages were processed
batch_scrape.startedBatch scrape job begins processing
batch_scrape.pageA URL was scraped during a batch scrape
batch_scrape.completedAll URLs in the batch were processed
extract.startedExtract job begins processing
extract.completedExtraction finished successfully
extract.failedExtraction failed (error has the reason)
agent.started / agent.action / agent.completed / agent.failed / agent.cancelledAgent job lifecycle
monitor.page / monitor.check.completedMonitor page scrape and check results

For payload shapes and the full list, see references/overview.md and Firecrawl event types

Important Headers

HeaderDescription
X-Firecrawl-Signaturesha256=<hex> HMAC-SHA256 of the raw body

Environment Variables

FIRECRAWL_WEBHOOK_SECRET=your_webhook_secret   # Account settings > Advanced tab

Local Development

# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 firecrawl --path /webhooks/firecrawl

Reference Materials


Repository

hookdeck/webhook-skills

v0.1.0 · MIT · Updated Nov 3, 2026

View on GitHub →