n8n Expression Cheat Sheet (2026)
Stop Googling the same n8n expressions over and over. This is the reference you'll actually use.
n8n expressions are powerful, but the syntax trips people up constantly. Whether you're formatting dates, building conditional logic, or manipulating JSON, this cheat sheet covers what you need.
Bookmark this. You'll be back.
Quick reference: The essentials
Here's what 90% of your expression work looks like:
// Access the current item
{{ $json.fieldName }}
// Access data from a specific node
{{ $node["Node Name"].json.fieldName }}
// Current timestamp
{{ $now }}
// Conditional (ternary)
{{ $json.status === "active" ? "Yes" : "No" }}
Datetime expressions with Luxon
n8n uses Luxon for datetime handling. Forget JavaScript's messy Date object. Luxon just works.
Getting the current time
// Current datetime (ISO format)
{{ $now.toISO() }}
// Output: 2026-01-30T14:30:00.000-08:00
// Just the date
{{ $now.toISODate() }}
// Output: 2026-01-30
// Just the time
{{ $now.toISOTime() }}
// Output: 14:30:00.000-08:00
// Unix timestamp (seconds)
{{ $now.toSeconds() }}
// Output: 1738275000
// Unix timestamp (milliseconds)
{{ $now.toMillis() }}
// Output: 1738275000000
Formatting dates
The toFormat() method is your best friend:
// Custom format
{{ $now.toFormat("yyyy-MM-dd") }}
// Output: 2026-01-30
// US style
{{ $now.toFormat("MM/dd/yyyy") }}
// Output: 01/30/2026
// Human readable
{{ $now.toFormat("MMMM d, yyyy") }}
// Output: January 30, 2026
// With time
{{ $now.toFormat("yyyy-MM-dd HH:mm:ss") }}
// Output: 2026-01-30 14:30:00
// 12-hour format
{{ $now.toFormat("h:mm a") }}
// Output: 2:30 PM
Format tokens reference
| Token | Output | Example |
|---|---|---|
| yyyy | 4-digit year | 2026 |
| yy | 2-digit year | 26 |
| MM | Month (padded) | 01 |
| M | Month | 1 |
| MMMM | Month name | January |
| MMM | Month abbrev | Jan |
| dd | Day (padded) | 30 |
| d | Day | 30 |
| HH | Hour 24h (padded) | 14 |
| h | Hour 12h | 2 |
| mm | Minutes | 30 |
| ss | Seconds | 00 |
| a | AM/PM | PM |
| EEEE | Day name | Thursday |
| EEE | Day abbrev | Thu |
Date math
Add or subtract time easily:
// Add days
{{ $now.plus({ days: 7 }).toISODate() }}
// Output: 2026-02-06
// Subtract hours
{{ $now.minus({ hours: 2 }).toISO() }}
// Multiple units
{{ $now.plus({ months: 1, days: 15 }).toISODate() }}
// Start of day
{{ $now.startOf("day").toISO() }}
// Output: 2026-01-30T00:00:00.000-08:00
// End of month
{{ $now.endOf("month").toISODate() }}
// Output: 2026-01-31
Working with timezones
// Convert to specific timezone
{{ $now.setZone("America/New_York").toISO() }}
// Convert to UTC
{{ $now.toUTC().toISO() }}
// Get timezone name
{{ $now.zoneName }}
// Output: America/Los_Angeles
Parsing date strings
// From ISO string
{{ DateTime.fromISO($json.dateField).toFormat("MM/dd/yyyy") }}
// From custom format
{{ DateTime.fromFormat($json.dateField, "dd-MM-yyyy").toISO() }}
// From Unix timestamp (seconds)
{{ DateTime.fromSeconds($json.timestamp).toISO() }}
// From Unix timestamp (milliseconds)
{{ DateTime.fromMillis($json.timestampMs).toISO() }}
Conditional logic (ternary operators)
The ternary operator is how you do if/else in expressions:
// Basic syntax: condition ? valueIfTrue : valueIfFalse
// Simple check
{{ $json.status === "active" ? "Active" : "Inactive" }}
// Null/undefined check
{{ $json.name ? $json.name : "Unknown" }}
// Shorter null check (nullish coalescing)
{{ $json.name ?? "Unknown" }}
// Nested conditions (use sparingly)
{{ $json.score > 90 ? "A" : $json.score > 80 ? "B" : "C" }}
// Check if field exists
{{ $json.email !== undefined ? "Has email" : "No email" }}
// Empty string check
{{ $json.name !== "" ? $json.name : "No name provided" }}
Common patterns
// Boolean to Yes/No
{{ $json.isEnabled ? "Yes" : "No" }}
// Pluralization
{{ $json.count === 1 ? "item" : "items" }}
// Default values
{{ $json.priority ?? "medium" }}
// Conditional formatting
{{ $json.amount > 0 ? "+" + $json.amount : $json.amount }}
JSON manipulation
Accessing nested data
// Dot notation
{{ $json.user.profile.name }}
// Bracket notation (required for special characters)
{{ $json["user-data"]["first-name"] }}
// Array access
{{ $json.items[0].name }}
// Last item in array
{{ $json.items[$json.items.length - 1].name }}
Array operations
// Get array length
{{ $json.items.length }}
// Map to extract field
{{ $json.items.map(item => item.name) }}
// Filter array
{{ $json.items.filter(item => item.active === true) }}
// Find first match
{{ $json.items.find(item => item.id === "123") }}
// Join array to string
{{ $json.tags.join(", ") }}
// Check if array includes value
{{ $json.roles.includes("admin") ? "Is admin" : "Not admin" }}
Object operations
// Get all keys
{{ Object.keys($json.data) }}
// Get all values
{{ Object.values($json.data) }}
// Check if key exists
{{ "email" in $json ? "Has email" : "No email" }}
// Spread into new object (in Function node)
{{ { ...$json, newField: "value" } }}
String manipulation
Basic operations
// Uppercase
{{ $json.name.toUpperCase() }}
// Lowercase
{{ $json.name.toLowerCase() }}
// Trim whitespace
{{ $json.input.trim() }}
// Replace text
{{ $json.text.replace("old", "new") }}
// Replace all occurrences
{{ $json.text.replaceAll("old", "new") }}
// Split to array
{{ $json.csv.split(",") }}
// Get substring
{{ $json.text.substring(0, 10) }}
// Check if includes
{{ $json.text.includes("keyword") }}
// Check if starts with
{{ $json.text.startsWith("http") }}
Template literals
Build strings with embedded expressions:
// Basic interpolation
{{ `Hello, ${$json.name}!` }}
// Multi-part string
{{ `${$json.firstName} ${$json.lastName}` }}
// With formatting
{{ `Order #${$json.orderId} - Total: $${$json.total.toFixed(2)}` }}
Accessing other nodes
Previous node data
// Input data (same as $json in most cases)
{{ $input.item.json.fieldName }}
// All items from input
{{ $input.all() }}
// First item
{{ $input.first().json.fieldName }}
// Last item
{{ $input.last().json.fieldName }}
Specific node by name
// Single field
{{ $node["HTTP Request"].json.data.id }}
// Check if node has data
{{ $node["Webhook"].json ? "Has data" : "No data" }}
// All items from node
{{ $("Node Name").all() }}
// First item from node
{{ $("Node Name").first().json.fieldName }}
Workflow context
// Workflow ID
{{ $workflow.id }}
// Workflow name
{{ $workflow.name }}
// Execution ID
{{ $execution.id }}
// Execution mode (manual, trigger, etc.)
{{ $execution.mode }}
// Current item index
{{ $itemIndex }}
// Run index (for loops)
{{ $runIndex }}
Number operations
// Round to 2 decimal places
{{ $json.price.toFixed(2) }}
// Round down
{{ Math.floor($json.value) }}
// Round up
{{ Math.ceil($json.value) }}
// Round to nearest
{{ Math.round($json.value) }}
// Absolute value
{{ Math.abs($json.difference) }}
// Parse string to number
{{ parseInt($json.stringNumber) }}
// Parse to float
{{ parseFloat($json.stringDecimal) }}
// Random number (0-1)
{{ Math.random() }}
// Random integer (1-100)
{{ Math.floor(Math.random() * 100) + 1 }}
Common pitfalls and fixes
Problem: Expression returns [object Object]
Cause: You're trying to output an object as a string.
Fix: Access a specific field or use JSON.stringify():
// Wrong
{{ $json.user }}
// Right
{{ $json.user.name }}
// Or stringify if you need the whole object
{{ JSON.stringify($json.user) }}
Problem: Cannot read property of undefined
Cause: The field doesn't exist or a parent is null.
Fix: Use optional chaining or check for existence:
// Wrong
{{ $json.user.profile.name }}
// Right (optional chaining)
{{ $json.user?.profile?.name ?? "Unknown" }}
// Or explicit check
{{ $json.user && $json.user.profile ? $json.user.profile.name : "Unknown" }}
Problem: Date showing as Invalid DateTime
Cause: Wrong format when parsing.
Fix: Match the format exactly:
// If your date is "30-01-2026"
{{ DateTime.fromFormat($json.date, "dd-MM-yyyy").toISO() }}
// If your date is "2026/01/30"
{{ DateTime.fromFormat($json.date, "yyyy/MM/dd").toISO() }}
// When in doubt, use ISO
{{ DateTime.fromISO($json.date).toISO() }}
Problem: Ternary not working as expected
Cause: JavaScript truthy/falsy confusion.
Fix: Be explicit about the condition:
// Wrong (0 is falsy, empty string is falsy)
{{ $json.count ? "Has items" : "Empty" }}
// Right
{{ $json.count > 0 ? "Has items" : "Empty" }}
{{ $json.name !== "" ? $json.name : "No name" }}
Problem: Expression not updating
Cause: Referencing a node that runs after the current one.
Fix: Check your workflow order. You can only access data from nodes that have already executed.
Quick copy-paste templates
Timestamp for filenames
{{ $now.toFormat("yyyyMMdd_HHmmss") }}
// Output: 20260130_143000
Slack-formatted date
{{ `<!date^${$now.toSeconds()}^{date_short} at {time}|${$now.toISO()}>` }}
Email greeting by time of day
{{ $now.hour < 12 ? "Good morning" : $now.hour < 17 ? "Good afternoon" : "Good evening" }}
Clean phone number
{{ $json.phone.replace(/[^0-9]/g, "") }}
Generate UUID-like string
{{ $now.toMillis().toString(36) + Math.random().toString(36).substring(2) }}
More resources
Need help with complex workflows? Book a call or join our community.
Related Posts

n8n Self-Hosting Requirements Guide (2026)
Planning to self-host n8n? The official docs give minimum specs, but real-world deployments need more context. This guide covers RAM, CPU, storage, and database recommendations.

Critical n8n vulnerability: CVE-2026-1470 allows remote code execution
A critical remote code execution vulnerability (CVE-2026-1470) in n8n allows authenticated users to execute arbitrary code. Here's what you need to know and how to fix it.

n8n autosave is here: never lose your workflow progress again
n8n's new autosave feature saves your workflows every two seconds. Here's what changed, why it matters, and how to use the three save modes effectively.
