n8n Code Node: JavaScript & Python Transformation Examples


⚡ n8n Workflow Automation
T3 · Code Node Transformations

n8n Code Node: JavaScript & Python Transformation Examples

The Code node executes custom JavaScript (Node.js 18) or
Python (3.10+ native, or legacy Pyodide) as a workflow step,
providing full access to incoming data for complex manipulation beyond built‑in
nodes. JavaScript runs natively with promises, console.log, and
external npm module support; Python runs in a sandboxed subprocess or via
WebAssembly depending on n8n version. Both languages share two execution
modes—Run Once for All Items (aggregation) and Run Once
for Each Item
(per‑item mapping)—and must return an array of objects
each containing a json key [1].

Node.js 18
JavaScript Runtime [2]

3.10+
Python (Native) Version [3]

2
Execution Modes [1]

1.63.0
Native Python Introduced [3]

Property JavaScript Python (Native) Python (Legacy Pyodide)
Runtime Node.js 18 Native Python 3.10+ Pyodide (CPython via WebAssembly)
Available in Cloud ✅ Yes ❌ No ⚠️ Limited – no external libraries
External Modules Via NODE_FUNCTION_ALLOW_EXTERNAL Full pip (self‑hosted) Pre‑installed Pyodide packages only
Performance Fast (~0.68 ms/exec) Fast (~0.68 ms/exec) Slower (~25.5 ms/exec)
async/await ✅ Yes ✅ Yes ❌ Not supported
Data Access $input.all(), $json _input.all(), _json _input.all(), _json

What are the two Code node execution modes and how do you choose between them?

The Code node provides two execution modes. Run Once for All Items
(default) executes code once regardless of input count, accessing all items
via $input.all() as an array—ideal for aggregation, counting,
cross‑item comparisons, or restructuring nested arrays. Run Once for
Each Item
executes separately per item, accessing data through
$input.item.json (shorthand: $json)—best for
independent field mapping and enrichment.
[1]
[3]

A common mistake: using “Each Item” mode for aggregation tasks like counting
total records—each item sees only its own data and cannot compute a sum across
all items. Use “All Items” mode when the result depends on multiple items.
From n8n 0.166.0, the return format is auto‑corrected if missing the
json wrapper—but for maximum compatibility, always explicitly
return [{ json: { key: "value" } }]. For production
environments, n8n 2.0+ runs Code nodes in isolated Task Runners by default,
with process.env access blocked and ExecuteCommand/
LocalFileTrigger nodes disabled [4].
The “Try to avoid the Code node unless you really need it” community benchmark
found that Code nodes performing filtering or mapping typically take 1‑3
seconds to execute, compared to near‑instant built‑in nodes—use expressions
or Set/IF/Merge nodes when they suffice [5].
For the complete reference of core nodes you can combine with the Code node,
see the
Core n8n Nodes guide.

How do you iterate over items and transform JSON data with JavaScript in the Code node?

In “Run Once for All Items” mode, loop over all input items with
for (const item of $input.all()) { item.json.newField = 1; } return $input.all();.
Use the $input.all() array with .map(),
.filter(), and .reduce() for functional
transformations. To extract a nested array buried inside a JSON wrapper and
convert it into n8n’s item structure, use:
return $input.first().json.data.map(item => ({ json: item })).
[6]
[7]

Key data access patterns: $input.all() returns all items as an
array; $input.first() returns the first item;
$input.last() returns the last;
$input.item.json.fieldName accesses the current item’s JSON
(available in “Each Item” mode); and $json is shorthand for
$input.item.json in “Each Item” mode. Always access
item.json.fieldName rather than item.fieldName—the
data lives under .json. For async operations, use
await $http.get('https://api.example.com') in JavaScript.
For complete Code node transformation patterns including flatMap
expansion of nested arrays into individual items, Luxon date formatting,
and AJV JSON Schema validation, see the
n8n Expression Node reference.

How do you write Python code in the n8n Code node for data transformation?

Python in the Code node accesses items through _input.all()
(mirroring $input.all()) and returns the transformed list with
return _input.all(). List comprehension enables compact field
extraction: summaries = [item.json.get("summary") for item in _input.all()]; return [{"json": {"merged_summary": " ".join(summaries)}}].
In native Python mode (1.63.0+), full Python 3.10+ standard libraries are
available; in legacy Pyodide mode, only Pyodide’s built‑in package set works.
[8]
[9]

A critical Pyodide‑specific pitfall: when type() outputs
<class 'pyodide.ffi.JsProxy'>, convert to a native
Python object using to_py(). This occurs when working with
n8n node data structures such as inputs and outputs.
json.dumps() is not compatible with Pyodide JsProxy objects
and causes workflow hangs [9].
On n8n Cloud, the Python option for the Code node
does not support importing any Python libraries—whether
from the standard library or third‑party packages [10].
For the complete comparison of Code node vs Execute Command node—when you
need full Python capabilities with pip packages—see the
n8n Node Configuration Hub.

🐍 Native Python Upgrade Note (n8n ≥ 1.63.0): Native
Python execution replaced legacy Pyodide. All Code nodes created after
this version use native Python by default. Existing Pyodide nodes
continue to work but receive no further updates. Native Python runs in
a sandboxed subprocess and requires the n8n-python package
installed on the host [3].

How do you handle dates, external modules, and advanced data structures in the Code node?

Dates: In JavaScript, n8n provides the Luxon library globally—
access it with DateTime without any import statement
(DateTime.now().toISO()). In native Python, use
from datetime import datetime and
datetime.fromtimestamp(timestamp).isoformat().
External modules: Self‑hosted JavaScript can import built‑in
modules (NODE_FUNCTION_ALLOW_BUILTIN=*) and external npm modules
(NODE_FUNCTION_ALLOW_EXTERNAL=axios,moment,lodash) [11].

Binary data: Access binary files via
$input.item.binary.fileName in JavaScript or
_input.item.binary.fileName in Python. The Code node can
generate binary output (PDFs, images) using Buffer operations in
JavaScript or bytes() in native Python. Nested
arrays to individual items:
Use flatMap to expand nested
structures:
return $input.first().json.items.flatMap(item => ({ json: item })).
For the n8n 2.0+ environment, process.env access is blocked
by default
inside Code nodes—pass variables via
$env.VARIABLE_NAME in a Set node before the Code node
to keep separation of concerns [11].
For comprehensive error handling, logging, and production‑ready patterns
that combine all data structures, see the
Core n8n Nodes guide.

How can JavaScript and Python in the Code node be compared for choosing the right tool?

Benchmark data reveals a stark performance gap. In legacy Pyodide mode, Python
averages ~25.5 ms per execution compared to ~0.68 ms
for JavaScript
due to WebAssembly compilation overhead. Native Python
(1.63.0+) closes this gap significantly. Beyond raw speed, a single Code node
with JavaScript can replace approximately 15 standard nodes for complex logic,
reducing execution overhead for enterprise‑grade automations.
[12]
[8]

The pragmatic decision rule: use JavaScript for performance‑
critical production workflows with npm dependencies and async API calls.
Use native Python for data‑science tasks requiring pandas,
numpy, or scikit‑learn in self‑hosted deployments. Use Pyodide
Python
only for lightweight math/string transformations where no
external libraries are needed and async is not required. The community
best‑practice guide “Try to avoid the Code node unless you really need it”
advises: reach for built‑in nodes first, expressions next, and Code node
last—since built‑in nodes are more readable, upgrade‑safe, and break less
across versions [5].
For the complete expressions reference and the 58+ built‑in methods that can
replace Code node logic, see the
n8n Expression Node reference.

What are the most common Code node errors and how do you fix them?

Error “A ‘json’ property isn’t an object”—most frequent—
occurs when the Code node returns data without wrapping it in the item
structure { json: { ... } }. Always return
return [{ json: { key: "value" } }].
Error workflow hangs in Python—caused by
json.dumps() on Pyodide JsProxy objects; convert with
to_py() first.
[13]
[14]

Error Code node times out—default timeout is 300 seconds;
increase via node Settings or set EXECUTIONS_TIMEOUT
environment variable. Error Python module import fails—on
n8n Cloud, no Python libraries are importable; on self‑hosted, verify the
module is installed and accessible. Error process.env undefined in
n8n 2.0+
—Code nodes can no longer access environment variables
directly; pass values via $env in nodes upstream of the Code
node. For systematic debugging strategies that catch these errors at
runtime, see the
n8n Error Handling nodes guide.

🧵 Data Structure Golden Rule: Every Code node, in
every language, in every execution mode, must return an array of
objects each containing a json key. For a single output:
return [{ json: { key: "value" } }]. For multiple
outputs: return [{ json: { id: 1 } }, { json: { id: 2 } }].
The json value must be a plain object—not an array, not
a string, not a number [13].
Error Message Likely Cause Fix
“A ‘json’ property isn’t an object” Returned array of raw values ([1, 2, 3]) instead of item objects Wrap each value: [{ json: { value: 1 } }, ...]
Workflow hangs (Python) json.dumps() on Pyodide JsProxy object Call .to_py() first, then json.dumps()
“process is not defined” (n8n 2.0+) Accessing process.env in Code node (blocked by default) Pass env values via Set node using $env.VARIABLE
“ExpressionError” / timeout Code execution exceeds 300s default timeout Set EXECUTIONS_TIMEOUT env var or node‑level timeout

References

This guide is for informational purposes only. For the most current and authoritative information,
always refer to the official n8n website (n8n.io) and
the n8n documentation. Node parameters, Python
version support, and execution defaults may change over time.



Leave a Reply

Your email address will not be published. Required fields are marked *