Problem: Built-In Nodes Don't Cover Your Logic
n8n has 400+ nodes, but sometimes you need to reshape a payload in a way no node supports, call a library function, or implement business logic that doesn't fit a visual block. That's what the Code node is for.
You'll learn:
- How to use the Code node in both JavaScript and Python modes
- How to read input items, transform them, and return new items
- Patterns for error handling, external HTTP calls, and multi-item processing
Time: 20 min | Difficulty: Intermediate
How the Code Node Works
The Code node runs inside n8n's execution environment. JavaScript runs in a sandboxed Node.js context. Python runs via a subprocess (requires Python 3.10+ on your n8n host).
Each execution receives $input.all() — an array of items from the previous node. You return a new array of items. n8n passes that array to the next node.
Previous Node ──items──▶ Code Node ──transformed items──▶ Next Node
Two execution modes matter:
| Mode | Use when |
|---|---|
| Run Once for All Items | You want to process the full array together (aggregation, dedup) |
| Run Once for Each Item | You want to process each item independently (transform, enrich) |
Set this in the node's Settings → Run Once for Each Item toggle.
Solution
Step 1: Add a Code Node to Your Workflow
- Click + to add a node
- Search for Code
- Select language: JavaScript or Python
- Set execution mode (default is Run Once for All Items)
For the examples below, start with JavaScript.
Step 2: Read and Return Items (JavaScript)
This is the base pattern. Every Code node follows this structure.
// $input.all() returns an array of { json: {...}, binary: {...} }
const items = $input.all();
// Process and return a new array
return items.map(item => {
return {
json: {
...item.json, // keep existing fields
fullName: `${item.json.firstName} ${item.json.lastName}`,
processedAt: new Date().toISOString()
}
};
});
Rules n8n enforces:
- Always return an array of objects
- Each object must have a
jsonkey - Returning
nullor an empty array stops execution for that branch
Step 3: Run Once for Each Item Mode
When you enable Run Once for Each Item, n8n calls your function once per item. Use $input.item instead of $input.all().
// $input.item is the single current item
const item = $input.item;
const price = item.json.price;
const qty = item.json.quantity;
// Validate before operating — bad data crashes the node otherwise
if (typeof price !== 'number' || typeof qty !== 'number') {
throw new Error(`Invalid data on item: ${JSON.stringify(item.json)}`);
}
return {
json: {
...item.json,
total: price * qty,
discount: qty > 10 ? price * qty * 0.1 : 0
}
};
Note: in this mode you return a single object, not an array.
Step 4: Make HTTP Requests Inside the Code Node
JavaScript has $http available as a built-in helper. Use it instead of fetch to stay inside n8n's credential and proxy system.
const items = $input.all();
const results = [];
for (const item of items) {
const userId = item.json.userId;
// $http.get / .post / .put / .delete — mirrors the HTTP Request node
const response = await $http.get(`https://api.example.com/users/${userId}`, {
headers: {
Authorization: `Bearer ${$env.API_TOKEN}` // use n8n env vars, not hardcoded secrets
}
});
results.push({
json: {
...item.json,
email: response.data.email,
plan: response.data.subscription.plan
}
});
}
return results;
If it fails:
401 Unauthorized→ Check thatAPI_TOKENis set in Settings → Environment VariablesTypeError: $http is not defined→ You're on n8n < 1.0. Userequire('axios')instead, or upgrade
Step 5: Use Python Mode
Switch the Code node language to Python. The input items arrive as _input.all() (underscore prefix, not dollar sign).
# Python mode — n8n 1.x with Python 3.10+ on host
items = _input.all()
output = []
for item in items:
data = item["json"]
# Example: parse a date string and reformat it
from datetime import datetime
raw_date = data.get("createdAt", "")
try:
parsed = datetime.strptime(raw_date, "%Y-%m-%dT%H:%M:%S.%fZ")
formatted = parsed.strftime("%B %d, %Y")
except ValueError:
formatted = "Unknown date"
output.append({
"json": {
**data,
"formattedDate": formatted
}
})
return output
Python-specific notes:
importstatements work inside the function — no setup required for stdlib- Third-party packages (e.g.
pandas,httpx) must be installed on the host:pip install pandas - n8n Cloud does not support Python Code nodes — self-hosted only
Step 6: Aggregate Items (Reduce Pattern)
Use Run Once for All Items when you need to combine items into one output.
const items = $input.all();
// Sum a field across all items
const total = items.reduce((sum, item) => sum + (item.json.amount ?? 0), 0);
// Collect unique categories
const categories = [...new Set(items.map(i => i.json.category))];
// Return a single summary item
return [
{
json: {
totalAmount: total,
itemCount: items.length,
categories,
generatedAt: new Date().toISOString()
}
}
];
Step 7: Access Data from Earlier Nodes
Use $node["Node Name"].json to pull data from any upstream node by name — not just the immediately previous one.
// Pull data from a specific earlier node
const webhookData = $node["Webhook"].json;
const dbRow = $node["Postgres"].json;
const item = $input.item;
return {
json: {
userId: webhookData.userId,
planName: dbRow.plan_name,
event: item.json.eventType
}
};
This is useful when your Code node is downstream of a Merge node and the data you need came from two different branches.
Error Handling Pattern
Wrap risky operations and surface meaningful errors. n8n will mark the execution as failed and show your message in the log.
const items = $input.all();
const results = [];
for (const item of items) {
try {
const parsed = JSON.parse(item.json.rawPayload); // may throw
if (!parsed.orderId) {
// Skip malformed items but log them — don't crash the whole run
console.log(`Skipping item missing orderId: ${item.json.rawPayload}`);
continue;
}
results.push({
json: {
orderId: parsed.orderId,
amount: parsed.amount,
currency: parsed.currency ?? "USD"
}
});
} catch (err) {
// Re-throw with context so the n8n log is useful
throw new Error(`Failed to parse item ${item.json.id}: ${err.message}`);
}
}
return results;
Verification
Run your workflow with a test payload and open the Output panel on the Code node. You should see:
Items: 3
Item 0: { json: { ... your transformed fields ... } }
To test error handling, pass a malformed item and confirm n8n marks the execution red with your custom error message — not a generic crash.
What You Learned
- The Code node needs
$input.all()(JS) or_input.all()(Python) and must return an array of{ json: {} }objects - Run Once for Each Item simplifies single-item transforms; Run Once for All Items is for aggregation
$httpis the right way to make HTTP calls — it respects n8n's credential and proxy config- Python mode works only on self-hosted n8n with Python 3.10+ installed
$node["Name"].jsonlets you reach data from any upstream node, not just the previous one
When not to use the Code node: if a built-in node covers 90% of your logic, use it. Code nodes are harder to debug visually and don't show in n8n's node graph as structured data. Save them for logic that genuinely has no node equivalent.
Tested on n8n 1.82, Node.js 20.x, Python 3.12, self-hosted via Docker