{
  "id": "NGnt5dWPVpVGTwOF",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Scrape, search and browse the web with a Firecrawl AI agent webhook",
  "tags": [],
  "nodes": [
    {
      "id": "b4b5e2a2-3f60-406f-81b4-f7fcad4f9144",
      "name": "Receive Scrape Request",
      "type": "n8n-nodes-base.webhook",
      "position": [
        224,
        672
      ],
      "parameters": {
        "path": "scrape-agent",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 2.1
    },
    {
      "id": "82a9cc43-5e23-4fbb-8d35-aff63475013a",
      "name": "Validate Output Schema",
      "type": "n8n-nodes-base.code",
      "onError": "continueErrorOutput",
      "position": [
        448,
        672
      ],
      "parameters": {
        "jsCode": "const body = $input.first().json.body;\n\n// No schema provided, use permissive default\nif (!body.output_schema) {\n  return [{\n    json: {\n      prompt: body.prompt,\n      output_schema: {\n        type: \"object\",\n        additionalProperties: true\n      }\n    }\n  }];\n}\n\n// Validate the provided schema\nconst schema = body.output_schema;\n\nif (typeof schema !== \"object\" || Array.isArray(schema)) {\n  throw new Error(\"output_schema must be a JSON object\");\n}\n\nif (!schema.type) {\n  throw new Error(\"output_schema must have a 'type' property\");\n}\n\nconst validTypes = [\"object\", \"array\", \"string\", \"number\", \"boolean\"];\nif (!validTypes.includes(schema.type)) {\n  throw new Error(`output_schema.type must be one of: ${validTypes.join(\", \")}`);\n}\n\n// Schema is valid, pass it through\nreturn [{\n  json: {\n    prompt: body.prompt,\n    output_schema: schema\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "132edac3-6602-4963-bf8a-d9a3c3d28733",
      "name": "Return Schema Error",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        640,
        800
      ],
      "parameters": {
        "options": {},
        "respondWith": "json",
        "responseBody": "{\n  \"error\": true,\n  \"message\": \"Invalid output_schema: must be a JSON object with a valid 'type' property (object, array, string, number, boolean)\",\n  \"example_schema\": {\n    \"type\": \"object\",\n    \"properties\": {\n      \"name\": { \"type\": \"string\" },\n      \"price\": { \"type\": \"number\" }\n    }\n  }\n}"
      },
      "typeVersion": 1.5
    },
    {
      "id": "5785b8ae-1c34-4587-83d4-a072c485ef46",
      "name": "Research & Extract Web Data",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        992,
        656
      ],
      "parameters": {
        "text": "={{ $('Receive Scrape Request').item.json.body.prompt }}",
        "options": {
          "maxIterations": 40,
          "systemMessage": "Use Firecrawl's tools to search, then scrape whatever the user's prompt requires. Make sure to  answer the user's query in the best way possible. Consider using search to find the URL before trying to scrape if the user does not specify one.                                                \n                                                                                                    \nWhen using the search tool, at least one source must be selected (web, images, or news).          \n\n Do not use the search tool if you already have the URL.\n\nIMPORTANT:\nIf a URL is provided, try using the scrape tool before using the search tool.\n\nCRITICAL: In Node/JS mode use process.stdout.write(data + \"\\n\") instead of console.log() to return data (console.log output is NOT captured), use unique variable names per call to avoid re-declaration errors in the persistent REPL, and NEVER put agent-browser commands or plain English in the Code field when Language is Node \u2014 agent-browser is Bash only.\n\nIf the website has heavy JavaScript or problems while fetching data (such as requiring interaction for pagination, clicking through elements, filling forms, or navigating deeper), only then use the Interact feature. First scrape the page to get a scrapeId, then use the Interact tool with a prompt or code to perform the needed interactions. \n\nALWAYS use the \"Interact Context\" tool to get full context on how to use the interact tools before using them."
        },
        "promptType": "define",
        "needsFallback": true,
        "hasOutputParser": true
      },
      "typeVersion": 3.1
    },
    {
      "id": "0cfe18d0-f86d-4eae-80e5-d2d3672fcda9",
      "name": "Return Structured Results",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        1424,
        656
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1.5
    },
    {
      "id": "10f8ba2e-c1f3-4d9c-ad74-48fc9c0d422a",
      "name": "Primary Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
      "position": [
        864,
        800
      ],
      "parameters": {
        "model": "anthropic/claude-sonnet-4.6",
        "options": {}
      },
      "credentials": {
        "openRouterApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "4b8f8364-1692-42fa-a005-3642a60390b5",
      "name": "Fallback Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
      "position": [
        1024,
        800
      ],
      "parameters": {
        "model": "anthropic/claude-haiku-4.5",
        "options": {}
      },
      "credentials": {
        "openRouterApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "e7192283-1b70-4d50-abb8-e2fae7b24ae6",
      "name": "Parser Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
      "position": [
        1376,
        912
      ],
      "parameters": {
        "model": "anthropic/claude-haiku-4.5",
        "options": {}
      },
      "credentials": {
        "openRouterApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "e023509d-a032-469f-aa06-ee10d10daebc",
      "name": "Format Response to Schema",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        1392,
        816
      ],
      "parameters": {
        "autoFix": true,
        "schemaType": "manual",
        "inputSchema": "={{ JSON.stringify($('Validate Output Schema').item.json.output_schema) }}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "d1b90a28-a9b1-4552-8ee2-f81b708932ac",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        160,
        -32
      ],
      "parameters": {
        "width": 624,
        "height": 624,
        "content": "## Firecrawl Interact Agent\nSend a POST request with a URL, a natural language prompt, and an optional JSON schema. An AI agent uses Firecrawl to scrape the page, then interact with it, clicking buttons, filling forms, navigating dynamic content, and extracting structured data that matches your schema.\n**Use cases:** form-driven data extraction, authenticated page scraping, paginated content collection, dynamic SPA navigation, multi-step checkout or search flows.\n## How it works\n1. **Receive Interact Request** accepts a POST with a `url`, `prompt`, and optional `output_schema`.\n2. **Validate Output Schema** checks if the schema is valid JSON. If missing, a permissive default is used. If malformed, a clear error is returned immediately.\n3. **Scrape & Interact** first scrapes the target URL to get initial content and a `scrapeId`, then uses Firecrawl's interact feature to click, fill forms, and navigate the live page based on the prompt. No manual session management is required.\n4. **Format Response to Schema** parses the agent's output into structured JSON matching the provided or default schema.\n5. **Return Structured Results** sends the final JSON back to the caller.\n## Setup steps\n1. **Firecrawl API key:** Sign up at [firecrawl.dev](https://www.firecrawl.dev) and connect your key to all Firecrawl credential nodes.\n2. **LLM providers:** Configure the Primary Chat Model and Fallback Chat Model nodes with your preferred provider (OpenRouter, OpenAI, Anthropic, etc.). Also set up the Parser Chat Model used by the output formatter.\n3. **Activate the workflow** and copy your webhook URL.\n4. **Test it:** Send a POST with a `url` and `prompt` to confirm everything works."
      },
      "typeVersion": 1
    },
    {
      "id": "6f01b690-3570-447f-adbf-69fb5fb65bc3",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        160,
        608
      ],
      "parameters": {
        "color": 7,
        "width": 624,
        "height": 304,
        "content": "## Input & Validation"
      },
      "typeVersion": 1
    },
    {
      "id": "1854ff48-aa38-493b-b42d-6919c3e5884e",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        800,
        608
      ],
      "parameters": {
        "color": 7,
        "width": 512,
        "height": 304,
        "content": "## AI Agent & LLM Models"
      },
      "typeVersion": 1
    },
    {
      "id": "89dedb88-3334-472f-9e81-684dd069743c",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1328,
        608
      ],
      "parameters": {
        "color": 7,
        "width": 336,
        "height": 416,
        "content": "## Output & Response"
      },
      "typeVersion": 1
    },
    {
      "id": "01de6598-5edf-4bb0-a91c-032027a1d1f0",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        816,
        1040
      ],
      "parameters": {
        "color": 7,
        "width": 848,
        "height": 640,
        "content": "## Firecrawl Tools"
      },
      "typeVersion": 1
    },
    {
      "id": "2be3ff3c-deb6-4057-84f6-b60ad61e7143",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1056,
        1360
      ],
      "parameters": {
        "color": 5,
        "width": 592,
        "height": 304,
        "content": "## Browser Tool"
      },
      "typeVersion": 1
    },
    {
      "id": "626fbcc2-952a-44d9-9278-4d62182e14af",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        960,
        1088
      ],
      "parameters": {
        "color": 4,
        "width": 352,
        "height": 240,
        "content": "## Search & Scrape"
      },
      "typeVersion": 1
    },
    {
      "id": "db7882fd-6b95-4571-86c0-d12c37db0c0e",
      "name": "/scrape with Firecrawl",
      "type": "@mendable/n8n-nodes-firecrawl.firecrawlTool",
      "position": [
        1008,
        1168
      ],
      "parameters": {
        "url": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('URL', ``, 'string') }}",
        "parsers": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Parsers', ``, 'string') }}",
        "operation": "scrape",
        "requestOptions": {}
      },
      "credentials": {
        "firecrawlApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "466ac39c-e56f-4c59-b6f7-236e68131f5d",
      "name": "/search with Firecrawl",
      "type": "@mendable/n8n-nodes-firecrawl.firecrawlTool",
      "position": [
        1184,
        1168
      ],
      "parameters": {
        "query": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Query', ``, 'string') }}",
        "sources": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Sources', ``, 'string') }}",
        "resource": "MapSearch",
        "operation": "search",
        "requestOptions": {}
      },
      "credentials": {
        "firecrawlApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "24377630-a048-4a29-8374-7e62d7a83008",
      "name": "Interact context with Firecrawl",
      "type": "@mendable/n8n-nodes-firecrawl.firecrawlTool",
      "position": [
        1136,
        1408
      ],
      "parameters": {
        "resource": "Interact",
        "requestOptions": {}
      },
      "credentials": {
        "firecrawlApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "26069d9a-ae64-423e-9172-9cc2a920d918",
      "name": "Execute interaction with Firecrawl",
      "type": "@mendable/n8n-nodes-firecrawl.firecrawlTool",
      "position": [
        1296,
        1488
      ],
      "parameters": {
        "code": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Code', ``, 'string') }}",
        "resource": "Interact",
        "scrapeId": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Scrape_ID', ``, 'string') }}",
        "operation": "interact",
        "interactMode": "code",
        "requestOptions": {}
      },
      "credentials": {
        "firecrawlApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "9b777540-a930-40c0-8e18-c6692b6ac8bb",
      "name": "Stop interaction with Firecrawl",
      "type": "@mendable/n8n-nodes-firecrawl.firecrawlTool",
      "position": [
        1472,
        1488
      ],
      "parameters": {
        "resource": "Interact",
        "scrapeId": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Scrape_ID', ``, 'string') }}",
        "operation": "interactStop",
        "requestOptions": {}
      },
      "credentials": {
        "firecrawlApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    }
  ],
  "active": true,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "823b4c27-e6a2-41a3-a7e1-ac3bec06d801",
  "connections": {
    "Parser Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Format Response to Schema",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Primary Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Research & Extract Web Data",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Fallback Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Research & Extract Web Data",
            "type": "ai_languageModel",
            "index": 1
          }
        ]
      ]
    },
    "/scrape with Firecrawl": {
      "ai_tool": [
        [
          {
            "node": "Research & Extract Web Data",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "/search with Firecrawl": {
      "ai_tool": [
        [
          {
            "node": "Research & Extract Web Data",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Receive Scrape Request": {
      "main": [
        [
          {
            "node": "Validate Output Schema",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate Output Schema": {
      "main": [
        [
          {
            "node": "Research & Extract Web Data",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Return Schema Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Response to Schema": {
      "ai_outputParser": [
        [
          {
            "node": "Research & Extract Web Data",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Research & Extract Web Data": {
      "main": [
        [
          {
            "node": "Return Structured Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Interact context with Firecrawl": {
      "ai_tool": [
        [
          {
            "node": "Research & Extract Web Data",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Stop interaction with Firecrawl": {
      "ai_tool": [
        [
          {
            "node": "Research & Extract Web Data",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Execute interaction with Firecrawl": {
      "ai_tool": [
        [
          {
            "node": "Research & Extract Web Data",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    }
  }
}