Reference for the n8n IF node -- conditional branching with string, number, boolean, and date comparisons.
The IF node splits a workflow into two branches based on a condition. Items that match the condition flow to the True output; items that do not match flow to the False output. It is the primary tool for conditional logic in n8n.
| Branch | Description |
|---|---|
| True | Items that satisfy all conditions (AND mode) or at least one condition (OR mode). |
| False | Items that do not satisfy the conditions. |
Each branch can connect to different downstream nodes, allowing the workflow to take different actions depending on the data.
| Type | Available Operators |
|---|---|
| String | equals, not equals, contains, does not contain, starts with, ends with, regex match, is empty, is not empty |
| Number | equals, not equals, greater than, less than, greater than or equal, less than or equal, is empty, is not empty |
| Boolean | is true, is false, is empty, is not empty |
| Date & Time | is after, is before, is empty, is not empty |
You can add multiple conditions and combine them with AND or OR logic:
| Combine Mode | Behavior |
|---|---|
| AND | All conditions must be true for an item to go to the True branch. |
| OR | At least one condition must be true for an item to go to the True branch. |
Tip
For complex logic that mixes AND and OR, chain multiple IF nodes in sequence or use the Code node with a custom boolean expression.
| Parameter | Description |
|---|---|
| Conditions | One or more conditions to evaluate against each input item. |
| Combine | How multiple conditions are combined: AND or OR. |
| Value 1 | The left side of the comparison. Usually an expression referencing input data (e.g., {{ $json.status }}). |
| Operation | The comparison operator (equals, contains, greater than, etc.). |
| Value 2 | The right side of the comparison. Can be a static value or an expression. |
For conditions that go beyond the built-in operators, use an expression that returns a boolean:
{{ $json.tags.includes('urgent') && $json.priority > 3 }}
Set the condition type to Boolean and the operator to is true. Put the expression in the Value 1 field.
Note
Expression-based conditions give you the full power of JavaScript inside the IF node without needing a separate Code node.
Route items by status:
Webhook --> IF (status equals "paid") --> True: Send Invoice / False: Send Reminder
Check a field value and send items down different paths. The True branch handles one case, the False branch handles the other.
Null and empty checks:
HTTP Request --> IF (email is not empty) --> True: Send Email / False: Log Error
Before using a field, verify it exists and is not empty. This prevents downstream nodes from failing on missing data.
Numeric threshold:
Schedule Trigger --> PostgreSQL (count) --> IF (count > 100) --> True: Alert / False: No Action
Compare a numeric value against a threshold to decide whether to trigger an alert.
String pattern matching:
Email Trigger --> IF (subject contains "URGENT") --> True: Slack Alert / False: Normal Processing
Use the contains operator to match partial strings without needing a regex.
Regex matching:
Use the regex match operator for complex pattern matching:
{{ $json.email }}^[a-zA-Z0-9._%+-]+@company\.com$This routes only emails matching the company domain to the True branch.
Warning: Type mismatches cause unexpected results
If a field contains the string
"42"and you compare it as a Number greater than10, the comparison may fail or behave unexpectedly. Use theNumber()function in an expression to cast strings to numbers:{{ Number($json.count) }}.
is empty operator catches both null and "". If you need to distinguish between them, use an expression: {{ $json.field === null }}..toLowerCase(): {{ $json.status.toLowerCase() }} equals active.undefined. The is empty operator treats undefined as empty. Other operators may produce unexpected results. Always check for existence first when the field may not be present.All items go to the False branch even when the condition appears correct.
The most common cause is a type mismatch. If the field contains the string "42" and you compare it as a Number greater than 10, the comparison may fail. Cast the value explicitly using {{ Number($json.count) }}. Also check for case sensitivity in string comparisons -- use .toLowerCase() to normalize.
TypeError: Cannot read properties of undefined in the condition expression.
The field you are referencing does not exist on the current item. This happens when upstream data is inconsistent or when a previous node returned fewer fields than expected. Add a null check using the is not empty operator first, or use optional chaining in expressions: {{ $json.field?.subfield }}.
Items are not splitting correctly between True and False branches. Verify the Combine mode (AND vs. OR) matches your intent. With AND, all conditions must be true. With OR, any single condition being true sends the item to True. If you have complex mixed logic, consider chaining multiple IF nodes or using a Code node with a custom boolean expression.
I build production n8n and Cloudflare automation for teams — the same engineering behind HarperFlow. Fixed-price, escrow-protected, US-based.