AutomationFlowsWeb Scraping › Recondash - Web Recon Workflow

Recondash - Web Recon Workflow

ReconDash - Web Recon Workflow. Uses httpRequest. Webhook trigger; 11 nodes.

Webhook trigger★★★★☆ complexity11 nodesHTTP Request
Web Scraping Trigger: Webhook Nodes: 11 Complexity: ★★★★☆ Added:

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 →

Download .json
{
  "name": "ReconDash - Web Recon Workflow",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "recon-trigger",
        "responseMode": "lastNode",
        "options": {}
      },
      "id": "node_webhook",
      "name": "Webhook Trigger",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 1,
      "position": [
        250,
        300
      ],
      "notes": "Entry point \u2014 receives {target_url} from the Python backend or directly from UI."
    },
    {
      "parameters": {
        "functionCode": "// \u2500\u2500 Validate input URL \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst body = items[0].json.body || items[0].json;\nconst targetUrl = (body.target_url || '').trim();\n\nif (!targetUrl.match(/^https?:\\/\\//i)) {\n  throw new Error('Invalid URL: must start with http:// or https://');\n}\n\nconst { hostname } = new URL(targetUrl);\nconst blocked = ['localhost', '127.', '0.0.0.0', '192.168.', '10.', '172.16.'];\nfor (const b of blocked) {\n  if (hostname.startsWith(b)) {\n    throw new Error(`Blocked: ${hostname} is a private/local address.`);\n  }\n}\n\nreturn [{ json: { target_url: targetUrl, hostname, timestamp: new Date().toISOString() } }];\n"
      },
      "id": "node_validate",
      "name": "Validate URL",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        450,
        300
      ]
    },
    {
      "parameters": {
        "url": "http://127.0.0.1:8000/scan/start",
        "method": "POST",
        "bodyParametersUi": {
          "parameter": []
        },
        "sendBody": true,
        "bodyContentType": "json",
        "jsonBody": "={{ JSON.stringify({ target_url: $json.target_url }) }}",
        "options": {
          "timeout": 30000
        }
      },
      "id": "node_recon",
      "name": "Start Recon (Python API)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 3,
      "position": [
        650,
        300
      ],
      "notes": "Calls FastAPI /scan/start \u2192 resolves IP and gets Ollama assessment."
    },
    {
      "parameters": {
        "functionCode": "// \u2500\u2500 Check AI assessment for recommendation \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst data = items[0].json;\nconst assessment = (data.ai_assessment || '').toLowerCase();\n\n// Determine if AI recommends scanning\nconst recommended = !assessment.includes('caution') && !assessment.includes('not recommended');\n\nreturn [{\n  json: {\n    ...data,\n    ai_recommends_scan: recommended,\n    decision_reason: recommended ? 'AI approved' : 'AI flagged caution'\n  }\n}];\n"
      },
      "id": "node_ai_decision",
      "name": "AI Decision Logic",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        850,
        300
      ]
    },
    {
      "parameters": {
        "conditions": {
          "boolean": [
            {
              "value1": "={{ $json.ai_recommends_scan }}",
              "value2": true
            }
          ]
        }
      },
      "id": "node_if_proceed",
      "name": "Should Run Nikto?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        1050,
        300
      ],
      "notes": "True = AI says proceed. False = AI flagged caution."
    },
    {
      "parameters": {
        "url": "http://127.0.0.1:8000/scan/confirm",
        "method": "POST",
        "sendBody": true,
        "bodyContentType": "json",
        "jsonBody": "={{ JSON.stringify({ scan_id: $json.scan_id, confirmed: true }) }}",
        "options": {}
      },
      "id": "node_confirm_yes",
      "name": "Confirm \u2192 Run Nikto",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 3,
      "position": [
        1250,
        200
      ],
      "notes": "Triggers Nikto scan via FastAPI /scan/confirm"
    },
    {
      "parameters": {
        "functionCode": "// \u2500\u2500 Poll until scan completes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Note: In real n8n, use a Wait node + recursive webhook for true async.\n// This example does a simple pass-through; polling is done by the frontend.\nconst data = items[0].json;\nreturn [{ json: { ...data, n8n_action: 'scan_triggered', message: 'Nikto started. Frontend will poll /scan/status.' } }];\n"
      },
      "id": "node_wait_result",
      "name": "Await Result (pass-through)",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        1450,
        200
      ]
    },
    {
      "parameters": {
        "functionCode": "const data = items[0].json;\nreturn [{ json: { ...data, n8n_action: 'scan_skipped', message: 'AI flagged caution. Scan not triggered.' } }];\n"
      },
      "id": "node_skip",
      "name": "Skip Scan (AI Caution)",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        1250,
        420
      ]
    },
    {
      "parameters": {
        "url": "http://127.0.0.1:8000/scan/result/={{ $json.scan_id }}",
        "method": "GET",
        "options": {}
      },
      "id": "node_fetch_results",
      "name": "Fetch Final Results",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 3,
      "position": [
        1650,
        200
      ],
      "notes": "After scan completes, fetch parsed results from API."
    },
    {
      "parameters": {
        "functionCode": "// \u2500\u2500 Store result to JSON file (simple persistence) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// In production: store to PostgreSQL, MongoDB, or Elasticsearch.\nconst data = items[0].json;\nconst summary = {\n  scan_id: data.scan_id,\n  target: data.target_url,\n  ip: data.ip_address,\n  findings_count: (data.findings || []).length,\n  high_count: (data.findings || []).filter(f => f.severity === 'HIGH').length,\n  completed_at: data.completed_at,\n  summary: data.summary\n};\nconsole.log('[ReconDash n8n] Scan stored:', JSON.stringify(summary));\nreturn [{ json: { ...data, stored: true, n8n_summary: summary } }];\n"
      },
      "id": "node_store",
      "name": "Store Result",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        1850,
        200
      ]
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify($json) }}"
      },
      "id": "node_respond",
      "name": "Return Response",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [
        2050,
        300
      ]
    }
  ],
  "connections": {
    "Webhook Trigger": {
      "main": [
        [
          {
            "node": "Validate URL",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate URL": {
      "main": [
        [
          {
            "node": "Start Recon (Python API)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Start Recon (Python API)": {
      "main": [
        [
          {
            "node": "AI Decision Logic",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Decision Logic": {
      "main": [
        [
          {
            "node": "Should Run Nikto?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Should Run Nikto?": {
      "main": [
        [
          {
            "node": "Confirm \u2192 Run Nikto",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Skip Scan (AI Caution)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Confirm \u2192 Run Nikto": {
      "main": [
        [
          {
            "node": "Await Result (pass-through)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Await Result (pass-through)": {
      "main": [
        [
          {
            "node": "Fetch Final Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Final Results": {
      "main": [
        [
          {
            "node": "Store Result",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Store Result": {
      "main": [
        [
          {
            "node": "Return Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Skip Scan (AI Caution)": {
      "main": [
        [
          {
            "node": "Return Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {},
  "id": "recondash-workflow-v1",
  "tags": [
    "security",
    "recon",
    "local"
  ]
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

ReconDash - Web Recon Workflow. Uses httpRequest. Webhook trigger; 11 nodes.

Source: https://github.com/SarthakShende/ReconDash-Local-AI-Powered-Web-Reconnaissance-Dashboard/blob/ff97319048abc05db5b3d00a6e38bd113290e7da/n8n/recon-workflow.json — original creator credit. Request a take-down →

More Web Scraping workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Web Scraping

This n8n template provides enterprise-level version control for your workflows using GitHub integration. Stop losing hours to broken workflows and manual exports – get proper commit history, visual di

n8n, Execute Workflow Trigger, HTTP Request +1
Web Scraping

This flow creates dummy files for every item added in your *Arrs (Radarr/Sonarr) with the tag .

HTTP Request, Ssh
Web Scraping

eek-Go v2 (Batch-Then-Review). Uses httpRequest. Webhook trigger; 75 nodes.

HTTP Request
Web Scraping

This workflow receives webhook requests from a content calendar and uses the X API v2 to publish text posts, threads, image/video posts, and polls, as well as delete existing posts and run a credentia

HTTP Request
Web Scraping

This workflow acts as a central API gateway for all technical indicator agents in the Binance Spot Market Quant AI system. It listens for incoming webhook requests and dynamically routes them to the c

HTTP Request