Write Python code in n8n Code nodes. Use when writing Python in n8n, using _input/_json/_node syntax, working with standard library, or need to understand Python limitations in n8n Code nodes.
Add this skill
npx mdskills install czlonkowski/n8n-code-pythonComprehensive Python guidance for n8n with clear patterns, critical limitations, and practical workarounds
1---2name: n8n-code-python3description: Write Python code in n8n Code nodes. Use when writing Python in n8n, using _input/_json/_node syntax, working with standard library, or need to understand Python limitations in n8n Code nodes.4---56# Python Code Node (Beta)78Expert guidance for writing Python code in n8n Code nodes.910---1112## ⚠️ Important: JavaScript First1314**Recommendation**: Use **JavaScript for 95% of use cases**. Only use Python when:15- You need specific Python standard library functions16- You're significantly more comfortable with Python syntax17- You're doing data transformations better suited to Python1819**Why JavaScript is preferred:**20- Full n8n helper functions ($helpers.httpRequest, etc.)21- Luxon DateTime library for advanced date/time operations22- No external library limitations23- Better n8n documentation and community support2425---2627## Quick Start2829```python30# Basic template for Python Code nodes31items = _input.all()3233# Process data34processed = []35for item in items:36 processed.append({37 "json": {38 **item["json"],39 "processed": True,40 "timestamp": datetime.now().isoformat()41 }42 })4344return processed45```4647### Essential Rules48491. **Consider JavaScript first** - Use Python only when necessary502. **Access data**: `_input.all()`, `_input.first()`, or `_input.item`513. **CRITICAL**: Must return `[{"json": {...}}]` format524. **CRITICAL**: Webhook data is under `_json["body"]` (not `_json` directly)535. **CRITICAL LIMITATION**: **No external libraries** (no requests, pandas, numpy)546. **Standard library only**: json, datetime, re, base64, hashlib, urllib.parse, math, random, statistics5556---5758## Mode Selection Guide5960Same as JavaScript - choose based on your use case:6162### Run Once for All Items (Recommended - Default)6364**Use this mode for:** 95% of use cases6566- **How it works**: Code executes **once** regardless of input count67- **Data access**: `_input.all()` or `_items` array (Native mode)68- **Best for**: Aggregation, filtering, batch processing, transformations69- **Performance**: Faster for multiple items (single execution)7071```python72# Example: Calculate total from all items73all_items = _input.all()74total = sum(item["json"].get("amount", 0) for item in all_items)7576return [{77 "json": {78 "total": total,79 "count": len(all_items),80 "average": total / len(all_items) if all_items else 081 }82}]83```8485### Run Once for Each Item8687**Use this mode for:** Specialized cases only8889- **How it works**: Code executes **separately** for each input item90- **Data access**: `_input.item` or `_item` (Native mode)91- **Best for**: Item-specific logic, independent operations, per-item validation92- **Performance**: Slower for large datasets (multiple executions)9394```python95# Example: Add processing timestamp to each item96item = _input.item9798return [{99 "json": {100 **item["json"],101 "processed": True,102 "processed_at": datetime.now().isoformat()103 }104}]105```106107---108109## Python Modes: Beta vs Native110111n8n offers two Python execution modes:112113### Python (Beta) - Recommended114- **Use**: `_input`, `_json`, `_node` helper syntax115- **Best for**: Most Python use cases116- **Helpers available**: `_now`, `_today`, `_jmespath()`117- **Import**: `from datetime import datetime`118119```python120# Python (Beta) example121items = _input.all()122now = _now # Built-in datetime object123124return [{125 "json": {126 "count": len(items),127 "timestamp": now.isoformat()128 }129}]130```131132### Python (Native) (Beta)133- **Use**: `_items`, `_item` variables only134- **No helpers**: No `_input`, `_now`, etc.135- **More limited**: Standard Python only136- **Use when**: Need pure Python without n8n helpers137138```python139# Python (Native) example140processed = []141142for item in _items:143 processed.append({144 "json": {145 "id": item["json"].get("id"),146 "processed": True147 }148 })149150return processed151```152153**Recommendation**: Use **Python (Beta)** for better n8n integration.154155---156157## Data Access Patterns158159### Pattern 1: _input.all() - Most Common160161**Use when**: Processing arrays, batch operations, aggregations162163```python164# Get all items from previous node165all_items = _input.all()166167# Filter, transform as needed168valid = [item for item in all_items if item["json"].get("status") == "active"]169170processed = []171for item in valid:172 processed.append({173 "json": {174 "id": item["json"]["id"],175 "name": item["json"]["name"]176 }177 })178179return processed180```181182### Pattern 2: _input.first() - Very Common183184**Use when**: Working with single objects, API responses185186```python187# Get first item only188first_item = _input.first()189data = first_item["json"]190191return [{192 "json": {193 "result": process_data(data),194 "processed_at": datetime.now().isoformat()195 }196}]197```198199### Pattern 3: _input.item - Each Item Mode Only200201**Use when**: In "Run Once for Each Item" mode202203```python204# Current item in loop (Each Item mode only)205current_item = _input.item206207return [{208 "json": {209 **current_item["json"],210 "item_processed": True211 }212}]213```214215### Pattern 4: _node - Reference Other Nodes216217**Use when**: Need data from specific nodes in workflow218219```python220# Get output from specific node221webhook_data = _node["Webhook"]["json"]222http_data = _node["HTTP Request"]["json"]223224return [{225 "json": {226 "combined": {227 "webhook": webhook_data,228 "api": http_data229 }230 }231}]232```233234**See**: [DATA_ACCESS.md](DATA_ACCESS.md) for comprehensive guide235236---237238## Critical: Webhook Data Structure239240**MOST COMMON MISTAKE**: Webhook data is nested under `["body"]`241242```python243# ❌ WRONG - Will raise KeyError244name = _json["name"]245email = _json["email"]246247# ✅ CORRECT - Webhook data is under ["body"]248name = _json["body"]["name"]249email = _json["body"]["email"]250251# ✅ SAFER - Use .get() for safe access252webhook_data = _json.get("body", {})253name = webhook_data.get("name")254```255256**Why**: Webhook node wraps all request data under `body` property. This includes POST data, query parameters, and JSON payloads.257258**See**: [DATA_ACCESS.md](DATA_ACCESS.md) for full webhook structure details259260---261262## Return Format Requirements263264**CRITICAL RULE**: Always return list of dictionaries with `"json"` key265266### Correct Return Formats267268```python269# ✅ Single result270return [{271 "json": {272 "field1": value1,273 "field2": value2274 }275}]276277# ✅ Multiple results278return [279 {"json": {"id": 1, "data": "first"}},280 {"json": {"id": 2, "data": "second"}}281]282283# ✅ List comprehension284transformed = [285 {"json": {"id": item["json"]["id"], "processed": True}}286 for item in _input.all()287 if item["json"].get("valid")288]289return transformed290291# ✅ Empty result (when no data to return)292return []293294# ✅ Conditional return295if should_process:296 return [{"json": processed_data}]297else:298 return []299```300301### Incorrect Return Formats302303```python304# ❌ WRONG: Dictionary without list wrapper305return {306 "json": {"field": value}307}308309# ❌ WRONG: List without json wrapper310return [{"field": value}]311312# ❌ WRONG: Plain string313return "processed"314315# ❌ WRONG: Incomplete structure316return [{"data": value}] # Should be {"json": value}317```318319**Why it matters**: Next nodes expect list format. Incorrect format causes workflow execution to fail.320321**See**: [ERROR_PATTERNS.md](ERROR_PATTERNS.md) #2 for detailed error solutions322323---324325## Critical Limitation: No External Libraries326327**MOST IMPORTANT PYTHON LIMITATION**: Cannot import external packages328329### What's NOT Available330331```python332# ❌ NOT AVAILABLE - Will raise ModuleNotFoundError333import requests # ❌ No334import pandas # ❌ No335import numpy # ❌ No336import scipy # ❌ No337from bs4 import BeautifulSoup # ❌ No338import lxml # ❌ No339```340341### What IS Available (Standard Library)342343```python344# ✅ AVAILABLE - Standard library only345import json # ✅ JSON parsing346import datetime # ✅ Date/time operations347import re # ✅ Regular expressions348import base64 # ✅ Base64 encoding/decoding349import hashlib # ✅ Hashing functions350import urllib.parse # ✅ URL parsing351import math # ✅ Math functions352import random # ✅ Random numbers353import statistics # ✅ Statistical functions354```355356### Workarounds357358**Need HTTP requests?**359- ✅ Use **HTTP Request node** before Code node360- ✅ Or switch to **JavaScript** and use `$helpers.httpRequest()`361362**Need data analysis (pandas/numpy)?**363- ✅ Use Python **statistics** module for basic stats364- ✅ Or switch to **JavaScript** for most operations365- ✅ Manual calculations with lists and dictionaries366367**Need web scraping (BeautifulSoup)?**368- ✅ Use **HTTP Request node** + **HTML Extract node**369- ✅ Or switch to **JavaScript** with regex/string methods370371**See**: [STANDARD_LIBRARY.md](STANDARD_LIBRARY.md) for complete reference372373---374375## Common Patterns Overview376377Based on production workflows, here are the most useful Python patterns:378379### 1. Data Transformation380Transform all items with list comprehensions381382```python383items = _input.all()384385return [386 {387 "json": {388 "id": item["json"].get("id"),389 "name": item["json"].get("name", "Unknown").upper(),390 "processed": True391 }392 }393 for item in items394]395```396397### 2. Filtering & Aggregation398Sum, filter, count with built-in functions399400```python401items = _input.all()402total = sum(item["json"].get("amount", 0) for item in items)403valid_items = [item for item in items if item["json"].get("amount", 0) > 0]404405return [{406 "json": {407 "total": total,408 "count": len(valid_items)409 }410}]411```412413### 3. String Processing with Regex414Extract patterns from text415416```python417import re418419items = _input.all()420email_pattern = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'421422all_emails = []423for item in items:424 text = item["json"].get("text", "")425 emails = re.findall(email_pattern, text)426 all_emails.extend(emails)427428# Remove duplicates429unique_emails = list(set(all_emails))430431return [{432 "json": {433 "emails": unique_emails,434 "count": len(unique_emails)435 }436}]437```438439### 4. Data Validation440Validate and clean data441442```python443items = _input.all()444validated = []445446for item in items:447 data = item["json"]448 errors = []449450 # Validate fields451 if not data.get("email"):452 errors.append("Email required")453 if not data.get("name"):454 errors.append("Name required")455456 validated.append({457 "json": {458 **data,459 "valid": len(errors) == 0,460 "errors": errors if errors else None461 }462 })463464return validated465```466467### 5. Statistical Analysis468Calculate statistics with statistics module469470```python471from statistics import mean, median, stdev472473items = _input.all()474values = [item["json"].get("value", 0) for item in items if "value" in item["json"]]475476if values:477 return [{478 "json": {479 "mean": mean(values),480 "median": median(values),481 "stdev": stdev(values) if len(values) > 1 else 0,482 "min": min(values),483 "max": max(values),484 "count": len(values)485 }486 }]487else:488 return [{"json": {"error": "No values found"}}]489```490491**See**: [COMMON_PATTERNS.md](COMMON_PATTERNS.md) for 10 detailed Python patterns492493---494495## Error Prevention - Top 5 Mistakes496497### #1: Importing External Libraries (Python-Specific!)498499```python500# ❌ WRONG: Trying to import external library501import requests # ModuleNotFoundError!502503# ✅ CORRECT: Use HTTP Request node or JavaScript504# Add HTTP Request node before Code node505# OR switch to JavaScript and use $helpers.httpRequest()506```507508### #2: Empty Code or Missing Return509510```python511# ❌ WRONG: No return statement512items = _input.all()513# Processing...514# Forgot to return!515516# ✅ CORRECT: Always return data517items = _input.all()518# Processing...519return [{"json": item["json"]} for item in items]520```521522### #3: Incorrect Return Format523524```python525# ❌ WRONG: Returning dict instead of list526return {"json": {"result": "success"}}527528# ✅ CORRECT: List wrapper required529return [{"json": {"result": "success"}}]530```531532### #4: KeyError on Dictionary Access533534```python535# ❌ WRONG: Direct access crashes if missing536name = _json["user"]["name"] # KeyError!537538# ✅ CORRECT: Use .get() for safe access539name = _json.get("user", {}).get("name", "Unknown")540```541542### #5: Webhook Body Nesting543544```python545# ❌ WRONG: Direct access to webhook data546email = _json["email"] # KeyError!547548# ✅ CORRECT: Webhook data under ["body"]549email = _json["body"]["email"]550551# ✅ BETTER: Safe access with .get()552email = _json.get("body", {}).get("email", "no-email")553```554555**See**: [ERROR_PATTERNS.md](ERROR_PATTERNS.md) for comprehensive error guide556557---558559## Standard Library Reference560561### Most Useful Modules562563```python564# JSON operations565import json566data = json.loads(json_string)567json_output = json.dumps({"key": "value"})568569# Date/time570from datetime import datetime, timedelta571now = datetime.now()572tomorrow = now + timedelta(days=1)573formatted = now.strftime("%Y-%m-%d")574575# Regular expressions576import re577matches = re.findall(r'\d+', text)578cleaned = re.sub(r'[^\w\s]', '', text)579580# Base64 encoding581import base64582encoded = base64.b64encode(data).decode()583decoded = base64.b64decode(encoded)584585# Hashing586import hashlib587hash_value = hashlib.sha256(text.encode()).hexdigest()588589# URL parsing590import urllib.parse591params = urllib.parse.urlencode({"key": "value"})592parsed = urllib.parse.urlparse(url)593594# Statistics595from statistics import mean, median, stdev596average = mean([1, 2, 3, 4, 5])597```598599**See**: [STANDARD_LIBRARY.md](STANDARD_LIBRARY.md) for complete reference600601---602603## Best Practices604605### 1. Always Use .get() for Dictionary Access606607```python608# ✅ SAFE: Won't crash if field missing609value = item["json"].get("field", "default")610611# ❌ RISKY: Crashes if field doesn't exist612value = item["json"]["field"]613```614615### 2. Handle None/Null Values Explicitly616617```python618# ✅ GOOD: Default to 0 if None619amount = item["json"].get("amount") or 0620621# ✅ GOOD: Check for None explicitly622text = item["json"].get("text")623if text is None:624 text = ""625```626627### 3. Use List Comprehensions for Filtering628629```python630# ✅ PYTHONIC: List comprehension631valid = [item for item in items if item["json"].get("active")]632633# ❌ VERBOSE: Manual loop634valid = []635for item in items:636 if item["json"].get("active"):637 valid.append(item)638```639640### 4. Return Consistent Structure641642```python643# ✅ CONSISTENT: Always list with "json" key644return [{"json": result}] # Single result645return results # Multiple results (already formatted)646return [] # No results647```648649### 5. Debug with print() Statements650651```python652# Debug statements appear in browser console (F12)653items = _input.all()654print(f"Processing {len(items)} items")655print(f"First item: {items[0] if items else 'None'}")656```657658---659660## When to Use Python vs JavaScript661662### Use Python When:663- ✅ You need `statistics` module for statistical operations664- ✅ You're significantly more comfortable with Python syntax665- ✅ Your logic maps well to list comprehensions666- ✅ You need specific standard library functions667668### Use JavaScript When:669- ✅ You need HTTP requests ($helpers.httpRequest())670- ✅ You need advanced date/time (DateTime/Luxon)671- ✅ You want better n8n integration672- ✅ **For 95% of use cases** (recommended)673674### Consider Other Nodes When:675- ❌ Simple field mapping → Use **Set** node676- ❌ Basic filtering → Use **Filter** node677- ❌ Simple conditionals → Use **IF** or **Switch** node678- ❌ HTTP requests only → Use **HTTP Request** node679680---681682## Integration with Other Skills683684### Works With:685686**n8n Expression Syntax**:687- Expressions use `{{ }}` syntax in other nodes688- Code nodes use Python directly (no `{{ }}`)689- When to use expressions vs code690691**n8n MCP Tools Expert**:692- How to find Code node: `search_nodes({query: "code"})`693- Get configuration help: `get_node_essentials("nodes-base.code")`694- Validate code: `validate_node_operation()`695696**n8n Node Configuration**:697- Mode selection (All Items vs Each Item)698- Language selection (Python vs JavaScript)699- Understanding property dependencies700701**n8n Workflow Patterns**:702- Code nodes in transformation step703- When to use Python vs JavaScript in patterns704705**n8n Validation Expert**:706- Validate Code node configuration707- Handle validation errors708- Auto-fix common issues709710**n8n Code JavaScript**:711- When to use JavaScript instead712- Comparison of JavaScript vs Python features713- Migration from Python to JavaScript714715---716717## Quick Reference Checklist718719Before deploying Python Code nodes, verify:720721- [ ] **Considered JavaScript first** - Using Python only when necessary722- [ ] **Code is not empty** - Must have meaningful logic723- [ ] **Return statement exists** - Must return list of dictionaries724- [ ] **Proper return format** - Each item: `{"json": {...}}`725- [ ] **Data access correct** - Using `_input.all()`, `_input.first()`, or `_input.item`726- [ ] **No external imports** - Only standard library (json, datetime, re, etc.)727- [ ] **Safe dictionary access** - Using `.get()` to avoid KeyError728- [ ] **Webhook data** - Access via `["body"]` if from webhook729- [ ] **Mode selection** - "All Items" for most cases730- [ ] **Output consistent** - All code paths return same structure731732---733734## Additional Resources735736### Related Files737- [DATA_ACCESS.md](DATA_ACCESS.md) - Comprehensive Python data access patterns738- [COMMON_PATTERNS.md](COMMON_PATTERNS.md) - 10 Python patterns for n8n739- [ERROR_PATTERNS.md](ERROR_PATTERNS.md) - Top 5 errors and solutions740- [STANDARD_LIBRARY.md](STANDARD_LIBRARY.md) - Complete standard library reference741742### n8n Documentation743- Code Node Guide: https://docs.n8n.io/code/code-node/744- Python in n8n: https://docs.n8n.io/code/builtin/python-modules/745746---747748**Ready to write Python in n8n Code nodes - but consider JavaScript first!** Use Python for specific needs, reference the error patterns guide to avoid common mistakes, and leverage the standard library effectively.749
Full transparency — inspect the skill content before installing.