>_ * AY AUTOMATE Released— New product for developers & vibe coders— Supercharge your workflow with AY Claude

Free tool

n8n expression tester

Published · Last updated · Checked against docs.n8n.io and the n8n source on November 11, 2026

An n8n expression is JavaScript inside {{ }} that n8n runs to fill a node field, like {{ $json.email }} or {{ $now.toISO() }}. Paste sample data and an expression below to see the result or the error. It runs in your browser and approximates n8n.

Test an n8n expression

The result shows here.

One JSON object, or an array of objects (one per item). n8n's own [{ "json": { } }] shape works too. Copy it from the JSON view of the node before.

Your expression and data stay in this browser tab. They run in a sandboxed Web Worker on your device with network access switched off. Nothing is uploaded or saved. Results are an approximation of n8n, not n8n itself.

n8n expression syntax in one minute

  • Everything between {{ and }} is JavaScript. Outside the braces is plain text (n8n docs).
  • $json is the current item's data. {{ $json.body.city }} and {{ $json['body']['city'] }} read the same field (n8n docs).
  • One {{ }} block with nothing around it keeps its type: a number stays a number, an array stays an array. Text plus blocks always gives one string, and n8n joins the parts the way JavaScript's Array.join('') does, so null and undefined become empty text (n8n source).
  • A block ends at the first }}. To put }} inside code, write \}} (n8n source).
  • In an exported workflow, expression fields start with =, for example "={{ $json.email }}", and n8n strips the = before it runs the rest (n8n source). You can paste them here with the =.
  • Several statements need an immediately invoked function, like the example below (n8n docs).
{{ (() => {
  const first = $json.name.split(' ')[0]
  return first.toUpperCase()
})() }}

Common n8n expressions

Results use the sample data in the tester, first item, time zone UTC. Click an example button above to try most of them.

Common n8n expressions and their results
TaskExpressionResult
Read a field{{ $json.email }}Jane.Doe@Example.com
Read a nested field{{ $json.address.city }}Lyon
Field with a space or dash in its name{{ $json['address']['country'] }}FR
Text around a fieldPlan: {{ $json.plan }}Plan: pro
If / else{{ $json.plan === 'pro' ? 'Paid' : 'Free' }}Paid
If / else with $if(){{ $if($json.seats > 2, 'team', 'solo') }}team
Fallback when empty{{ $ifEmpty($json.nickname, 'there') }}there
Change case{{ $json.name.toTitleCase() }}Jane Doe
Math with rounding{{ ($json.seats * $json.price).round(2) }}78
Format a date field{{ $json.signedUpAt.toDateTime().format('dd LLL yyyy') }}14 Mar 2026
Remove duplicates{{ $json.tags.unique() }}["vip", "beta"]
Join a field from all items{{ $input.all().map(i => i.json.email).join(', ') }}Jane.Doe@Example.com, sam@example.org
Field from another node{{ $("Webhook").item.json.plan }}pro (here: from your sample data)

Dates in n8n expressions

n8n uses Luxon for dates and recommends it over JavaScript's Date, which ignores the workflow time zone (n8n docs). $now is the current moment in the workflow's time zone, and $today is midnight at the start of today (n8n docs). The tester loads Luxon 3.7.2, the version in n8n's package catalog (n8n source).

  • Today as text: {{ $now.toFormat('yyyy-MM-dd') }} or n8n's {{ $now.format('yyyy-MM-dd') }}. Tokens are in the Luxon token table.
  • Date math: {{ $today.plus(7, 'days') }} or Luxon's {{ $now.minus({ hours: 2 }) }}.
  • Text to date: {{ $json.created.toDateTime() }} reads ISO 8601, HTTP, RFC 2822, SQL and Unix milliseconds (n8n docs). For other formats use DateTime.fromFormat($json.created, 'dd/MM/yyyy').
  • Days between two dates: {{ $json.created.toDateTime().diffToNow('days') }}.

Why an n8n expression fails

Invalid syntax

The code inside the braces is not valid JavaScript, for example a trailing dot in {{ $('If').item.json. }} (n8n docs). A list of statements without an IIFE fails the same way.

Can't get data for expression

The expression reads a node that has not run yet. n8n says to test the workflow up to that node first, and you can check with $("Node name").isExecuted (n8n docs). The tester always has data, so it will not show this error.

"this is a function, please add ()"

You wrote a method without calling it, like {{ $json.name.toUpperCase }}. Add the brackets (n8n source).

Empty result or "Cannot read properties of undefined"

A field in the path does not exist on this item, so {{ $json.customer.email }} breaks when customer is missing. Use optional chaining, {{ $json.customer?.email }}, and a fallback with $ifEmpty(). In n8n's source, the legacy engine's error handler only rethrows n8n's own errors, so n8n may show an empty value where the tester shows the JavaScript error (n8n source).

[object Object] in the output

An object sits inside text. Pick one field, or use .toJsonString().

How this tool works

  • Nothing leaves your browser. The expression runs in a Web Worker, a separate thread with no access to the page, its cookies or its storage. Before it runs anything, the worker removes its own network and storage APIs (fetch, XMLHttpRequest, WebSocket, importScripts, IndexedDB and more). There is no server, no account and no API key.
  • The page never runs your code on its main thread. If an answer takes longer than 1.5 seconds, the page kills the worker and starts a new one, so an endless loop cannot freeze the tab.
  • Text is split into {{ }} blocks with the same rules as n8n's splitter. One block keeps its type, text plus blocks becomes a string. A .constructor anywhere is refused, as n8n does (n8n source).
  • Helper functions such as .toTitleCase(), .sum() and .round() are written for this page from n8n's docs and source. The lists below say which ones exist here.

Variables you can use

n8n variables the tester supports
VariableIn this tester
$jsonThe current item from your sample data.
$input.item, .all(), .first(), .last()Built from your sample data.
$("Any node name")Returns your sample data, whatever the name.
$now, $todayLuxon DateTime in the time zone you pick.
DateTime, Duration, IntervalLuxon 3.7.2, the version n8n pins.
$if(), $ifEmpty(), $max(), $min()Same rules as the n8n docs.
$itemIndex, $runIndexItem number you pick, run 0.
$workflow, $execution, $prevNodeFixed example values.
$varsAlways empty.

Not available here: $jmespath, $jmesPath, $env, $secrets, $fromAI, $parameter, $nodeVersion, $response, $request, $pageCount, $getWorkflowStaticData, $evaluateExpression, $items, $item, $node, $binary. The tester tells you why when you use one. See the full list in n8n's expression reference.

Helper functions

n8n helper functions in the tester
TypeWorks hereMissing here
StringisEmpty(), isNotEmpty(), toTitleCase(), toSentenceCase(), toSnakeCase(), toNumber(), toBoolean(), toDateTime(), toJsonString(), parseJson(), extractEmail(), extractDomain(), extractUrl(), extractUrlPath(), isEmail(), isUrl(), isNumeric(), removeTags(), quote(), urlEncode(), urlDecode(), base64Encode(), base64Decode()hash(), isDomain(), removeMarkdown(), replaceSpecialChars()
Arrayfirst(), last(), isEmpty(), isNotEmpty(), sum(), average(), min(), max(), unique(), removeDuplicates(), compact(), chunk(), pluck(), append(), difference(), intersection(), union(), randomItem(), renameKeys(), smartJoin(), toJsonString()mergeIntoObject()
Numberround(), floor(), ceil(), abs(), isEven(), isOdd(), isInteger(), format(), toBoolean(), toDateTime(), isEmpty(), isNotEmpty()none
ObjectisEmpty(), isNotEmpty(), hasField(), keys(), values(), removeField(), removeFieldsContaining(), keepFieldsContaining(), compact(), toJsonString(), urlEncode()merge()
BooleantoNumber(), isEmpty(), isNotEmpty()none
DateTimeAll Luxon DateTime methods, format(), plus(n, unit), minus(n, unit), diffTo(), diffToNow(), isBetween(), extract(), isEmpty(), isNotEmpty()none

Plain JavaScript methods such as split, includes, map, filter and join work as usual.

Limits: this is an approximation

  • It is not n8n. n8n runs expressions in its own engines. On the server the default is a sandboxed V8 isolate from n8n 2.35.0, and the editor uses the legacy engine unless an admin switches it to QuickJS (n8n docs). Error messages and edge cases can differ.
  • $("Any name") returns your sample data. There are no other nodes, no paired-item tracking and no runs other than run 0.
  • n8n blocks more JavaScript for security than this page checks, such as some property names. An expression that works here can still be refused by n8n.
  • .toTitleCase() capitalizes every word. n8n uses a title-case library that keeps small words such as "of" in lowercase.
  • n8n also runs date helpers on text that looks like a date, such as "2026-01-01".format(...) (n8n source). Here, call .toDateTime() first.
  • $workflow and $execution hold fixed example values, and $vars is empty.

More free n8n tools and templates

Want someone to build, review and run your n8n workflows? AY Automate builds and looks after n8n automations.

n8n expression FAQ

What is an n8n expression?

An n8n expression is a small piece of JavaScript inside {{ }} that you put in a node field. n8n runs it for each item and puts the result in the field. For example {{ $json.body.city }} reads the city from a webhook body. n8n's docs describe expressions as JavaScript-like code that sets parameter values from previous nodes, workflow metadata or environment variables.

How do I test an n8n expression without running the workflow?

Paste sample input data and the expression into the tester on this page. It shows the result, its type, and any error as you type. Inside n8n, an expression field also shows a preview of the computed value, which n8n's docs give as a reason to use expressions where you can.

How do I write an if / else in an n8n expression?

Use the JavaScript ternary operator: {{ $json.plan === 'pro' ? 'Paid' : 'Free' }}. n8n also has $if(condition, valueIfTrue, valueIfFalse), which does the same thing. For more than two outcomes, nest them or move the logic to an If or Switch node.

How do I format a date in an n8n expression?

n8n uses the Luxon library for dates. {{ $now.toFormat('yyyy-MM-dd') }} gives today's date, and n8n's own .format() helper does the same. To turn a text field into a date first, use .toDateTime(), for example {{ $json.created.toDateTime().format('dd LLL yyyy') }}. $now uses the workflow's time zone.

How do I get data from another node in an expression?

Use $("Node name"), for example {{ $("Webhook").item.json.body.email }}. .item gives the matching item, the one used to produce the current item, and .first(), .last() and .all() give the first, last or all items. The node has to run before the node that uses the expression.

Why does my n8n expression show [object Object]?

You put an object inside text. When an expression mixes text and {{ }} blocks, n8n joins the parts into one string, and an object turns into [object Object]. Pick a field such as {{ $json.address.city }}, or turn the object into JSON with {{ $json.address.toJsonString() }}.

Can an n8n expression have several lines of code?

Yes, if you wrap the code in an immediately invoked function: {{ (() => { const first = $json.name.split(' ')[0]; return first.toUpperCase() })() }}. A plain list of statements is a syntax error. For longer logic, n8n's docs suggest the Code node.

Is the result here the same as in n8n?

Not always. This page copies n8n's rules for {{ }} blocks, uses the same Luxon version and a subset of n8n's helper functions, but it is not n8n. It has no workflow, no paired items and no access to your instance, and some helpers are missing. Treat it as an approximation and check the final expression in n8n.

Sources

All checked November 11, 2026. n8n source links point to commit 2fdca26 (n8n-workflow 2.48.0).