N8n Code Python
davila7/claude-code-templates
Write Python code in n8n Code nodes. An agent skill from davila7/claude-code-templates.
Explains how to write native Python in n8n Code nodes, including the two input variables, blocked imports and fixes for common errors.
$ npx skills add czlonkowski/n8n-skills --skill n8n-code-python -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install czlonkowski/n8n-skills n8n-code-python --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/czlonkowski/n8n-skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/n8n-code-python .claude/skills/n8n-code-python && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "n8n-code-python" agent skill from https://github.com/czlonkowski/n8n-skills/tree/main/skills/n8n-code-python into .claude/skills/n8n-code-python/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "n8n-code-python", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/czlonkowski/n8n-skills/tree/main/skills/n8n-code-pythonType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add czlonkowski/n8n-skills --skill n8n-code-python -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install czlonkowski/n8n-skills n8n-code-python --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/czlonkowski/n8n-skills.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/n8n-code-python .agents/skills/n8n-code-python && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "n8n-code-python" agent skill from https://github.com/czlonkowski/n8n-skills/tree/main/skills/n8n-code-python into .agents/skills/n8n-code-python/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "n8n-code-python", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add czlonkowski/n8n-skills --skill n8n-code-python -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install czlonkowski/n8n-skills n8n-code-python --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/czlonkowski/n8n-skills.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/n8n-code-python .cursor/skills/n8n-code-python && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "n8n-code-python" agent skill from https://github.com/czlonkowski/n8n-skills/tree/main/skills/n8n-code-python into .cursor/skills/n8n-code-python/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "n8n-code-python", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/czlonkowski/n8n-skills.git --path skills/n8n-code-python--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add czlonkowski/n8n-skills --skill n8n-code-python -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install czlonkowski/n8n-skills n8n-code-python --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/czlonkowski/n8n-skills.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/n8n-code-python .gemini/skills/n8n-code-python && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "n8n-code-python" agent skill from https://github.com/czlonkowski/n8n-skills/tree/main/skills/n8n-code-python into .gemini/skills/n8n-code-python/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "n8n-code-python", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install czlonkowski/n8n-skills n8n-code-pythonInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add czlonkowski/n8n-skills --skill n8n-code-python -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/czlonkowski/n8n-skills.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/n8n-code-python .github/skills/n8n-code-python && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "n8n-code-python" agent skill from https://github.com/czlonkowski/n8n-skills/tree/main/skills/n8n-code-python into .github/skills/n8n-code-python/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "n8n-code-python", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add czlonkowski/n8n-skills --skill n8n-code-python -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install czlonkowski/n8n-skills n8n-code-python --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/czlonkowski/n8n-skills.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/n8n-code-python .opencode/skills/n8n-code-python && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "n8n-code-python" agent skill from https://github.com/czlonkowski/n8n-skills/tree/main/skills/n8n-code-python into .opencode/skills/n8n-code-python/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "n8n-code-python", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
n8n-code-pythonExplains how to write native Python in n8n Code nodes, including the two input variables, blocked imports and fixes for common errors.
Since n8n 2.0, Python in the Code node runs as native Python in a task runner, with `language` set to `pythonNative`. The old Pyodide 'Python (Beta)' and its helpers such as `_input`, `_json`, `_node` and `_now` are gone and now raise `NameError`, which is why code copied from older templates often breaks. The skill advises JavaScript first and Python only when asked, because everything n8n-specific, such as node lookups, Luxon, HTTP helpers and static data, exists only in JavaScript.
It covers the only two inputs: `_items` in run-once-for-all-items mode and `_item` in run-once-for-each-item mode, both plain dicts with dict-only access. It also covers blocked imports by default, the sandbox's denied builtins, accepted return shapes, webhook payloads under `body` and how errors interact with onError. A COMMON_PATTERNS.md file adds worked examples. Python in the AI-agent Custom Code Tool is handled by a different skill, where the input is `_query`.
Read from SKILL.md and the folder at commit 19cd793. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
pythonFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Native Python in n8n Code Nodes loads about 2.8k tokens when it runs. Until then it costs about 236 tokens; SKILL.md has 1,221 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from czlonkowski/n8n-skills at commit 19cd793, republished under its MIT licence (© czlonkowski). 1,221 words, ~2,759 tokens.
.claude/skills/n8n-code-python/SKILL.md (or your agent's skills folder). This skill also uses 2 other files; get the full folder from GitHub.Since n8n 2.0 the Code node's Python runs as native Python in a task runner (language: "pythonNative"). The old Pyodide "Python (Beta)" is gone, and with it every n8n helper it had:
_input, _json, _node, _now, _today and _jmespath all raise NameError now. Code copied
from old templates, forum posts or older docs usually breaks on this.
Native Python gives you two variables and plain Python, and by default no imports: no
json, datetime or re. Everything n8n-specific ($('Node'), $jmespath, Luxon,
this.helpers.httpRequest, static data) exists only in JavaScript. Use Python only when the user
explicitly asks for it. Even then, first check whether an expression, Edit Fields, or a native
node (Crypto, Date & Time, HTML, XML) does the job. See n8n-code-javascript and the transform
gatekeeper in n8n-expression-syntax.
# Run Once for All Items (default mode)
return [
{"json": {"name": it["json"]["name"], "revenue": it["json"]["revenue"]}}
for it in _items
if it["json"].get("active")
]# Run Once for Each Item
row = _item["json"]
return {"json": {**row, "name_upper": (row.get("name") or "").upper()}}Node config: {"language": "pythonNative", "mode": "runOnceForAllItems" | "runOnceForEachItem", "pythonCode": "..."} on n8n-nodes-base.code typeVersion 2.
_items and _item| Mode | Variable | Shape |
|---|---|---|
| Run Once for All Items | _items | list of plain dicts {"json": {...}, "pairedItem": {...}} |
| Run Once for Each Item | _item | one plain dict {"json": {...}, "pairedItem": {...}} |
_items in each-item mode (or _item in
all-items mode) raises NameError.it["json"]["name"] or it["json"].get("name"). it.json.name raises
AttributeError: 'dict' object has no attribute 'json'._node / $('Node') equivalent. If you need data from another
branch, bring it in with Merge first, or read it in JavaScript.["body"]: _items[0]["json"].get("body", {}).get("email")._items / _item keeps it. When you build new dicts and downstream
uses $('Node').item, add "pairedItem": {"item": i} to each returned item. That isn't
verified on native Python yet, so test-run before relying on it..get(key, default). row["missing"] raises KeyError.Migration table for legacy code:
| Legacy (Pyodide) | Native |
|---|---|
_input.all() | _items |
_input.first()["json"] | _items[0]["json"] (guard if _items) |
_input.item / _json | _item / _item["json"] |
_node["X"] | not available: Merge upstream, or use JS |
_now, _today | not available: pass {{ $now.toISO() }} in via Edit Fields, or use JS |
_jmespath(data, q) | not available: $jmespath in an expression, or a comprehension |
item.json.field | item["json"]["field"] |
Every import (standard library and third-party) is checked against an allowlist before the
code runs. The default allowlist is empty, so even import json rejects the whole node:
Security violations detected
Line 1: Import of standard library module 'json' is disallowed. Allowed stdlib modules: noneTASK_RUNNERS.md). Some instances therefore allow json, datetime
and re, and most don't.import json + return [{"json": {"ok": True}}], or ask the user. Never
assume.{{ JSON.parse($json.payload) }} in Edit Fields).
Do date math in expressions (Luxon) or JS. ISO-8601 strings still compare and sort correctly as
plain strings. Use the Crypto node for hashing.requests, pandas and numpy are never available unless the admin built a custom runner
image. Use the HTTP Request node for HTTP.| You write | What happens | Use instead |
|---|---|---|
eval, exec, compile, open, input, type, getattr, setattr, hasattr, vars, dir, globals, locals, object, memoryview, breakpoint | NameError: name 'type' is not defined (runtime) | isinstance(x, dict); key in d / d.get(key) |
class Foo: ... | __build_class__ not found (runtime) | dicts + functions |
x.__class__, "{0.__class__}".format(x), __import__("json") | Security violations detected (whole node rejected before running) | — |
global counter inside a function | NameError: name 'counter' is not defined, because your code runs inside a wrapper function | nonlocal counter |
Everything else in plain Python works (verified): comprehensions, generators, lambdas, closures,
recursion, try/except, f-strings / .format() / %, sorted/min/max/sum/any/all/
enumerate/zip/round, sets, isinstance, print() (output goes to the browser console).
Observed on n8n 2.38.5. The auto-wrapping and passthrough behaviours below are undocumented and could change in a later release. Re-check with a test run after upgrading n8n.
Run Once for All Items
| Return | Result |
|---|---|
[{"json": {...}}, ...] | canonical, N items |
[{...}, ...] (plain dicts) | auto-wrapped under json, N items |
{"json": {...}} or a single plain dict | 1 item |
_items (mutated in place) | passthrough with your changes |
None / no return | error Cannot read properties of null (reading 'json') |
Run Once for Each Item
| Return | Result |
|---|---|
{"json": {...}}, a plain dict, or _item | 1 item |
None | the item is dropped (a built-in filter) |
| a list | error A 'json' property isn't a dictionary [item 0] |
Value conversion on output: tuple becomes a list, set becomes the string "{1, 2}",
and a datetime becomes str(dt) ("2026-09-16 10:18:00.025792", not ISO). Convert explicitly
(sorted(s), dt.isoformat()).
Prefer the explicit [{"json": ...}] in all-items mode and {"json": ...} in each-item mode.
The auto-wrapping works, but the explicit shape makes the intent obvious to the next reader.
onErrorA plain raise ValueError("bad row") fails the node with that message. When the node has an
onError continue mode, the three failure kinds behave differently (verified):
| Failure | continueErrorOutput | continueRegularOutput |
|---|---|---|
Runtime exception (raise, KeyError, NameError, denied builtin) | {"error": "<message>"} on the error output (main[1]) ✅ | {"error": "<message>"} on the main output |
Static rejection (Security violations detected: import, dunder) | node marked failed, but the input items, unchanged, go out the success output; main[1] stays empty | input items, unchanged, on the main output |
Bad return shape (list in each-item mode, None in all-items mode) | same: unchanged input on the success output | same |
The last two are silent-data traps: downstream nodes receive unprocessed input as if the code had run, and the execution still shows success. No error branch catches them. Prevent them (no imports unless confirmed, correct return shape) and confirm with a real test run, checking the Code node's status and output (see n8n-error-handling).
Other messages:
Python runner unavailable: Python 3 is missing from this system: the self-hosted instance has
no Python task runner (the stock image ships none). It's an infrastructure problem, not a code
problem. See n8n-self-hosting → TASK_RUNNERS.md.validate_node / validate_workflow catch a few Python mistakes (import requests, missing
return, return None). They do not catch _input/_json, dot access, blocked stdlib
imports, dunder access or classes. A test execution is the only reliable check.Each Python Code node costs roughly 0.4 s (about 1 s when the runner is cold), noticeably more than a JS Code node or an expression. Process lists in Run Once for All Items mode rather than per item, and don't chain several small Python nodes where one would do.
_items (all items) / _item (each item)._input, _json, _node, _now or _jmespath.import unless confirmed allowlisted on this instance.type(), getattr/hasattr or dunders. nonlocal instead of global.$jmespath, Luxon and the transform gatekeeper, often a better fit than any Code node._query, returns a string).© czlonkowski, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 2 other files in skills/n8n-code-python of czlonkowski/n8n-skills.
Open the folder on GitHubat commit 19cd793
Native Python in n8n Code Nodes next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Native Python in n8n Code Nodes this skillczlonkowski/n8n-skills | 6.4k | — | ~2.8k | Automated safety check: Pass | MIT | |
| N8n Code Pythondavila7/claude-code-templates | 32k | 7 repos | ~4.5k | Automated safety check: Pass | MIT | |
| N8n Code Toolsickn33/agentic-awesome-skills | 47k | 1 repos | ~4.1k | Automated safety check: Pass | MIT | |
| N8n Code Javascriptdavila7/claude-code-templates | 32k | 4 repos | ~4k | Automated safety check: Pass | MIT | |
| VectCutAPI Video Editingsun-guannan/VectCutAPI | 2.3k | — | ~2.1k | Automated safety check: Pass | Apache-2.0 | |
| Skyvern Browser AutomationSkyvern-AI/skyvern | 23k | — | ~1.9k | Automated safety check: Pass | AGPL-3.0 |
davila7/claude-code-templates
Write Python code in n8n Code nodes. An agent skill from davila7/claude-code-templates.
sickn33/agentic-awesome-skills
Write and debug JavaScript or Python for the AI-callable n8n Custom Code Tool, including schemas, sandbox limits, and return formats.
davila7/claude-code-templates
Write JavaScript code in n8n Code nodes. An agent skill from davila7/claude-code-templates.
sun-guannan/VectCutAPI
Drives CapCut or JianYing through an HTTP and MCP API: create drafts, add video, audio, text, subtitles and effects, preview on the web and batch-produce videos.
Skyvern-AI/skyvern
Automates websites with Skyvern's AI browser agent to fill forms, extract data, download files, log in and run multi-step workflows through SDKs, REST, MCP or a CLI.
robocorp/robocorp
Bootstrap from an empty folder or build, debug, locally run, and validate Python automations built with Robocorp or Sema4.ai tooling, robocorp.tasks, rcc, robocorp-browser, and RPA Framework.
czlonkowski/n8n-skills
Explains how n8n keeps file bytes in $binary apart from structured $json data, and how to read, write and preserve binary across nodes, agent tools and chat.
czlonkowski/n8n-skills
Guides writing JavaScript in n8n Code nodes: picking an execution mode, reading input data, returning items, using built-in helpers and avoiding common errors.
czlonkowski/n8n-skills
Explains the n8n Custom Code Tool's actual runtime contract so an AI-agent-callable tool doesn't get written like a regular workflow Code node.
czlonkowski/n8n-skills
Wires n8n workflows so failures are visible and recoverable: per-node error outputs, retries, error workflows and correct 4xx and 5xx webhook responses.
czlonkowski/n8n-skills
Keeps an n8n MCP session pointed at the right n8n instance, with rules for discovering, switching and verifying the target before credential writes and for recovering from misroutes.
czlonkowski/n8n-skills
Explains how to configure n8n nodes correctly: which fields each operation requires, how property dependencies show or hide fields, and which get_node detail level to use.
Works with
Categories
Explains how to write native Python in n8n Code nodes, including the two input variables, blocked imports and fixes for common errors. 0, Python in the Code node runs as native Python in a task runner, with `language` set to `pythonNative`. The old Pyodide 'Python (Beta)' and its helpers such as `_input`, `_json`, `_node` and `_now` are gone and now raise `NameError`, which is why code copied from older templates often breaks.
Native Python in n8n Code Nodes fits situations like: writing Python in an n8n Code node when you explicitly want Python; migrating old Pyodide Python code that used _input or _json; fixing a Code node that fails with NameError or a security violation.
Run `npx skills add czlonkowski/n8n-skills --skill n8n-code-python -a claude-code`. Or copy the skill folder (skills/n8n-code-python in czlonkowski/n8n-skills) into .claude/skills/n8n-code-python in your project. Claude Code loads it when a task matches its description.
Run `npx skills add czlonkowski/n8n-skills --skill n8n-code-python -a codex`. Or copy the skill folder (skills/n8n-code-python in czlonkowski/n8n-skills) into .agents/skills/n8n-code-python in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add czlonkowski/n8n-skills --skill n8n-code-python -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/n8n-code-python, .gemini/skills/n8n-code-python, .github/skills/n8n-code-python and .opencode/skills/n8n-code-python in your project.
Going by SKILL.md and its folder, Native Python in n8n Code Nodes needs the command-line tools its instructions call (python). Our summary lists: n8n 2.x with the native Python task runner.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Native Python in n8n Code Nodes is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 2.8k tokens (SKILL.md is roughly 11k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Native Python in n8n Code Nodes: N8n Code Python (davila7/claude-code-templates, 32k stars), N8n Code Tool (sickn33/agentic-awesome-skills, 47k stars), N8n Code Javascript (davila7/claude-code-templates, 32k stars) and VectCutAPI Video Editing (sun-guannan/VectCutAPI, 2.3k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
czlonkowski (a GitHub user) maintains it in czlonkowski/n8n-skills, which has 6,387 GitHub stars. The repository holds 15 skills in this directory. The repository was last updated on September 16, 2026.
Source: czlonkowski/n8n-skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.