This workflow follows the Execute Workflow Trigger → HTTP Request recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "[FC Sub] Firecrawl Autopilot Agent",
"settings": {
"executionOrder": "v1"
},
"nodes": [
{
"parameters": {
"content": "## [FC Sub] Firecrawl Autopilot Agent\n**Purpose:** Hands a natural-language goal to Firecrawl's own `/v1/agent` endpoint \u2014 their server-side agent that autonomously navigates, scrapes, and reasons over a site. Best for complex multi-page tasks where you don't know the structure in advance.\n\n**Called by:** main agent's `firecrawl_autopilot` tool.\n\n**Inputs:**\n- `prompt` (required) \u2014 goal description, e.g. 'Find all pricing pages on shopify.com and summarize their plans'\n- `url?` \u2014 starting URL hint\n- `max_wait?` \u2014 max seconds to wait for sync completion (default 180, max 300)\n- `session_id?`\n\n**Credit cost:** Variable \u2014 Firecrawl bills per scraped page. Expect 5-30 credits per call.\n\n**Mode:** Sync (blocking). Uses Firecrawl's `/v1/agent` sync endpoint so we wait for completion within the workflow instead of polling.\n\n**Flow:** Trigger \u2192 Prep \u2192 POST `/v1/agent` (sync, long timeout) \u2192 Shape \u2192 Ledger \u2192 Return.\n\n**Credentials:** Firecrawl API, Postgres RW.",
"height": 580,
"width": 620,
"color": 6
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-40,
-620
],
"id": "sticky-fc-agent",
"name": "README"
},
{
"parameters": {
"inputSource": "passthrough"
},
"type": "n8n-nodes-base.executeWorkflowTrigger",
"typeVersion": 1.1,
"position": [
0,
0
],
"id": "fc-agent-trigger",
"name": "When Executed by Another Workflow"
},
{
"parameters": {
"jsCode": "const input = $input.first().json;\nconst q = (input.query && typeof input.query === 'object') ? input.query : {};\nconst pick = (k, def) => {\n if (input[k] !== undefined) return input[k];\n if (q[k] !== undefined) return q[k];\n return def;\n};\n\nlet prompt;\nif (typeof input.prompt === 'string') prompt = input.prompt;\nelse if (typeof q.prompt === 'string') prompt = q.prompt;\nif (!prompt || !prompt.trim()) throw new Error('firecrawl_autopilot requires a `prompt` describing the goal.');\n\nlet url = (pick('url') || '').toString().trim();\nif (url && !/^https?:\\/\\//i.test(url)) url = 'https://' + url;\nif (url) { try { new URL(url); } catch { throw new Error(`Invalid URL: ${url}`); } }\n\nlet max_wait = Number(pick('max_wait', 180));\nif (!Number.isFinite(max_wait) || max_wait < 30) max_wait = 180;\nif (max_wait > 300) max_wait = 300; // hard cap\n\nconst session_id = (pick('session_id') || $execution.id || 'no-session').toString();\n\nreturn [{ json: {\n prompt: prompt.trim(),\n url: url || null,\n max_wait,\n session_id,\n execution_id: $execution.id\n} }];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
220,
0
],
"id": "fc-agent-prep",
"name": "Prep Input"
},
{
"parameters": {
"method": "POST",
"url": "https://api.firecrawl.dev/v1/agent",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"prompt\": {{ JSON.stringify($json.prompt) }},\n \"mode\": \"sync\",\n \"maxWait\": {{ $json.max_wait }}\n {{ $json.url ? (', \"url\": ' + JSON.stringify($json.url)) : '' }}\n}",
"options": {
"response": {
"response": {
"responseFormat": "json"
}
},
"timeout": 320000
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
440,
0
],
"id": "fc-agent-http",
"name": "Call Firecrawl Agent (Sync)"
},
{
"parameters": {
"jsCode": "const prep = $('Prep Input').first().json;\nconst resp = $input.first().json;\n\nconst status = resp.status || (resp.success ? 'completed' : 'unknown');\nconst result = resp.data || resp.result || resp.output || null;\nconst pages_visited = Array.isArray(resp.pages) ? resp.pages.length\n : (Array.isArray(resp.data?.pages) ? resp.data.pages.length : 0);\n\n// Firecrawl bills per scraped page during agent execution.\n// If the response doesn't surface credit usage, estimate from pages visited.\nconst reported = resp.credits_used ?? resp.creditsUsed ?? null;\nconst credits_used = reported !== null ? Number(reported) : Math.max(5, pages_visited);\n\nreturn [{ json: {\n prompt: prep.prompt,\n starting_url: prep.url,\n status,\n complete: status === 'completed',\n result,\n pages_visited,\n credits_used,\n run_id: resp.id || resp.runId || null,\n session_id: prep.session_id,\n execution_id: prep.execution_id\n} }];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
660,
0
],
"id": "fc-agent-shape",
"name": "Shape Response"
},
{
"parameters": {
"operation": "executeQuery",
"query": "INSERT INTO public.firecrawl_credit_ledger (session_id, execution_id, operation, credits_used, url, status, metadata)\nVALUES ($1, $2, 'autopilot', $3, $4, $5, $6::jsonb);",
"options": {
"queryReplacement": "={{ $json.session_id }}, {{ $json.execution_id }}, {{ $json.credits_used }}, {{ $json.starting_url }}, {{ $json.complete ? 'ok' : 'partial' }}, {{ JSON.stringify({ status: $json.status, pages_visited: $json.pages_visited, run_id: $json.run_id, prompt: $json.prompt }) }}"
}
},
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.6,
"position": [
880,
0
],
"id": "fc-agent-ledger",
"name": "Log Credit Ledger"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "fa1",
"name": "status",
"value": "={{ $('Shape Response').first().json.status }}",
"type": "string"
},
{
"id": "fa2",
"name": "complete",
"value": "={{ $('Shape Response').first().json.complete }}",
"type": "boolean"
},
{
"id": "fa3",
"name": "result",
"value": "={{ $('Shape Response').first().json.result }}",
"type": "object"
},
{
"id": "fa4",
"name": "pages_visited",
"value": "={{ $('Shape Response').first().json.pages_visited }}",
"type": "number"
},
{
"id": "fa5",
"name": "credits_used",
"value": "={{ $('Shape Response').first().json.credits_used }}",
"type": "number"
},
{
"id": "fa6",
"name": "run_id",
"value": "={{ $('Shape Response').first().json.run_id }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1100,
0
],
"id": "fc-agent-return",
"name": "Return Autopilot"
}
],
"connections": {
"When Executed by Another Workflow": {
"main": [
[
{
"node": "Prep Input",
"type": "main",
"index": 0
}
]
]
},
"Prep Input": {
"main": [
[
{
"node": "Call Firecrawl Agent (Sync)",
"type": "main",
"index": 0
}
]
]
},
"Call Firecrawl Agent (Sync)": {
"main": [
[
{
"node": "Shape Response",
"type": "main",
"index": 0
}
]
]
},
"Shape Response": {
"main": [
[
{
"node": "Log Credit Ledger",
"type": "main",
"index": 0
}
]
]
},
"Log Credit Ledger": {
"main": [
[
{
"node": "Return Autopilot",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
[FC Sub] Firecrawl Autopilot Agent. Uses executeWorkflowTrigger, httpRequest, postgres. Event-driven trigger; 7 nodes.
Source: https://github.com/MinaSaad1/n8n-firecrawl-web-crawler-agent/blob/main/workflows/09-sub-firecrawl-agent.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
[FC Sub] Scrape URL with 24h Cache. Uses executeWorkflowTrigger, postgres, httpRequest. Event-driven trigger; 14 nodes.
[FC Sub] Crawl Site (Bounded). Uses executeWorkflowTrigger, httpRequest, postgres. Event-driven trigger; 12 nodes.
[FC Sub] Batch Scrape URLs. Uses executeWorkflowTrigger, httpRequest, postgres. Event-driven trigger; 12 nodes.
[FC Sub] Extract Structured Data. Uses executeWorkflowTrigger, httpRequest, postgres. Event-driven trigger; 12 nodes.
[FC Sub] Search the Web. Uses executeWorkflowTrigger, httpRequest, postgres. Event-driven trigger; 7 nodes.