The Code Node: Transform Items With JavaScript
Expressions are perfect for one field at a time. But sometimes you need to do more: reshape every item, combine several fields, filter a list, or generate brand-new items. For that, n8n gives you the Code node, a single node where you write plain JavaScript that runs over your items. It is the escape hatch that means n8n never boxes you in: when the visual nodes are not enough, you write a few lines of code and carry on. And because it is just JavaScript, you can practice the exact logic in this lesson before you ever open n8n.
What You'll Learn
- What the Code node is and when to reach for it instead of a Set node
- The two run modes: once for all items, and once per item
- How to read incoming items and return correctly shaped items
- How to add, transform, and filter fields in code
- Hands-on practice writing the same transforms you would use in n8n
When to use the Code node
Reach for the Code node when a task is awkward or impossible with the standard nodes:
- Combine multiple fields with custom logic (build a full mailing address from parts).
- Reshape data heavily (turn one item with an array inside it into many items).
- Apply calculations that are too involved for a single expression.
- Filter items based on a condition you would rather express in code.
If you only need to set a couple of fields, the Set node is simpler. The Code node is for when you genuinely need programmable control.
The data contract: items in, items out
The Code node has one rule that matters above all else: it works with items, and it must return items. Incoming data arrives as an array, and you read each element's .json to get its fields. You must return an array where every element is an object with a json property. Get that shape right and everything works; get it wrong and n8n complains that your output is not valid items.
In the default "Run Once for All Items" mode, you have a variable that holds all incoming items, and you return a new array:
// $input.all() gives you every incoming item.
const items = $input.all();
return items.map((item) => {
return {
json: {
fullName: item.json.firstName + " " + item.json.lastName,
email: item.json.email.toLowerCase(),
},
};
});
Notice the shape: you receive { json: {...} } objects and you return { json: {...} } objects. That symmetry is the whole contract.
The two modes
The Code node can run in one of two modes, and choosing the right one saves a lot of confusion:
Pick the mode that matches how you think about the task
| Criteria | Run Once for All Items | Run Once for Each Item |
|---|---|---|
| You receive | The whole list at once | One item at a time |
| You return | An array of items | A single item |
| Best for | Filtering, splitting, totals across items | Simple per-row transforms |
| Read items with | $input.all() | $json (the current item) |
Run Once for All Items
- You receive
- The whole list at once
- You return
- An array of items
- Best for
- Filtering, splitting, totals across items
- Read items with
- $input.all()
Run Once for Each Item
- You receive
- One item at a time
- You return
- A single item
- Best for
- Simple per-row transforms
- Read items with
- $json (the current item)
In "Run Once for Each Item" mode the code is simpler because you only think about one item:
// $json is the current item's fields, just like in an expression.
return {
json: {
fullName: $json.firstName + " " + $json.lastName,
isPro: $json.plan === "pro",
},
};
Use "each item" mode for straightforward row-by-row work, and "all items" mode when you need to see the whole list, for example to filter it or compute a total.
Practice: write the transform first
Because the Code node is plain JavaScript over { json } items, you can build and test your logic right here, then paste it into n8n. The editor below simulates a list of incoming items and runs an "all items" style transform. Run it, then complete the challenges.
For challenge 1, returning items.filter(i => i.json.plan === "pro") from a Code node is a clean way to filter when an IF node would be clumsy. For challenge 2, items.reduce((sum, i) => sum + i.json.amount, 0) gives you 240; in a real workflow you would wrap that in a single returned item like return [{ json: { total } }] so it flows on as one item.
Dropping a Code node into a workflow
Here is the starter workflow you can import. It uses a manual trigger, a small Set node that creates two sample items, and a Code node that adds a fullName field. Copy it, paste it onto your canvas, and run it.
{
"name": "Code Node Demo",
"nodes": [
{
"parameters": {},
"id": "trig-1",
"name": "When clicking Test",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [240, 300]
},
{
"parameters": {
"jsCode": "return [\n { json: { firstName: 'Ada', lastName: 'Lovelace' } },\n { json: { firstName: 'Grace', lastName: 'Hopper' } }\n];"
},
"id": "seed-1",
"name": "Make Sample Items",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [480, 300]
},
{
"parameters": {
"jsCode": "return $input.all().map((item) => {\n return { json: { fullName: item.json.firstName + ' ' + item.json.lastName } };\n});"
},
"id": "code-1",
"name": "Add Full Name",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [720, 300]
}
],
"connections": {
"When clicking Test": {
"main": [[{ "node": "Make Sample Items", "type": "main", "index": 0 }]]
},
"Make Sample Items": {
"main": [[{ "node": "Add Full Name", "type": "main", "index": 0 }]]
}
}
}
Click Add Full Name after running and you will see two items, each with a single fullName field. The challenge: edit the Add Full Name Code node so it also adds an initials field, for example "A. L.". (Hint: item.json.firstName.charAt(0) + '. ' + item.json.lastName.charAt(0) + '.'.)
Key Takeaways
- The Code node lets you write plain JavaScript when the visual nodes are not enough; it is n8n's escape hatch, not a requirement.
- It follows a strict contract: read items via
$input.all()(or$jsonper item) and return objects shaped as{ json: {...} }. - "Run Once for All Items" gives you the whole list (good for filtering and totals); "Run Once for Each Item" gives you one item at a time (good for simple transforms).
- Because it is just JavaScript over
{ json }items, you can build and test your logic in a plain editor first, then paste it in. - Use Set for a couple of fields and the Code node for real reshaping, filtering, or generating new items.

