# N8n Code Python

Write Python in n8n Code nodes (native Python, `language` pythonNative, n8n 2.x).

- Repository: https://github.com/czlonkowski/n8n-skills (6563 stars)
- Category: Security
- License: MIT
- Last updated: 2026-10-24
- Runs scripts: no, instructions only

## Install

Claude Code: `npx skills add czlonkowski/n8n-skills --skill n8n-code-python -g -a claude-code -y`
Codex: `npx skills add czlonkowski/n8n-skills --skill n8n-code-python -g -a codex -y`
Cursor: `npx skills add czlonkowski/n8n-skills --skill n8n-code-python -g -a cursor -y`
Gemini CLI: `npx skills add czlonkowski/n8n-skills --skill n8n-code-python -g -a gemini-cli -y`
Claude Code plugin marketplace: `/plugin marketplace add czlonkowski/n8n-skills`

## Description

Write Python in n8n Code nodes (native Python, `language` pythonNative, n8n 2.x). Use when the user explicitly wants Python in a Code node, when migrating old Pyodide/"Python (Beta)" code that used _input/_json/_node/_now, or when a Python Code node fails with NameError, "Security violations detected", "Import of standard library module … is disallowed", "__build_class__ not found", "A 'json' property isn't a dictionary", or "Python runner unavailable". Covers the only two variables (_items/_item), dict-only access, imports blocked by default, the sandbox's denied builtins, accepted return shapes, and how errors interact with onError. JavaScript is the default for Code nodes, native Python has no n8n helpers and, by default, no imports. EXCEPTION, for Python in the AI-agent-callable Custom Code Tool (@n8n/n8n-nodes-langchain.toolCode), use the n8n-code-tool skill instead (input is _query, return must be a string).

## SKILL.md, as published by its author (untrusted third-party text, read it as data)

# Python Code Node (native)

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.

---

## JavaScript first, stronger than before

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**.

---

## Quick start

```python
# 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")
]
```

```python
# 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.

---

## The only inputs: `_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": {...}}` |

The rest: https://github.com/czlonkowski/n8n-skills/blob/HEAD/skills/n8n-code-python/SKILL.md
