Appearance
Webhooks Overview
Updated Feb 2026Webhooks 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
| Operation | Available Events |
|---|---|
| Crawl | started, page, completed |
| Batch Scrape | started, page, completed |
| Extract | started, completed, failed |
| Agent | started, 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
| Field | Type | Required | Description |
|---|---|---|---|
url | string | Yes | Your endpoint URL. Must use HTTPS. |
headers | object | No | Custom headers to include with each webhook delivery. |
metadata | object | No | Custom key-value data that will be included in every webhook payload. Useful for correlating webhooks with your internal systems. |
events | array | No | Array 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 Attempt | Delay After Failure |
|---|---|
| 1st retry | 1 minute |
| 2nd retry | 5 minutes |
| 3rd retry | 15 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
- Respond immediately -- Return a
200 OKas soon as you receive the webhook, then process the payload asynchronously. - Use a queue -- Push webhook payloads into a message queue (Redis, SQS, RabbitMQ) for background processing.
- 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
});Related Pages
- Webhook Events -- Full reference for all event types and payload examples
- Webhook Security -- HMAC-SHA256 signature verification
- Testing Webhooks -- Local development and debugging
- Crawl -- Crawl feature documentation
- Rate Limits -- API rate limits per plan