Claude Marketplaces
SkillsMCP serversMarketplacesDigestTools
Submit

This week in Claude

Every Monday: Claude Code, Agent SDK, MCP, and the Anthropic platform moves worth your time.

Skills by category
Frontend DevelopmentBackend & APIsTesting & QASecurityDevOps & CI/CDGit & Pull RequestsDocumentationCode Review & QualityAI & Agent BuildingSkill Development
MCP servers by category
Sales & MarketingWeb & Browser AutomationDatabasesAI & LLM ToolsCloud & InfrastructureCommunication & MessagingDeveloper ToolsDesign & CreativeDocuments & KnowledgeSearch & Web Crawling
Marketplaces by category
AI Agents & OrchestrationLLM IntegrationDevelopment ToolsFrontend & UIBackend & APIsDatabasesTesting & Code QualityDevOps & CloudSecurity & ComplianceGit & Version Control
Claude Marketplaces

An independent directory of skills, plugins and MCP servers for Claude Code. Not affiliated with Anthropic.

Browse

  • Skills
  • MCP servers
  • Marketplaces
  • Weekly digest
  • Skill index
  • MCP index
  • Marketplace index

Site

  • About
  • Tools
  • Submit
  • Feedback
  • Privacy
  • llms.txt
  • Plugins reference

Maker

  • Snug
  • Agent Caffeine
  • knobs
  • Wax
  • Vectoys
  • mertduzgun.com
Crafted at
Skills/Documentation
czlonkowski avatar

N8n Code Python

czlonkowski/n8n-skills

The n8n-code-python skill provides expert guidance for writing Python code in n8n Code nodes, helping workflow developers understand data access patterns, output formatting requirements, and Python's limitations in this environment. It addresses the problem that Python has restricted capabilities in n8n (no external libraries, standard library only) and recommends JavaScript as the preferred alternative for most use cases, while documenting when Python is genuinely necessary. The skill serves developers who are more comfortable with Python syntax and need specific standard library functions for data transformations within n8n workflows.

installs
4.9K
GitHub stars
6.5K
last updated
Aug 21, 2026
View on GitHubSave

Install

$ npx -y skills add czlonkowski/n8n-skills --skill n8n-code-python --agent claude-code

Installs into .claude/skills of the current project.

Files

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

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


The only inputs: _items and _item

ModeVariableShape
Run Once for All Items_itemslist of plain dicts {"json": {...}, "pairedItem": {...}}
Run Once for Each Item_itemone plain dict {"json": {...}, "pairedItem": {...}}
  • Each variable exists only in its own mode. _items in each-item mode (or _item in all-items mode) raises NameError.
  • Dict access only. it["json"]["name"] or it["json"].get("name"). it.json.name raises AttributeError: 'dict' object has no attribute 'json'.
  • No other nodes. There is no _node / $('Node') equivalent. If you need data from another branch, bring it in with Merge first, or read it in JavaScript.
  • Webhook payloads are under ["body"]: _items[0]["json"].get("body", {}).get("email").
  • Binary data isn't covered here. Read and write binary in JavaScript (see n8n-binary-and-data).
  • pairedItem: returning _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.
  • Missing keys: prefer .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, _todaynot 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.fielditem["json"]["field"]

Imports: blocked by default

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: none
  • n8n Cloud: no imports at all.
  • Self-hosted: the admin can allowlist modules in the task-runner config (see n8n-self-hosting → TASK_RUNNERS.md). Some instances therefore allow json, datetime and re, and most don't.
  • Default to import-free code. If an import would really help, confirm it first: a one-line test node import json + return [{"json": {"ok": True}}], or ask the user. Never assume.
  • Without imports: parse JSON strings upstream ({{ JSON.parse($json.payload) }} in Edit Fields). Do date math with the Date & Time node or Luxon in an expression. 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.

Sandbox limits (these fail even without imports)

You writeWhat happensUse instead
eval, exec, compile, open, input, type, getattr, setattr, hasattr, vars, dir, globals, locals, object, memoryview, breakpointNameError: 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 functionNameError: name 'counter' is not defined, because your code runs inside a wrapper functionnonlocal 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).


Return shapes (verified)

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

ReturnResult
[{"json": {...}}, ...]canonical, N items
[{...}, ...] (plain dicts)auto-wrapped under json, N items
{"json": {...}} or a single plain dict1 item
_items (mutated in place)passthrough with your changes
None / no returnerror Cannot read properties of null (reading 'json')

Run Once for Each Item

ReturnResult
{"json": {...}}, a plain dict, or _item1 item
Nonethe item is dropped (a built-in filter)
a listerror 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.


Errors and onError

A 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):

FailurecontinueErrorOutputcontinueRegularOutput
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 emptyinput 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 outputsame

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.

Performance

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.


Checklist

  • The user actually asked for Python. Otherwise JS, an expression, or a native node.
  • Mode matches the variable: _items (all items) / _item (each item).
  • Only dict access. No _input, _json, _node, _now or _jmespath.
  • No import unless confirmed allowlisted on this instance.
  • No classes, type(), getattr/hasattr or dunders. nonlocal instead of global.
  • Return shape fits the mode. Sets and datetimes converted explicitly.
  • Ran a real test execution and inspected the output items (validation alone won't catch the traps above).

Reference

  • COMMON_PATTERNS.md: 12 import-free patterns, each verified on a live n8n instance (filter, aggregate, group, dedupe, top N, flatten, validate, drop items, text report, safe nested access, running totals, ISO timestamps).

Related skills

  • n8n-code-javascript: the default for Code nodes, with all n8n helpers.
  • n8n-expression-syntax: $jmespath, Luxon and the transform gatekeeper, often a better fit than any Code node.
  • n8n-code-tool: Python in the AI-agent Custom Code Tool (_query, returns a string).
  • n8n-error-handling: wiring error outputs; the passthrough trap above.
  • n8n-self-hosting: enabling the Python task runner and allowlisting modules.
SKILL.md on GitHub

Sponsors

SnugThe clipboard manager you and your agent can use, safelyAgent CaffeineClose your lid, come back to finished workWaxBlock anything with supervision, without erasing your iPhoneOpen StepsSponsoredFree and open-source skills that make AI coding agents easier to understand, verify, and control.

Details

Repository
github.com/czlonkowski/n8n-skills
Categories
Documentation, AI & Agent Building, Data Science & ML, Debugging, Automation & Workflows, Python

More from czlonkowski/n8n-skills

All 7
  • N8n Workflow Patterns11.8K
  • N8n Mcp Tools Expert8.3K
  • N8n Node Configuration7.6K
  • N8n Code Javascript7.2K
  • N8n Validation Expert6.8K
  • N8n Expression Syntax6.6K

Recommended

More Documentation
1jeffallan avatarangular-architectjeffallan/claude-skillsGenerates Angular 17+ standalone components, configures advanced routing with lazy loading and guards, implements NgRx state management, applies RxJS patterns, 4.9Kinstalls
2affaan-m avatarreact-testingaffaan-m/eccReact component testing with React Testing Library, Vitest/Jest, MSW for network mocking, accessibility assertions with axe, and the decision boundary between c4.9Kinstalls
3forcedotcom avatardx-code-analyzer-custom-rule-createforcedotcom/sf-skillsCreate custom Code Analyzer rules for Regex (pattern matching), PMD (XPath/AST for Apex and metadata XML), and ESLint (LWC/JavaScript/TypeScript). Use when user4.9Kinstalls
4samber avatarfrontend-design-deslopsamber/cc-skillsProduce distinctive, non-generic UI and design applications well, working strategy-first. Identify the project (landing page, SaaS app, dashboard, ecommerce, pr4.8Kinstalls
5tavily-ai avatarextracttavily-ai/skillsExtract content from specific URLs using Tavily's extraction API. Returns clean markdown/text from web pages. Use when you have specific URLs and need their con4.8Kinstalls
6affaan-m avatarcpp-testingaffaan-m/eccUse only when writing/updating/fixing C++ tests, configuring GoogleTest/CTest, diagnosing failing or flaky tests, or adding coverage/sanitizers.4.8Kinstalls