n8n Code node in JavaScript: items, $input and examples
Updated 2026-10-21 · 6 min read
The n8n Code node runs your own JavaScript (or Python) as one step of a workflow. It is the escape hatch for logic that built-in nodes don't cover: reshaping payloads, computing fields, deduplicating, merging lists. This page is the practical reference for the JavaScript side: how data comes in, what you must return, how to read other nodes, and examples that work in n8n 2.x. For Python, see the Python Code node guide.
How data flows through a Code node
Everything passed between n8n nodes is an array of items. Each item wraps your data in a json key, and binary files in a binary key (data structure):
[
{ "json": { "id": 1, "email": "a@example.com" } },
{ "json": { "id": 2, "email": "b@example.com" } }
]
The Code node receives that array and must return one in the same shape. If you return plain objects, n8n adds the json key for you. If you set json to an array, you get the error "A 'json' property isn't an object" (common issues).
The two modes
| Mode | Code runs | Read input with | Return |
|---|---|---|---|
| Run Once for All Items (default) | Once per node execution | $input.all(), $input.first(), $input.last() |
An array of items |
| Run Once for Each Item | Once per input item | $json, $input.item |
A single item |
Pick All Items when the logic needs the whole list: totals, sorting, deduplication, grouping. Pick Each Item for per-record transforms where every item is independent. $json only works in Each Item mode inside the Code node; in All Items mode use item.json on the items you iterate over.
Built-in variables you will use most
From the reference-previous-nodes and n8n metadata pages:
| Expression | Returns |
|---|---|
$input.all() |
All input items |
$input.first() / $input.last() |
First or last input item |
$input.item |
Current item (Each Item mode) |
$json |
Current item's json (Each Item mode) |
$('Node name').all() |
All items output by another node |
$('Node name').first() |
First item of another node |
$('Node name').item |
The item linked to the current one |
$execution.id, $execution.mode |
Execution ID, test or production |
$workflow.id, $workflow.name |
Workflow metadata |
$vars.NAME |
Custom variables (Cloud Pro/Enterprise, self-hosted Business/Enterprise) |
$runIndex |
Zero-based index of the current run of this node |
$('Node name') uses the node's display name. After renaming a node, search your Code nodes for the old name.
Examples
All examples are for Run Once for All Items unless noted.
1. Add a field to every item
return $input.all().map(item => ({
json: { ...item.json, domain: item.json.email.split('@')[1] }
}));
2. The same in Each Item mode
$json.domain = $json.email.split('@')[1];
return $input.item;
3. Filter items
return $input.all().filter(item => item.json.amount > 100);
For a simple condition, the Filter node or an If node is easier to read later. Use code when the condition needs several fields or helper logic.
4. Sum into one item
const total = $input.all().reduce((s, i) => s + Number(i.json.amount || 0), 0);
return [{ json: { total, count: $input.all().length } }];
5. Split an array field into separate items
const order = $input.first().json;
return order.lines.map(line => ({ json: { orderId: order.id, ...line } }));
6. Deduplicate by key
const seen = new Set();
return $input.all().filter(i => {
if (seen.has(i.json.email)) return false;
seen.add(i.json.email);
return true;
});
The Remove Duplicates node does this without code and can also remember keys across executions, which the docs suggest instead of hand-written global state.
7. Read data from an earlier node
const body = $('Webhook').first().json.body;
const user = $('Get user').first().json;
return [{ json: { orderId: body.id, userEmail: user.email } }];
8. Group by a field
const groups = {};
for (const { json } of $input.all()) {
(groups[json.country] ??= []).push(json);
}
return Object.entries(groups).map(([country, rows]) => ({
json: { country, count: rows.length, rows }
}));
9. Stop the branch
if (!$input.first().json.email) return [];
return $input.all();
Returning an empty array means the nodes after this one get no items and don't run. That replaces "exit early" logic from other platforms.
10. Async code
const out = await Promise.all($input.all().map(async item => {
// any async logic that doesn't need the network
return { json: { ...item.json, checkedAt: new Date().toISOString() } };
}));
return out;
The Code node supports promises: you can await inside it or return a promise that resolves to items. For pauses, use the Wait node instead of a timer; for waits of 65 seconds or more it offloads the execution to the database.
What the sandbox doesn't allow
Code nodes in n8n 2.x run on task runners, which are on by default (only external mode is a real isolation boundary; internal mode is a child process the docs call insecure by design) (task runners). That changes what plain Node.js code can do.
| You might write | In the n8n Code node |
|---|---|
fetch(...), axios |
Not available. The docs say the Code node can't make HTTP requests; use the HTTP Request node |
import x from 'y' |
Syntax error. Use require() |
require('lodash') |
Cloud: only crypto and moment. Self-hosted: only allow-listed modules |
fs.readFile |
No file system. Use Read/Write File From Disk |
process.env.KEY |
No process. Use $vars or $env (if env access isn't blocked) |
new URL(...), URLSearchParams |
Not in the 2.x sandbox; parse with string methods or do it in an expression |
this.getCredentials() |
Not allowed by design: Code nodes can't read credentials |
On self-hosted n8n you enable extra modules with NODE_FUNCTION_ALLOW_BUILTIN and NODE_FUNCTION_ALLOW_EXTERNAL, set on the task runner, not the main n8n container. In internal runner mode even crypto is blocked; external mode with the n8nio/runners image and an allow-list is the setup to plan for. Details: npm packages in n8n.
Debugging
console.log()writes to your browser's developer console while you test in the editor, not to the server log.- Run the single node with the input pinned, so you don't trigger upstream API calls on every try.
- If the node errors with "Code doesn't return items properly", log what you return and check it's an array of objects.
Code node or another node?
A Code node is harder to read than a configured node, and harder for teammates to maintain. Before writing code, check if one of these does the job: Edit Fields (Set) for adding or renaming fields, Filter and If for conditions, Split Out for arrays, Aggregate and Summarize for totals, Remove Duplicates, Date & Time. Keep code for logic that would take five nodes to express.
Coming from Pipedream code steps
A Pipedream Node.js step is a component with run({ steps, $ }) and can import any npm package. The n8n Code node is a function body that receives items and returns items, without steps, $.export or free npm. The full mapping, including $.flow.exit and $.respond, is in Pipedream code steps to n8n.
To see which of your steps will run as is and which need rewriting, paste one into the free code step checker. For a whole project, upload the export to the converter: it wraps each code step in a Code node with a compatibility layer and lists every npm import. That layer includes a fetch shim built on a helper n8n doesn't document for the Code node, so test every converted step that calls an API, and prefer moving those calls into HTTP Request nodes. The report and 1 workflow are free. Full export: $3 per workflow, $19 minimum — coming soon.
Not affiliated with Pipedream or n8n.
FAQ
- What does the n8n Code node have to return?
- An array of items, each shaped { json: {...} }. n8n adds the json key and the array wrapper if you leave them out, but json must be an object, not an array.
- What is the difference between $input.all() and $json?
- $input.all() returns every input item and is used in Run Once for All Items mode. $json is the current item's data and works in the Code node only in Run Once for Each Item mode.
- Can I use fetch or axios in the n8n Code node?
- No. The Code node docs say it can't make HTTP requests, and the 2.x sandbox has no fetch. Use the HTTP Request node before or after the Code node.
- Can I use import in the n8n Code node?
- No. ES import and export aren't supported. Use require(), and only for modules that are allowed: crypto and moment on n8n Cloud, allow-listed modules on self-hosted.
- Where does console.log output go?
- To your browser's developer console while you run the workflow in the editor.
Related
Sources
- https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.code
- https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.code/common-issues
- https://docs.n8n.io/build/work-with-data/understand-n8ns-data-structure
- https://docs.n8n.io/build/work-with-data/reference-data/reference-previous-nodes
- https://docs.n8n.io/build/code-in-n8n/use-built-in-shortcuts/n8n-metadata
- https://docs.n8n.io/deploy/host-n8n/configure-n8n/set-up-task-runners