Skip to main content

n8n Advanced Workflows: Build AI-Powered Automations with Custom Code Nodes (2026)

· 7 min read
Yassine El Haddad
Software Developer & Automation Specialist

I build production AI agents, web scrapers, and automation pipelines. Most of what I publish here comes from the actual problems they run into: proxies that get banned, anti-bot stacks that fingerprint your client, RAG that drifts when the underlying data moves. Stack: Python, TypeScript, Go, FastAPI, LangChain, Crawlee, Playwright, deployed on AWS, GCP, and Cloudflare.

This guide is for developers who've outgrown n8n basics and want custom logic: Code nodes, sub-workflows, error handling, AI agents, and webhook-triggered scraping with Apify. You'll also see how to self-host n8n and when Make.com might fit better.

Try Make.com for no-code automations → | Apify for web data →

Who This Is For

You've built a few n8n workflows. Triggers, HTTP requests, and basic transforms work. Now you need:

  • Custom logic that doesn't fit a standard node
  • Reusable workflows called from others
  • Robust error handling and retries
  • AI-powered decisions in the middle of a flow
  • Webhook-triggered scraping with Apify

Code Node: JavaScript and Python

The Code node runs JavaScript or Python inside n8n. You get full access to upstream data.

Data access:

  • $input.all() — All items from previous node(s)
  • $input.first() — First item
  • $input.item — Current item (when processing one at a time)
  • $json — Data from the current item
  • $env — Environment variables (e.g. API keys)

Example (JavaScript): Transform and filter

const items = $input.all();
const query = $json.query || "default";
const filtered = items.filter(i => i.json.score > 0.5);
return filtered.map(i => ({
json: {
...i.json,
normalized: i.json.value / 100,
source: "n8n-code"
}
}));

Example (Python): Same logic

items = $input.all()
query = items[0].get("json", {}).get("query", "default")
filtered = [i for i in items if i.get("json", {}).get("score", 0) > 0.5]
return [{"json": {**i["json"], "normalized": i["json"].get("value", 0) / 100, "source": "n8n-code"}} for i in filtered]

Return an array of objects with a json property. Each becomes an item for the next node.

Expressions and Data Mapping

Beyond the Code node, n8n's expression language lets you reference upstream data without writing JavaScript. Use {{ $json.fieldName }} to pull values from the previous node. For arrays, use {{ $json.items[0].url }}. Expressions work in any field that supports them—HTTP request bodies, condition checks, and node parameters. When expressions aren't enough, drop in a Code node for full control.

Sub-workflows

Call one workflow from another. Use the Execute Workflow node.

  1. Create a child workflow (e.g. "Process Scraped Data")
  2. In the parent, add Execute Workflow
  3. Select workflow by ID or name
  4. Pass data via the input — the child receives it as $input

Use sub-workflows for:

  • Reusable logic (deduplication, formatting)
  • Parallel branches (call same workflow with different params)
  • Isolated error handling (child fails → parent can retry or route)

Error Handling

Error Trigger node — Runs when another workflow fails. Use it to:

  • Notify via Slack/email
  • Log to a database
  • Push to a dead-letter queue

Retry strategies — In workflow settings, set:

  • Max retries (e.g. 3)
  • Retry interval (e.g. 30 seconds)
  • Retry on specific errors (timeout, 5xx)

Dead-letter webhook — If all retries fail, n8n can POST to a URL with the error payload. Use it to archive failures for later inspection.

AI Agent Workflow

n8n's AI Agent node is LangChain-based. It can:

  • Use OpenAI or Anthropic
  • Call tools (web search, database lookup, HTTP)
  • Maintain conversation memory

Example: Webhook → AI Agent → response

  1. Webhook trigger (POST with {"question": "..."})
  2. AI Agent node: system prompt = "You are a research assistant. Use web search when needed."
  3. Tools: add a tool that calls an API (e.g. Apify run)
  4. Respond with the agent's answer (HTTP Respond or another action)

For scraping-then-analysis, chain: Webhook → Apify HTTP Request → AI Agent (with scraped data as context) → response. See the Apify n8n guide for webhook patterns.

Webhook-Triggered Scraping: n8n + Apify

Typical flow:

  1. Trigger: Webhook receives {"urls": ["https://..."], "query": "..."}
  2. Start Apify run: HTTP Request to POST https://api.apify.com/v2/acts/%7BactorId%7D/runs?fpr=use-apify with Authorization: Bearer {token} and JSON body
  3. Wait: Apify runs asynchronously. Don't wait in n8n — use webhooks.
  4. Callback: Configure Apify Actor to POST to an n8n webhook on SUCCEEDED
  5. Process: n8n webhook receives defaultDatasetId, fetches dataset items via GET https://api.apify.com/v2/datasets/%7Bid%7D/items?fpr=use-apify
  6. Downstream: Route to AI, CRM, or database

n8n's async webhook model avoids Zapier's 30-second timeout. Apify can run for minutes; when done, it pushes results to n8n. See Make.com Apify web scraping for a no-code alternative.

Custom Credentials

n8n supports 100+ integrations. Store API keys in Credentials (Settings → Credentials). Reference them in nodes via the credential selector. Use generic "Header Auth" or "HTTP Request" credentials for custom APIs like Apify.

Self-Hosting n8n with Docker

# docker-compose.yml
services:
n8n:
image: n8nio/n8n
restart: unless-stopped
ports:
- "5678:5678"
environment:
- N8N_BASIC_AUTH_ACTIVE=true
- N8N_BASIC_AUTH_USER=admin
- N8N_BASIC_AUTH_PASSWORD=your_secure_password
volumes:
- n8n_data:/home/node/.n8n

volumes:
n8n_data:

Run: docker compose up -d. n8n at http://localhost:5678.

For local webhooks, use ngrok: ngrok http 5678. Use the ngrok URL as the Apify webhook target.

n8n vs Make.com for Advanced Developer Workflows

Featuren8nMake.com
Code executionFull JavaScript/Python in Code nodeLimited (functions, JSON)
Sub-workflowsExecute Workflow nodeScenarios in scenarios (limited)
Self-hostingYes (Docker, npm)No
Error handlingError Trigger, retries, dead-letterError routes, retries
AI AgentLangChain-based, custom toolsNative AI Agents, visual builder
PricingFree self-hosted; cloud from ~$24/moFrom ~$10.59/mo (operations)
Best forDevelopers, custom logic, self-hostingNon-devs, rapid prototyping, 3000+ apps

Choose n8n when you need Code nodes, sub-workflows, or self-hosting. Choose Make.com when you want the fastest path to production with minimal code. Both integrate with Apify; see Make + Apify and the LangChain Apify content pipeline for pipeline patterns.

Apify Affiliate Banner 728x90Apify Affiliate Banner 728x90Apify Affiliate Banner 300x50Apify Affiliate Banner 300x50
Next step

Add a Code node to your next n8n workflow. Use $input.all() and return an array of items. For no-code Apify pipelines, try Make.com.

Frequently Asked Questions

Yes. Select 'Python' in the Code node. Requires Python to be available in the n8n environment (default in Docker).

Use Execute Workflow node. The input you pass becomes $input in the child workflow. Pass JSON or item array.

Via the @apify/n8n-nodes-apify community node. Or use HTTP Request node with Apify REST API.

Yes. Run ngrok http 5678. Use the ngrok URL as the webhook URL. Configure Apify to POST to it on run completion.

n8n: async webhooks, no 30s timeout, Code node for transformations. Make: more integrations, simpler for non-devs. Both work.

Common mistakes and fixes

Code node throws 'item not found'

Use $input.item or $input.all() to access upstream data. Ensure previous node has run successfully.

Sub-workflow times out

Increase execution timeout in workflow settings. Use webhooks for long-running calls.

n8n webhook not receiving Apify callback

Expose n8n via ngrok or public URL. Add webhook URL to Apify Actor's webhooks config.