Skip to main content
The Python node lets you write and execute custom Python code within your flow. Use it when built-in nodes aren’t enough — complex data transformations, math, string parsing, conditional logic, or anything that’s easier to express in code.

When to Use It

  • Complex data transformations that go beyond what Transform can do
  • Parsing unstructured text (CSV, XML, regex extraction)
  • Mathematical computations or aggregations
  • Building dynamic objects with loops and conditionals
  • Encoding/decoding data (Base64, URL encoding, hashing)
  • Any logic that’s simpler to write in code than to wire with nodes

Configuration

Write your Python code directly in the node’s code editor. Your code has access to the data from previous nodes and must return a result.

Input

Data from previous nodes is available through the input variable — a dictionary containing the output of every upstream node:
# Access data from a previous node (ID: 1, label: "Fetch Users")
users = input["1_Fetch Users"]["body"]["data"]

# Access form data
name = input["1_Form"]["form_data"]["name"]

Output

Your code must return a value using the output variable. This becomes the Python node’s output that downstream nodes can reference:
# Simple value
output = {"status": "processed", "count": len(users)}

# Transformed list
output = [{"name": u["name"], "email": u["email"]} for u in users]

Examples

users = input["1_API"]["body"]["users"]

# Filter to active users and extract relevant fields
active_users = [
    {
        "name": f"{u['first_name']} {u['last_name']}",
        "email": u["email"],
        "role": u.get("role", "member")
    }
    for u in users
    if u.get("active") is True
]

output = {
    "users": active_users,
    "total": len(active_users)
}
import csv
import io

csv_text = input["1_Request"]["body"]["csv_data"]
reader = csv.DictReader(io.StringIO(csv_text))
records = [row for row in reader]

output = {
    "records": records,
    "count": len(records)
}
orders = input["1_Fetch Orders"]["body"]["orders"]

total_revenue = sum(o["amount"] for o in orders)
avg_order = total_revenue / len(orders) if orders else 0
high_value = [o for o in orders if o["amount"] > 500]

output = {
    "total_revenue": round(total_revenue, 2),
    "average_order": round(avg_order, 2),
    "high_value_count": len(high_value),
    "order_count": len(orders)
}
form = input["1_Form"]["form_data"]

# Build different payloads based on form input
if form.get("type") == "bug":
    output = {
        "channel": "#bugs",
        "priority": "high",
        "message": f"Bug report from {form['name']}: {form['description']}"
    }
else:
    output = {
        "channel": "#feedback",
        "priority": "normal",
        "message": f"Feedback from {form['name']}: {form['description']}"
    }
import re

text = input["1_Webhook"]["body"]["message"]

# Extract all email addresses from text
emails = re.findall(r'[\w.+-]+@[\w-]+\.[\w.]+', text)

# Extract invoice numbers (pattern: INV-XXXX)
invoices = re.findall(r'INV-\d+', text)

output = {
    "emails": emails,
    "invoices": invoices
}
from datetime import datetime, timedelta

created = input["1_Record"]["body"]["created_at"]
created_dt = datetime.fromisoformat(created)

output = {
    "created": created,
    "days_ago": (datetime.utcnow() - created_dt).days,
    "is_recent": (datetime.utcnow() - created_dt).days < 7,
    "expiry": (created_dt + timedelta(days=30)).isoformat()
}

Available Libraries

The Python node runs in a sandboxed environment with access to Python’s standard library, including:
  • json — JSON parsing and serialization
  • re — Regular expressions
  • datetime — Date and time operations
  • math — Mathematical functions
  • csv — CSV reading and writing
  • io — String I/O
  • hashlib — Hashing (MD5, SHA256, etc.)
  • base64 — Base64 encoding/decoding
  • urllib.parse — URL encoding/decoding
  • collections — Useful data structures
External packages (like requests or pandas) are not available. For HTTP calls, use a Request node before or after the Python node. For data manipulation, Python’s built-in capabilities are sufficient for most use cases.

Error Handling

If your Python code raises an exception, the node’s failure path fires. The error message is available to downstream nodes on the failure path. Write defensive code when working with data that might be missing or malformed:
users = input.get("1_API", {}).get("body", {}).get("users", [])

if not users:
    output = {"error": "No users found", "count": 0}
else:
    output = {"count": len(users), "first": users[0]["name"]}
Use print() statements for debugging. Print output appears in the run logs, which you can view from the flow’s run history.