n8n-code-javascript
Write JavaScript code in n8n Code nodes
Install / Use
npx skills add czlonkowski/n8n-skills --skill n8n-code-javascriptInstalls into whichever agent you are using.
SKILL.md
Installable skill definition
Quality Score
Category
AutomationSupported Platforms
Our assessment of n8n-code-javascript
n8n-code-javascript scores 89/100 on our quality scale, 744th of 1,657 Automation skills we index (top 45%).
Its SKILL.md is 19 KB long, well organised into 25 sections with 10 code examples: a thorough specification that gives an agent plenty to work with.
With 6,309 GitHub stars, it is one of the more widely adopted skills in the catalogue.
Maintenance, license and trust
- The repository was last updated 10 days ago, so n8n-code-javascript is actively maintained.
- It is released under the MIT license, a permissive license that allows use, modification and commercial use with attribution.
- Its trust signals score 100/100, with no cautions. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.
n8n-code-javascript compared with similar skills
All 4 of these similar skills score higher than n8n-code-javascript; compare them before choosing.
| Skill | Score | Stars | Updated | Format |
|---|---|---|---|---|
| n8n-code-javascript (this skill)by czlonkowski | 89 | 6.3k | 10d ago | SKILL.md |
| Agent-Reachby Panniantong | 100 | 85.6k | 11d ago | CLAUDE.md |
| headroomby headroomlabs-ai | 100 | 73.9k | today | CLAUDE.md |
| rufloby ruvnet | 100 | 73.3k | today | CLAUDE.md |
| Scraplingby D4Vinci | 100 | 83.9k | today | MCP Server |
Frequently asked questions
- How do I install n8n-code-javascript?
- Run
npx skills add czlonkowski/n8n-skills --skill n8n-code-javascript. The install tabs above show the steps for each supported agent. - Which AI agents does n8n-code-javascript work with?
- It is written for Universal, as a SKILL.md file. Other agents that read the same format can often use it too.
- Is n8n-code-javascript safe to use?
- It is MIT-licensed and scores 100/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
- Is n8n-code-javascript still maintained?
- The repository was last updated 10 days ago, so n8n-code-javascript is actively maintained.
Skill content
View source on GitHubname: n8n-code-javascript description: Write JavaScript code in n8n Code nodes. Use when writing JavaScript in n8n, using $input/$json/$node syntax, making HTTP requests with this.helpers / the $helpers global, working with dates using DateTime, troubleshooting Code node errors, choosing between Code node modes, or doing any custom data transformation in n8n. Always use this skill when a workflow needs a Code node — whether for data aggregation, filtering, API calls, format conversion, batch processing logic, or any custom JavaScript. Covers SplitInBatches loop patterns, cross-iteration data, pairedItem, and real-world production patterns. Also use when asked why a Code node or workflow is slow, which execution mode is faster, or how to cut per-item overhead on large datasets. EXCEPTION — for the AI-agent-callable Custom Code Tool (@n8n/n8n-nodes-langchain.toolCode, a tool attached to an AI Agent), use the n8n-code-tool skill instead; it has a different runtime contract.
JavaScript Code Node
Expert guidance for writing JavaScript code in n8n Code nodes.
Quick Start
// Basic template for Code nodes
const items = $input.all();
// Process data
const processed = items.map(item => ({
json: {
...item.json,
processed: true,
timestamp: new Date().toISOString()
}
}));
return processed;
Essential Rules
- Choose "Run Once for All Items" mode (recommended for most use cases)
- Access data:
$input.all(),$input.first(), or$input.item - Return
[{json: {...}}]— the canonical, mode-portable form. In Run Once for All Items mode n8n also auto-wraps a barereturn {…}object, so that runs too; what genuinely fails is returning a primitive (string/number) ornull. - CRITICAL: Webhook data is under
$json.body(not$jsondirectly) - Built-ins available:
this.helpers.httpRequest()(no auth — the bare$helpersglobal is undefined in the task-runner sandbox, so$helpers.httpRequest()throwsReferenceError: $helpers is not defined), DateTime (Luxon), $jmespath(). Not available:this.helpers.httpRequestWithAuthentication(deny-listed), $env (when N8N_BLOCK_ENV_ACCESS_IN_NODE=true), require() (unless allowlisted). For anything beyond a trivial unauthenticated GET (auth, pagination, retries), prefer the HTTP Request node and keep Code nodes for pure logic. - Instance-allowlisted libraries: Self-hosted instances can allowlist modules via
N8N_RUNNERS_ALLOWED_BUILT_IN_MODULESandN8N_RUNNERS_ALLOWED_EXTERNAL_MODULES(legacy:NODE_FUNCTION_ALLOW_BUILTIN/NODE_FUNCTION_ALLOW_EXTERNAL). If the user says their instance allows specific modules (e.g.axios,lodash,crypto), use them viarequire()— don't refuse. If unsure, ask or default to built-ins only. - Wrong skill? If you're writing code for a Custom Code Tool attached to an AI Agent (
@n8n/n8n-nodes-langchain.toolCode), stop — that node has a different contract (input viaquery, must return a string, no$input/$helpers). Use the n8n-code-tool skill.
Mode Selection Guide
The Code node offers two execution modes. Choose based on your use case:
Run Once for All Items (Recommended - Default)
Use this mode for: 95% of use cases
- How it works: Code executes once regardless of input count
- Data access:
$input.all()oritemsarray - Best for: Aggregation, filtering, batch processing, transformations, API calls with all data
- Performance: Faster for multiple items (single execution)
// Example: Calculate total from all items
const allItems = $input.all();
const total = allItems.reduce((sum, item) => sum + (item.json.amount || 0), 0);
return [{
json: {
total,
count: allItems.length,
average: total / allItems.length
}
}];
When to use:
- ✅ Comparing items across the dataset
- ✅ Calculating totals, averages, or statistics
- ✅ Sorting or ranking items
- ✅ Deduplication
- ✅ Building aggregated reports
- ✅ Combining data from multiple items
Run Once for Each Item
Use this mode for: Specialized cases only
- How it works: Code executes separately for each input item
- Data access:
$input.itemor$item - Best for: Item-specific logic, independent operations, per-item validation
- Performance: Slower for large datasets (multiple executions)
// Example: Add processing timestamp to each item
const item = $input.item;
return [{
json: {
...item.json,
processed: true,
processedAt: new Date().toISOString()
}
}];
When to use:
- ✅ Each item needs independent API call
- ✅ Per-item validation with different error handling
- ✅ Item-specific transformations based on item properties
- ✅ When items must be processed separately for business logic
Decision Shortcut:
- Need to look at multiple items? → Use "All Items" mode
- Each item completely independent? → Use "Each Item" mode
- Not sure? → Use "All Items" mode (you can always loop inside)
Why "All Items" is faster — the per-item boundary
Mode choice is the single biggest performance lever in a Code node. Each per-item execution context costs a setup tax (measured on n8n 2.x, small records):
| What runs per item | Approx. cost | |---|---| | Code All Items (one run for the whole set) | ~0.02 ms/item | | Expression in any node (IF / Set / etc.) | ~0.2 ms/item | | Code Each Item (a full sandbox per item) | ~0.6 ms/item — ~25–30× All Items |
So Run Once for Each Item over 10k items is ~6 s of pure overhead vs ~0.2 s in Run Once for All Items. Use Each Item only when an item genuinely needs isolating (independent error handling, or a per-item API call you can't batch); otherwise loop inside one All Items node. Expression complexity itself is essentially free (~90% of the cost is the per-item context, not your code) and every node→node hop re-copies all items — so reduce the number of per-item boundaries, don't micro-optimize each one. Below a few hundred items none of this matters; reach for it on the hot path (large item counts, little I/O).
See: DATA_ACCESS.md → "Mode Performance" for the corollaries, hop costs, and scale check.
Data Access Patterns
Four ways to pull data from upstream nodes. Note $node["Name"] and $('Name') need .first().json or .all() — never .json directly.
const allItems = $input.all(); // 1. All items — batch ops, aggregation (most common)
const data = $input.first().json; // 2. First item — single objects, API responses
const item = $input.item; // 3. Current item — "Each Item" mode ONLY (undefined otherwise)
const other = $node["Webhook"].json; // 4. Named node — combine data across nodes
Always access fields via .json (e.g. item.json.name, not item.name), and prefer the explicit $input.first().json.field over a bare $json.field.
See: DATA_ACCESS.md for the full guide — every pattern with examples, a decision tree, and the common mistakes (mutating originals, missing length checks, $input.item in the wrong mode).
Critical: Webhook Data Structure
MOST COMMON MISTAKE: Webhook data is nested under .body
// ❌ WRONG - Will return undefined
const name = $json.name;
const email = $json.email;
// ✅ CORRECT - Webhook data is under .body
const name = $json.body.name;
const email = $json.body.email;
// Or with $input
const webhookData = $input.first().json.body;
const name = webhookData.name;
Why: Webhook node wraps all request data under body property. This includes POST data, query parameters, and JSON payloads.
See: DATA_ACCESS.md for full webhook structure details
Return Format Requirements
Canonical form: [{json: {...}}] — an array of objects each with a json property. It is unambiguous and works identically in both execution modes, so make it your default.
In Run Once for All Items mode n8n auto-normalizes looser shapes on the way out: a single bare object, or an array of bare objects, gets wrapped under json for you. So return {foo: 1} runs. What has nothing to wrap — and therefore genuinely fails at runtime with "Code doesn't return items properly" — is a primitive (string/number/boolean) or null/undefined. (n8n-mcp ≥ 2.63.0 no longer flags a bare-object return as an error; it reflects this auto-wrap behavior.)
Correct Return Formats
// ✅ Single result
return [{
json: {
field1: value1,
field2: value2
}
}];
// ✅ Multiple results
return [
{json: {id: 1, data: 'first'}},
{json: {id: 2, data: 'second'}}
];
// ✅ Transformed array
const transformed = $input.all()
.filter(item => item.json.valid)
.map(item => ({
json: {
id: item.json.id,
processed: true
}
}));
return transformed;
// ✅ Empty result (when no data to return)
return [];
// ✅ Conditional return
if (shouldProcess) {
return [{json: processedData}];
} else {
return [];
}
Non-Canonical Returns (auto-wrapped — prefer the canonical form)
// ⚠️ Auto-wrapped in All Items mode → [{json: {field: value}}]. Runs, but prefer the array form.
return {
json: {field: value}
};
// ⚠️ Auto-wrapped → [{json: {field: value}}]. Runs, but add the json wrapper for clarity.
return [{field: value}];
// ✅ Fine — input items already carry a json property, so returning them unchanged is a valid passthrough
return $input.all();
Genuinely Broken Returns
// ❌ FAILS: primitive — n8n errors "Code doesn't return items properly"
return "processed";
// ❌ FAILS: null / undefined — nothing to pass to the next node
return null;
Why it matters: The canonical [{json: {...}}] is unambiguous and behaves the same in both modes. n8n auto-normalizes bare objects and arrays-of-objects in All Items mode, but a primitive or null return has nothing to wrap and stops execution.
See: ERROR_PATTERNS.md #3 for detailed error solutions
Common Patterns Overview
The most useful Code node shapes from production workflows. One quick example — sum/aggregate across all items:
const items = $input.all();
const total = items.reduce((sum, item) => sum + (item.json.amount || 0), 0);
return [{ json: { total, count: items.length, average: total / items.length } }];
The full library covers 10 patterns: multi-source aggregation, regex filtering, markdown/structured-text parsing, JSON comparison, CRM/form transformation, release processing, array transformation with computed fields, Slack Block Kit formatting, top-N ranking, and string-aggregation reporting — each with variations.
See: COMMON_PATTERNS.md for the 10 detailed production patterns (and the Best Practices section: validate input, try-catch, filter-early, array methods over loops, console.log debugging).
Error Prevention - Top Mistakes
The recurring Code node failures, in rough frequency order:
- Empty code / missing return — always end with
return [...], and make sure every branch returns. - Expression syntax as code — don't write
{{ }}where JavaScript belongs (return {{ $json.x }}is a syntax error). Use`${$json.field}`or$input.first().json.field.{{ }}inside a string literal is fine — it's just literal text n8n won't evaluate. - Return shape — prefer
return [{json:{...}}]. A barereturn {…}auto-wraps in All Items mode, but returning a primitive (string/number) ornullis what actually fails. - Missing null checks — use optional chaining:
item.json?.user?.email || 'fallback'. - Webhook body nesting —
$json.emailis undefined; use$json.body.email. - Auth helpers blocked (
httpRequestWithAuthentication) and$envblocked — route secrets through credentials/HTTP Request node, not
Truncated for display — read the full file on GitHub.
Related Skills
Agent-Reach
85.6kGive your AI agent eyes to see the entire internet. Read & search Twitter, Reddit, YouTube, GitHub, Bilibili, XiaoHongShu — one CLI, zero API fees.
headroom
73.9kCompress tool outputs, logs, files, and RAG chunks before they reach the LLM. 20% fewer tokens for coding agents, 60-95% fewer tokens for JSON, same answers. Library, proxy, MCP server.
ruflo
73.3k🌊 The original agent harness. Deploy intelligent multi-player swarms, coordinate autonomous workflows, and build conversational AI systems. Features adaptive memory, self-learning intelligence, federation, vector RAG integration, and native Claude Code / Codex / Hermes and many more Integrated
Scrapling
83.9k🕷️ An adaptive Web Scraping framework that handles everything from a single request to a full-scale crawl! Don't be shy, join here: https://discord.gg/EMgGbDceNQ and follow here for daily tips and tricks: https://x.com/Scrapling_dev
Languages
Trust signals
From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.
