n8n expressions let you insert dynamic values into any workflow field — pulling data from previous nodes, transforming strings, calculating dates, and applying logic without a full Code node. Expressions use double-curly-brace syntax: {{ }}. Inside those braces you write standard JavaScript, with access to a set of n8n-specific variables. Use expressions for inline transformations and simple conditionals; switch to a Code node when logic spans multiple lines, requires loops, or needs external modules.
Expression Syntax Basics
Any field with the expression toggle (the = icon) accepts an expression. The content inside {{ }} is evaluated as JavaScript at runtime. You can reference the current item, other nodes, workflow metadata, and built-in helpers.
| Syntax | What it does | Example |
|---|---|---|
{{ $json.fieldName }} |
Access a field from the current input item | {{ $json.email }} |
{{ $json["field name"] }} |
Access a field with spaces or special characters in the key | {{ $json["First Name"] }} |
{{ $node["Node Name"].json.field }} |
Access output data from a specific node by name | {{ $node["HTTP Request"].json.id }} |
{{ $input.item.json.field }} |
Access the current item’s data (n8n v1+) | {{ $input.item.json.status }} |
{{ $('Node Name').item.json.field }} |
Shorthand for accessing a named node’s current item (n8n v1+) | {{ $('Set').item.json.name }} |
{{ $prevNode.name }} |
Name of the immediately previous node | {{ $prevNode.name }} |
{{ $runIndex }} |
Current run index (0-based), useful in loops | {{ $runIndex }} |
{{ $itemIndex }} |
Index of the current item within the batch | {{ $itemIndex }} |
{{ $now }} |
Current date and time as a Luxon DateTime object (UTC) | {{ $now.toISO() }} |
{{ $today }} |
Today’s date at midnight UTC as a Luxon DateTime object | {{ $today.toFormat("yyyy-MM-dd") }} |
{{ $vars.variableName }} |
Access a workflow-level variable set in the Variables panel | {{ $vars.apiBaseUrl }} |
Built-in Variables
| Variable | Type | Description |
|---|---|---|
$json |
object | The current input item’s JSON data. The most commonly used variable in expressions. |
$binary |
object | The current input item’s binary data (files, images, etc.). |
$input |
object | Full input object exposing .item, .items, .first(), .last(), and .all(). |
$input.item |
object | The current item being processed. |
$input.all() |
array | All input items as an array. |
$input.first() |
object | The first input item. |
$input.last() |
object | The last input item. |
$items() |
array | All items from a node — legacy syntax still supported. Prefer $input.all() in v1+. |
$node |
object | Information about the current node (name, type, etc.). |
$prevNode |
object | Previous node’s metadata: .name, .outputIndex, .runIndex. |
$workflow |
object | Workflow metadata: .id, .name, .active. |
$execution |
object | Execution metadata: .id, .mode, .resumeUrl. |
$env |
object | Environment variables configured in n8n instance settings. |
$vars |
object | Workflow-level variables defined in the Variables panel. |
$secrets |
object | Credentials and secrets store — available on self-hosted n8n only. |
$now |
DateTime | Current UTC date and time as a Luxon DateTime object. |
$today |
DateTime | Current date at midnight UTC as a Luxon DateTime object. |
$runIndex |
number | 0-based index of the current execution run (useful in loop nodes). |
$itemIndex |
number | 0-based index of the current item within the batch being processed. |
String Functions
All standard JavaScript string methods are available. The examples below assume $json.value holds the string being operated on.
| Expression | What it does | Example result |
|---|---|---|
.toUpperCase() |
Converts string to uppercase | "hello" → "HELLO" |
.toLowerCase() |
Converts string to lowercase | "HELLO" → "hello" |
.trim() |
Removes leading and trailing whitespace | " hello " → "hello" |
.trimStart() / .trimEnd() |
Removes whitespace from start or end only | " hello " → "hello " |
.includes("text") |
Returns true if the string contains the substring |
"hello world".includes("world") → true |
.startsWith("text") |
Returns true if the string begins with the given value |
"hello".startsWith("he") → true |
.endsWith("text") |
Returns true if the string ends with the given value |
"hello".endsWith("lo") → true |
.replace("old", "new") |
Replaces the first occurrence of a substring | "aabbaa".replace("a", "x") → "xabbaa" |
.replaceAll("old", "new") |
Replaces every occurrence of a substring | "aabbaa".replaceAll("a", "x") → "xxbbxx" |
.split(",") |
Splits string into an array using a delimiter | "a,b,c".split(",") → ["a","b","c"] |
.slice(0, 10) |
Extracts a substring from index start to end (exclusive) | "Hello World".slice(0, 5) → "Hello" |
.substring(start, end) |
Extracts a substring; unlike slice, does not accept negative indices |
"Hello World".substring(6, 11) → "World" |
.padStart(5, "0") |
Pads the start of a string to reach the specified length | "42".padStart(5, "0") → "00042" |
.length |
Number of characters in the string | "hello".length → 5 |
String(value) |
Converts any value to its string representation | String(42) → "42" |
JSON.stringify(obj) |
Serialises an object or array to a JSON string | JSON.stringify({a:1}) → '{"a":1}' |
JSON.parse(str) |
Parses a JSON string into a JavaScript object | JSON.parse('{"a":1}') → {a: 1} |
Number Functions
| Expression | What it does | Example result |
|---|---|---|
parseInt("42") |
Parses a string to an integer, discarding any decimal part | parseInt("42.9") → 42 |
parseFloat("3.14") |
Parses a string to a floating-point number | parseFloat("3.14") → 3.14 |
Number("42") |
Converts a value to a number; returns NaN if conversion fails |
Number("42") → 42 |
.toFixed(2) |
Formats a number to N decimal places, returns a string | (3.14159).toFixed(2) → "3.14" |
Math.round(n) |
Rounds to the nearest integer | Math.round(4.6) → 5 |
Math.floor(n) |
Rounds down to the nearest integer | Math.floor(4.9) → 4 |
Math.ceil(n) |
Rounds up to the nearest integer | Math.ceil(4.1) → 5 |
Math.abs(n) |
Returns the absolute (non-negative) value | Math.abs(-7) → 7 |
Math.max(a, b) |
Returns the largest of the supplied values | Math.max(3, 9) → 9 |
Math.min(a, b) |
Returns the smallest of the supplied values | Math.min(3, 9) → 3 |
Math.random() |
Returns a random floating-point number between 0 (inclusive) and 1 (exclusive) | Math.random() → 0.482... |
isNaN(value) |
Returns true if the value is Not a Number |
isNaN("hello") → true |
Array Functions
| Expression | What it does |
|---|---|
.length |
Returns the number of items in the array |
.join(", ") |
Joins all array elements into a single string with the given separator |
.includes(value) |
Returns true if the array contains the specified value |
.indexOf(value) |
Returns the index of the first occurrence of the value, or -1 if not found |
.map(item => item.name) |
Transforms each item and returns a new array of the transformed values |
.filter(item => item.active) |
Returns a new array containing only items that pass the test condition |
.find(item => item.id === 1) |
Returns the first item that satisfies the condition, or undefined |
.some(item => item.active) |
Returns true if at least one item passes the test condition |
.every(item => item.active) |
Returns true if all items pass the test condition |
.reduce((acc, item) => acc + item.value, 0) |
Aggregates the array to a single value (e.g. sum, concatenation) |
.slice(0, 5) |
Returns the first N items without modifying the original array |
.reverse() |
Reverses the array in place and returns it |
.sort() |
Sorts array elements as strings by default; pass a comparator for numbers |
.flat() |
Flattens one level of nested arrays into a single array |
.concat([...]) |
Merges another array onto the end, returning a new array |
[...arr1, ...arr2] |
Spread syntax to merge two arrays into a new array |
Date and Time (Luxon)
n8n uses the Luxon library for all date and time handling. $now and $today both return Luxon DateTime objects, and DateTime is available globally in expressions for parsing custom formats. All times are UTC unless you apply a timezone offset.
| Expression | What it returns | Example output |
|---|---|---|
$now.toISO() |
ISO 8601 string with milliseconds | "2026-05-11T14:30:00.000Z" |
$now.toFormat("yyyy-MM-dd") |
Formatted date string (ISO date) | "2026-05-11" |
$now.toFormat("dd/MM/yyyy") |
UK date format | "11/05/2026" |
$now.toFormat("HH:mm:ss") |
24-hour time string | "14:30:00" |
$now.toFormat("d MMMM yyyy") |
Long-form date with full month name | "11 May 2026" |
$now.toMillis() |
Unix timestamp in milliseconds | 1747051800000 |
$now.toSeconds() |
Unix timestamp in seconds | 1747051800 |
$now.plus({days: 7}) |
DateTime shifted forward by the given duration | DateTime 7 days from now |
$now.minus({hours: 2}) |
DateTime shifted back by the given duration | DateTime 2 hours ago |
$now.startOf("day") |
Midnight at the start of the current day | "2026-05-11T00:00:00.000Z" |
$now.endOf("month") |
Last millisecond of the current month | "2026-05-31T23:59:59.999Z" |
$now.weekday |
Day of the week as a number (1 = Monday, 7 = Sunday) | 1 |
$now.day |
Day of the month | 11 |
$now.month |
Month number (1–12) | 5 |
$now.year |
Four-digit year | 2026 |
DateTime.fromISO("2026-05-11") |
Parses an ISO 8601 string into a Luxon DateTime | DateTime object |
DateTime.fromMillis(timestamp) |
Parses a Unix millisecond timestamp into a Luxon DateTime | DateTime object |
DateTime.fromFormat("11/05/2026", "dd/MM/yyyy") |
Parses a string in a custom format into a Luxon DateTime | DateTime object |
Conditional Logic
Use JavaScript conditional operators directly inside expressions for inline branching. These are evaluated at runtime per item.
| Pattern | Syntax | Behaviour |
|---|---|---|
| Ternary operator | {{ condition ? "yes" : "no" }} |
Returns the first value if condition is truthy, otherwise the second |
| Nullish coalescing | {{ value ?? "default" }} |
Returns value unless it is null or undefined, then returns the default |
| Logical OR fallback | {{ value || "fallback" }} |
Returns the fallback if value is any falsy value (including 0, "", false) |
| Logical AND guard | {{ value && value.field }} |
Only accesses .field if value is truthy — a safe navigation pattern |
| Optional chaining | {{ value?.field }} |
Returns undefined instead of throwing if value is null or undefined |
| Deep optional chaining | {{ value?.nested?.deep }} |
Safely traverses multiple levels without throwing on any missing intermediate value |
Real-world conditional examples
{{/* Route based on a status field */}}
{{ $json.status === "active" ? "Send email" : "Skip" }}
{{/* Use a fallback when a name field may be absent */}}
{{ $json.name ?? "Unknown" }}
{{/* Safely access a nested field with an email fallback */}}
{{ $json.user?.email || "no-email@example.com" }}
{{/* Combine nullish coalescing with optional chaining */}}
{{ $json.address?.postcode ?? "Postcode not provided" }}
{{/* Nested ternary — use sparingly for readability */}}
{{ $json.score >= 90 ? "High" : $json.score >= 50 ? "Medium" : "Low" }}
Working with Multiple Items
$json always refers to the current item being processed. To access data from a different node, or from a specific position in a batch, use the node-reference patterns below.
| Pattern | Expression | Use case |
|---|---|---|
| Current item field | {{ $json.name }} |
Access any field on the item currently being processed — the most common pattern |
| Named node — current item | {{ $('HTTP Request').item.json.data }} |
Get the paired item from a specific upstream node |
| First item of a node | {{ $('Set').first().json.value }} |
When you always need item index 0, regardless of which item is currently processing |
| Last item of a node | {{ $('Set').last().json.value }} |
When you need the final item from an upstream batch |
| All items — mapped to a field | {{ $('Split Out').all().map(i => i.json.name) }} |
Collect a single field from every item in a node into an array |
| Item by index | {{ $('Split Out').all()[2].json.name }} |
Access a specific item by its zero-based position in the batch |
| Count items in a node | {{ $('Split Out').all().length }} |
Get the total number of items produced by an upstream node |
Useful Real-World Expressions
The following expressions are ready to copy into any n8n field that accepts an expression. Each is self-contained.
Dates and times
{{/* Today's date in UK format */}}
{{ $now.toFormat("dd/MM/yyyy") }}
{{/* ISO timestamp for API payloads */}}
{{ $now.toISO() }}
{{/* Add 30 days to a date field and return ISO string */}}
{{ DateTime.fromISO($json.createdAt).plus({days: 30}).toISO() }}
{{/* Format a stored Unix timestamp as a readable UK date */}}
{{ DateTime.fromMillis($json.timestamp).toFormat("dd/MM/yyyy HH:mm") }}
Strings
{{/* Capitalise the first letter of a string */}}
{{ $json.name.charAt(0).toUpperCase() + $json.name.slice(1) }}
{{/* Truncate long text to 100 characters with ellipsis */}}
{{ $json.description.length > 100 ? $json.description.slice(0, 100) + "..." : $json.description }}
{{/* Build a full name from first and last, skipping empty parts */}}
{{ [$json.firstName, $json.lastName].filter(Boolean).join(" ") }}
{{/* Extract domain from an email address */}}
{{ $json.email.split("@")[1] }}
{{/* Pad a number with leading zeros for invoice or reference numbers */}}
{{ String($json.invoiceNumber).padStart(6, "0") }}
Numbers and currency
{{/* Format a number as GBP currency */}}
{{ "£" + Number($json.amount).toFixed(2) }}
{{/* Calculate a percentage */}}
{{ ((($json.completed / $json.total) * 100)).toFixed(1) + "%" }}
{{/* Clamp a value between a min and max */}}
{{ Math.min(Math.max($json.quantity, 1), 100) }}
Arrays and objects
{{/* Check if an array field is non-empty */}}
{{ Array.isArray($json.items) && $json.items.length > 0 }}
{{/* Sum all price values in a line items array */}}
{{ $json.lineItems.reduce((sum, item) => sum + item.price, 0) }}
{{/* Join an array of tags into a comma-separated string */}}
{{ $json.tags.join(", ") }}
{{/* Get distinct values from an array (deduplicate) */}}
{{ [...new Set($json.categories)] }}
Safety and fallbacks
{{/* Safe email fallback when field may be absent */}}
{{ $json.email ?? "unknown@example.com" }}
{{/* Safely access a deeply nested field */}}
{{ $json.order?.customer?.name ?? "Guest" }}
{{/* Return a value only if it passes a type check */}}
{{ typeof $json.count === "number" ? $json.count : 0 }}
Debugging Expressions
Using the expression editor
Click the = toggle on any field to open the expression editor. The panel renders a live preview of the output below the expression as you type, using the actual input data from the last test run of the previous node. The Input tab on the left shows the full $json object available to that field, which is useful for confirming key names before writing an expression.
Inspecting the full input object
{{/* Dump the entire input as a JSON string to inspect its structure */}}
{{ JSON.stringify($json) }}
{{/* Pretty-print with indentation (useful in a Set node's value field) */}}
{{ JSON.stringify($json, null, 2) }}
Common errors and fixes
| Error | Cause | Fix |
|---|---|---|
Cannot read properties of undefined |
The field or object you are accessing does not exist on the current item | Use optional chaining: {{ $json?.fieldName }} or a nullish fallback: {{ $json.fieldName ?? "default" }} |
Expression Error with no further detail |
Syntax error inside the expression | Check for mismatched brackets, unclosed quotes, missing operators, or trailing commas |
TypeError: .map is not a function |
You are calling an array method on a value that is not an array | Guard with Array.isArray($json.field) ? $json.field.map(...) : [] |
NaN in output |
A numeric operation received a string or undefined value | Parse explicitly with Number($json.value) or parseFloat($json.value) and guard with isNaN() |
Expression returns [object Object] |
An object is being coerced to a string directly | Use JSON.stringify($json.field) or access the specific sub-field you need |
| Date method not found | The date field is a raw string, not a Luxon DateTime object | Parse first: DateTime.fromISO($json.dateField).toFormat("dd/MM/yyyy") |
Related articles: Proxmox Cheat Sheet: CLI Commands for VMs, LXC and Storage, Git Cheat Sheet: Every Command You Need, Linux Commands Cheat Sheet: Home Lab and Server Reference






