This n8n expressions cheat sheet lists 70 copy-paste expressions grouped by job: reading data with $json and $('Node name'), text, numbers, dates, arrays and objects, lookups and conditionals. Each one goes between double curly braces in a field switched to Expression. They were checked against n8n's expression reference and the 2.42.6 source, and not executed for this page, so watch the preview under the field before you rely on one.
This n8n expressions cheat sheet gives you 70 copy-paste expressions grouped by the job they do: reading data, text, numbers, dates, arrays and objects, lookups and conditionals. Each one goes between double curly braces in a field switched to Expression, and each uses only functions listed in n8n's expression reference for the current release.
Checked October 2026 against n8n's expression reference, its pages on expressions, referencing previous nodes and dates and times, and the extension functions in the source of n8n 2.42.6, the stable release on 9 October 2026. Nothing here was executed for this page. Where a line shows a result, it is the one printed in n8n's reference.
This is the quick-reference page in our n8n hub. Field and node names such as email and Get orders are placeholders: swap in your own. One thing this page is not: cron syntax for the Schedule Trigger is a different language, covered in our n8n cron expression guide.
- 1Run the previous nodes
The editor previews expressions against real data. Without it you see "Execute previous nodes for preview".
- 2Switch the field to Expression
Hover over the field and change it from Fixed to Expression.
- 3Paste the line
Copy the line with the curly braces. Lines that start with // are labels, not part of the expression.
- 4Swap in your names
Replace the field names, and use the exact node name from your canvas inside $('...').
- 5Read the preview
The result shows under the field. [undefined] or [empty] means the field is not there on this item.
n8n $json syntax: read data from the current item and earlier nodes
$json is the JSON of the item the node is working on, and the docs call it shorthand for $input.item.json. Dots walk down into nested data, square brackets handle awkward names and array positions, and $('Node name') reaches back to any earlier node.
// A field on the current item
{{ $json.email }}
// A field name with spaces or symbols
{{ $json['First Name'] }}
// A nested field, such as a webhook body
{{ $json.body.city }}
// The first element of an array field
{{ $json.items[0].sku }}
// A nested field whose parent may be missing (undefined, not an error)
{{ $json.customer?.email }}
// The linked item from an earlier node
{{ $('Get customer').item.json.email }}
// The first item an earlier node returned
{{ $('Get orders').first().json.id }}
// The last item an earlier node returned
{{ $('Get orders').last().json.id }}
// How many items an earlier node returned
{{ $('Get orders').all().length }}
// The file name of a binary attachment
{{ $('HTTP Request').item.binary.data.fileName }}| Variable | What it reads | Use it when |
|---|---|---|
| $json | The JSON of the current input item. Shorthand for $input.item.json. | The data comes from the node directly before this one |
| $('Node name').item | The item in an earlier node that produced the current item | You need a field from several steps back, item by item |
| $('Node name').first(), .last(), .all() | A fixed item, or every item, of an earlier node | Items were merged or aggregated, or you need a count or a lookup |
| $input.all() | Every input item of the current node | Totals and counts across the incoming items |
| $binary | Binary data of the current item | File names, MIME types and sizes |
| $now, $today | The current moment, and midnight today, as Luxon DateTimes in the workflow's time zone | Any date maths |
| $execution, $workflow, $vars | The run ID and mode, the workflow ID and name, and instance variables | Logs, alerts and configuration |
The older $items() syntax and its replacements are covered with a worked example in our n8n MongoDB guide. For the shape of webhook data (body, headers, query), see the n8n webhook guide.
n8n expressions examples for text and numbers
Text and number functions chain with a dot, left to right. n8n adds its own helpers, such as extractEmail() and round(), on top of plain JavaScript methods, and the editor lists them when you type a dot after a value.
// Clean up an email address
{{ $json.email.trim().toLowerCase() }}
// Title case: "quick a brown FOX" becomes "Quick a Brown Fox"
{{ $json.name.toTitleCase() }}
// Does the text contain a word? Returns true or false
{{ $json.subject.toLowerCase().includes('refund') }}
// Remove every space
{{ $json.phone.replaceAll(' ', '') }}
// Comma list to array: "wind,fire,water" becomes ['wind', 'fire', 'water']
{{ $json.tags.split(',') }}
// The first 100 characters
{{ $json.text.slice(0, 100) }}
// Pull the first email address out of free text
{{ $json.message.extractEmail() }}
// Domain of an email or URL: me@example.com becomes example.com
{{ $json.email.extractDomain() }}
// Strip HTML tags
{{ $json.html.removeTags() }}
// Make text safe to put in a URL
{{ $json.query.urlEncode() }}// Text to number: "123" becomes 123
{{ $json.amount.toNumber() }}
// Round to two decimals: 1.256 becomes 1.26
{{ $json.total.round(2) }}
// A line total
{{ ($json.qty * $json.price).round(2) }}
// A percentage with one decimal
{{ ($json.part / $json.whole * 100).round(1) }}
// Currency: 123456.789 becomes 123.456,79 €
{{ $json.total.format('de-DE', {'style': 'currency', 'currency': 'EUR'}) }}
// The larger of two numbers
{{ $max($json.a, $json.b) }}Two details from the reference. toNumber() throws an error when the text does not start with a valid number, so validate imported data first. And extractEmail(), extractDomain() and extractUrl() return undefined when they find nothing, which is a case for $ifEmpty().
Dates and times
Every date in an n8n expression is a Luxon DateTime. $now is the current moment and $today is midnight at the start of today, both in the workflow's time zone. Dates that arrive from other nodes are text, so convert them with toDateTime() before doing maths.
// Now, as an ISO timestamp
{{ $now.toISO() }}
// Today's date in the form 2026-10-11
{{ $now.toFormat('yyyy-MM-dd') }}
// A readable date and time, such as Apr 30, 2024, 10:00 PM
{{ $now.toLocaleString({'dateStyle':'medium', 'timeStyle':'short'}) }}
// Seven days ago, from midnight today
{{ $today.minus({days: 7}) }}
// Three days from now
{{ $now.plus(3, 'days') }}
// The first moment of this month
{{ $now.startOf('month') }}
// The last moment of this month
{{ $now.endOf('month') }}
// Text to a date you can do maths on (ISO 8601, HTTP, RFC2822, SQL)
{{ $json.createdAt.toDateTime() }}
// A date in your own format, such as 23-06-2019
{{ DateTime.fromFormat($json.date, 'dd-MM-yyyy') }}
// Unix seconds to a date
{{ $json.created.toDateTime('s') }}
// Whole days since a date
{{ $now.diff($json.createdAt.toDateTime(), 'days').days.floor() }}
// The same moment in another time zone
{{ $now.setZone('America/New_York') }}
// Is today a weekday? 1 is Monday and 7 is Sunday
{{ $now.weekday <= 5 }}
// Relative text, such as "in 1 day"
{{ $json.dueDate.toDateTime().toRelative() }}- {{ "Due " + $now }} prints a Unix timestamp, not a date
- {{ new Date($json.date) }} ignores the workflow time zone
- {{ $json.customer.email }} errors when customer is missing
- {{ $('Get orders').item.json.id }} after an Aggregate node
- {{ "Due " + $now.toFormat('yyyy-MM-dd') }}
- {{ $json.date.toDateTime() }}
- {{ $json.customer?.email }}
- {{ $('Get orders').first().json.id }}
Source: n8n dates and item linking docs, checked October 2026
n8n also has its own diffTo() and diffToNow() shortcuts for date differences. The cheat sheet uses Luxon's diff() because its direction is unambiguous: the date on the left minus the date in the brackets. Whichever you use, look at the sign in the preview.
Arrays and objects
An array field takes JavaScript's map, filter and find with arrow functions, plus n8n helpers such as pluck(), sum() and chunk(). Object helpers work on $json itself or on any nested object.
// The number of elements
{{ $json.items.length }}
// One field from every element
{{ $json.items.pluck('name') }}
// Transform every element
{{ $json.items.map(item => item.name.toUpperCase()) }}
// Keep the elements that match
{{ $json.items.filter(item => item.qty > 0) }}
// The first element that matches
{{ $json.items.find(item => item.sku === 'A1') }}
// Add up one field
{{ $json.items.pluck('price').sum() }}
// Array to text
{{ $json.tags.join(', ') }}
// Remove duplicates
{{ $json.tags.unique() }}
// Sort objects by a text field
{{ $json.items.sort((a, b) => a.name.localeCompare(b.name)) }}
// Split into batches of 50
{{ $json.ids.chunk(50) }}
// The field names of the current item
{{ $json.keys() }}
// Does a field exist? Returns true or false
{{ $json.hasField('email') }}
// Drop one field
{{ $json.removeField('password') }}
// The whole item as a JSON string
{{ $json.toJsonString() }}Lookups and workflow data
A lookup is two steps in one line: take every item of another node with .all(), then find the one whose key matches the current item. The rest of this group reads facts about the run itself, which belong in every alert and log line you send.
// Find the matching row in another node's output
{{ $('Price list').all().find(row => row.json.sku === $json.sku)?.json.price }}
// Every value of one field from another node
{{ $('Get users').all().map(row => row.json.email) }}
// Query nested JSON with JMESPath: the first name where age is over 20
{{ $jmespath($json.people, '[?age > `20`].name | [0]') }}
// A workflow variable (needs the Variables feature)
{{ $vars.apiBaseUrl }}
// The ID of this execution
{{ $execution.id }}
// How the run started: test or production
{{ $execution.mode }}
// The name of this workflow
{{ $workflow.name }}
// The position of the current item, starting at 0
{{ $itemIndex }}$vars needs the Variables feature, which the docs list for Cloud Pro and Enterprise and self-hosted Business and Enterprise. One more helper belongs to AI workflows: in a tool node attached to an AI Agent, {{ $fromAI('email', 'The customer email address') }} lets the model supply that parameter.
Conditionals and fallbacks
Most broken expressions are missing a fallback, not a function. JavaScript's ternary and ?? work as they do anywhere, and n8n adds $if() and $ifEmpty(), which treats undefined, null, empty strings, empty arrays and empty objects as empty.
// Pick one of two values
{{ $json.total > 100 ? 'priority' : 'standard' }}
// The same choice with n8n's helper
{{ $if($now.hour < 17, 'Good day', 'Good evening') }}
// A fallback for an empty field
{{ $ifEmpty($json.name, 'there') }}
// A fallback for null or undefined only
{{ $json.nickname ?? $json.firstName }}
// Both conditions must hold
{{ $json.status === 'paid' && $json.total > 0 }}
// The value is one of a list
{{ ['DE', 'AT', 'CH'].includes($json.country) }}
// Is a field empty? Also true for null and undefined
{{ $json.email.isEmpty() }}
// Use a node's data only if that node ran
{{ $if($('Lookup').isExecuted, $('Lookup').first().json.id, '') }}When an expression fails outright, the message tells you which kind of problem it is. Our list of common n8n errors and fixes has the expression errors with their exact text.
n8n expression editor: where expressions go and when to stop using them
Any node field can hold an expression: switch it from Fixed to Expression, then type or drag a value in from the INPUT pane. Text outside the braces stays as text, so Hi {{ $json.firstName }} is a valid field value. The editor's own tip sums it up: anything inside the braces is JavaScript. For more than one statement, the n8n docs wrap the code in a function that calls itself:
{{(()=>{
let end = DateTime.fromISO('2017-03-13');
let start = DateTime.fromISO('2017-02-13');
let diffInMonths = end.diff(start, 'months');
return diffInMonths.toObject();
})()}}That is the ceiling for an expression. Past it, pick a different tool:
The docs recommend the Edit Fields node for exactly that last case: transform the data once, then keep later fields to plain references. If writing these one-liners makes you want to build the whole product in code, our AI SaaS Builder program has no n8n lessons, but it does cover Claude Code and a Next.js and Supabase app from first commit to deployment.
Before you publish a workflow that depends on an expression
- The preview shows a real value, not [undefined] or [empty]
- It still works on an item where the optional fields are missing
- Node names inside $('...') match the canvas exactly; renaming a node changes them
- Dates are converted with toDateTime() before any maths, and formatted before they are joined to text
- References after a Merge, Aggregate or Summarize node use .first(), .last() or .all()
- The expression is short enough to read in the field; longer logic has moved to Edit Fields or a Code node
n8n expressions: FAQ
What is an expression in n8n?
An expression is a small piece of JavaScript inside double curly braces that n8n evaluates when a node runs, so a field gets its value from data instead of fixed text. Switch a field from Fixed to Expression and write something like {{ $json.email }}. Expressions can read the current item, earlier nodes, dates and workflow metadata. Python works in the Code node but not in expressions.
What does $json mean in n8n?
$json is the JSON data of the item the node is processing right now. The n8n docs describe it as shorthand for $input.item.json. Read a field with $json.fieldName, use brackets for names with spaces, such as $json['First Name'], and chain dots for nested data, such as $json.body.city. A node runs its expressions once for each input item, so $json changes with every item.
How do I reference data from a previous node in n8n?
Use $('Node name') with the exact name shown on the canvas. $('Node name').item.json.field reads the item that produced the current one, .first() and .last() read a fixed item, and .all() returns every item, which is what you need for counts and lookups. After a node that combines items, such as Aggregate or Merge, prefer .first() or .all() over .item.
How do I format a date in an n8n expression?
n8n dates are Luxon DateTime objects. {{ $now.toFormat('yyyy-MM-dd') }} prints today as 2026-10-11, and {{ $now.toLocaleString({'dateStyle':'medium'}) }} prints a readable date. For a date that arrives as text, convert it first: {{ $json.createdAt.toDateTime().toFormat('dd LLL yyyy') }}. $now uses the workflow's time zone, which you set in the workflow settings.
How do I open the n8n expression editor?
Hover over a field in a node and switch it from Fixed to Expression. You can type between the double curly braces or drag a value from the INPUT pane, which writes the expression for you. The result appears under the field as you type. The n8n docs recommend expressions where possible because of that immediate preview. Run the previous nodes first so the preview has data.
Can I write multi-line JavaScript in an n8n expression?
Yes. The n8n docs show the pattern: wrap the code in an immediately invoked function expression, {{(()=>{ ... return value; })()}}, and you can declare variables and use several statements. Use it for one calculated field. When the logic touches many items or needs loops, a Code node or the Aggregate and Summarize nodes are the better tools.
Why does my n8n expression show undefined?
The expression ran, and the thing it points at does not exist on the item being previewed. Check the field name, which is case-sensitive, check whether the value sits one level deeper, for example under body on webhook data, and check that the previous node has been executed. Use $json.parent?.child for parents that may be missing and $ifEmpty(value, fallback) to supply a default.
You are already writing JavaScript. Build the whole product with it.
AI SaaS Builder, included in All Access, starts where one-line expressions end: Claude Code, a Next.js and Supabase app, Claude API features, deployment and Stripe billing. It has no n8n lessons. All Access adds the other three programs, live coaching and the private community.
Stuck on one expression?
Post the expression and a sample item in the free Discord, where members untangle n8n data problems, or browse working workflows in our template library.