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].
| 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.
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.
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
- n8n Documentation — Code Node: execution modes, JavaScript & Python setup, data access ($input, $json), return format, built‑in methods
- 匠人学院 (Jiangren) — n8n Code Node: Node.js 18 support, npm package import, Code node vs Zapier comparison, Python flatMap examples (Apr 2026)
- DeepWiki — Code Node: Native Python 3.10+ (1.63.0), $input.all() vs $input.item.json, return format rules, common pitfalls (Mar 2026)
- Contabo — n8n 2.0 Release: Task Runners enabled by default, Code node process.env access blocked, ExecuteCommand/LocalFileTrigger disabled (Dec 2025)
- n8n Community — Try to avoid the Code node unless you really need it: built‑in nodes are more readable, upgrade‑safe, and faster (May 2026)
- Latenode Community — Extract array from JSON wrapper object: $input.all()[0].json.results.forEach with $return.push({json: item}) (Jun 2025)
- n8n Community — Code node vs old Function node: $input.all() loop with item.json.myNewField = 1, return $input.all() pattern (Dec 2022)
- C# Corner — Python to JavaScript in n8n: Data Analytics Playbook — conversion examples, async API handling, Python‑to‑JavaScript cheat sheet (Oct 2025)
- n8n 中文文档 — Code Node console.log/print: Pyodide ffi.JsProxy → to_py() conversion, json.dumps() incompatibility, Python data debugging (2026)
- n8n 中文文档 — 使用代码节点: Python Cloud limitations (no library imports), standard library and third‑party restrictions (2026)
- n8n Documentation — Enable modules in Code node: NODE_FUNCTION_ALLOW_BUILTIN (built‑in), NODE_FUNCTION_ALLOW_EXTERNAL (external npm), Task Runner configuration
- prodSens.live — n8n Code Node Best Practices: Python ~25.5 ms vs JavaScript ~0.68 ms per exec, Task Runner examples, 15‑node reduction (Nov 2025)
- n8n 中文文档 — Code Node Common Issues: ‘json’ property isn’t an object, data structure wrapping, return format rules (2026)
- n8n Community — “A ‘json’ property isn’t an object” fix: wrap return in $input.all() structure, use $json.recordingurl.split().flatMap pattern (Apr 2026)

