Skip to content

Webhooks Overview

Updated Feb 2026

Webhooks let you receive real-time notifications as your Firecrawl operations progress, instead of polling for status. When an event occurs (a crawl starts, a page is scraped, a job completes), Firecrawl sends an HTTP POST request to the URL you configure with a JSON payload describing the event.

Supported Operations

OperationAvailable Events
Crawlstarted, page, completed
Batch Scrapestarted, page, completed
Extractstarted, completed, failed
Agentstarted, action, completed, failed, cancelled

When to Use Webhooks

Use webhooks instead of polling when you want to react immediately to events without wasting API calls checking status. This is especially valuable for long-running crawl and batch scrape jobs.

Configuration

Add a webhook object to any supported API request:

json
{
  "webhook": {
    "url": "https://your-domain.com/webhook",
    "headers": {
      "X-Custom-Header": "my-value"
    },
    "metadata": {
      "any_key": "any_value"
    },
    "events": ["started", "page", "completed", "failed"]
  }
}

Webhook Configuration Fields

FieldTypeRequiredDescription
urlstringYesYour endpoint URL. Must use HTTPS.
headersobjectNoCustom headers to include with each webhook delivery.
metadataobjectNoCustom key-value data that will be included in every webhook payload. Useful for correlating webhooks with your internal systems.
eventsarrayNoArray of event types to receive. Defaults to all events if omitted.

Usage Examples

Crawl with Webhook

bash
curl -X POST https://api.firecrawl.dev/v2/crawl \
    -H 'Content-Type: application/json' \
    -H 'Authorization: Bearer YOUR_API_KEY' \
    -d '{
      "url": "https://docs.firecrawl.dev",
      "limit": 100,
      "webhook": {
        "url": "https://your-domain.com/webhook",
        "metadata": {
          "project_id": "proj_123",
          "triggered_by": "daily_sync"
        },
        "events": ["started", "page", "completed"]
      }
    }'

Batch Scrape with Webhook

bash
curl -X POST https://api.firecrawl.dev/v2/batch/scrape \
    -H 'Content-Type: application/json' \
    -H 'Authorization: Bearer YOUR_API_KEY' \
    -d '{
      "urls": [
        "https://example.com/page1",
        "https://example.com/page2",
        "https://example.com/page3"
      ],
      "webhook": {
        "url": "https://your-domain.com/webhook",
        "metadata": {
          "batch_name": "competitor_pages"
        },
        "events": ["started", "page", "completed"]
      }
    }'

Extract with Webhook

bash
curl -X POST https://api.firecrawl.dev/v2/extract \
    -H 'Content-Type: application/json' \
    -H 'Authorization: Bearer YOUR_API_KEY' \
    -d '{
      "urls": ["https://example.com"],
      "prompt": "Extract the company name and industry",
      "webhook": {
        "url": "https://your-domain.com/webhook",
        "events": ["completed", "failed"]
      }
    }'

Timeouts and Retries

Your webhook endpoint must respond with a 2xx status code within 10 seconds. If delivery fails (timeout, non-2xx response, or network error), Firecrawl retries automatically:

Retry AttemptDelay After Failure
1st retry1 minute
2nd retry5 minutes
3rd retry15 minutes

After 3 Retries

After 3 failed retries, the webhook is marked as failed and no further delivery attempts are made for that event. The underlying job (crawl, scrape, etc.) continues regardless of webhook delivery status.

Best Practices for Handling Timeouts

  1. Respond immediately -- Return a 200 OK as soon as you receive the webhook, then process the payload asynchronously.
  2. Use a queue -- Push webhook payloads into a message queue (Redis, SQS, RabbitMQ) for background processing.
  3. Keep handlers lightweight -- Avoid long database queries or external API calls in your webhook handler.
javascript
// Good: Respond immediately, process async
app.post('/webhook/firecrawl', (req, res) => {
  res.status(200).send('ok'); // Respond first
  queue.add('process-webhook', req.body); // Process later
});