n8n Form Node - Tutorial, Examples, Best Practices
📝
Trigger Node

n8n Form Node

Build interactive forms in n8n without coding. Master the Form Trigger and Form nodes for multi-step forms, file uploads, conditional logic, and custom styling.

Every workflow needs input. Forms are how you get it without building a website. The Form node in n8n lets you create professional, multi-step forms that feed directly into your automations. No coding. No external form builders. No complicated integrations.

Need to collect leads? Gather customer feedback? Build an intake process for client requests? Run surveys? The Form node handles it all while giving you complete control over what happens after someone hits submit.

The Form Building Challenge

Most automation platforms force you to use external form tools like Typeform or Google Forms, then connect them via webhooks or Zapier. That means managing multiple services, dealing with API limits, and losing data fidelity during transfers.

n8n’s Form node eliminates this complexity. The form lives inside your workflow. Data flows directly into your automation logic. No middleware. No conversion issues. No subscription costs for yet another tool.

What You’ll Learn

  • The difference between Form Trigger and Form nodes (and when to use each)
  • How to configure all 12 form field types for any use case
  • Building multi-step forms with logic between pages
  • Conditional branching for dynamic form experiences
  • Custom CSS styling to match your brand
  • Pre-filling fields via URL parameters
  • Handling file uploads properly
  • Debugging the most common form issues

When to Use the Form Node

Before diving into configuration, understand when the Form node is the right choice versus other input methods.

ScenarioBest OptionWhy
Collect data from humans via web formForm NodePurpose-built for user input
Receive data from external servicesWebhook NodeAPIs send JSON, not form submissions
Fetch data from APIsHTTP Request NodePull data rather than receive it
Process incoming emailsEmail TriggerDedicated email handling
Manual workflow testingManual TriggerQuick testing without form setup
Scheduled data processingSchedule TriggerNo human input needed

Rule of thumb: If a human needs to enter data through a browser, use the Form node. If a system sends data programmatically, use the Webhook node.

Understanding the Two Form Nodes

n8n provides two nodes for forms, and understanding the difference is critical.

Form Trigger Node

The Form Trigger starts your workflow. It generates a public URL where users access your form, displays the first page of fields, and waits for submissions. Every form workflow begins with a Form Trigger.

What it provides:

  • A unique test URL for development
  • A production URL for live use
  • Form title and description
  • The first page of form fields
  • Custom CSS styling options

Form Node

The Form node adds additional pages to your form. It creates multi-step experiences where users progress through several screens. You can add processing logic between Form nodes to validate data, fetch related information, or make routing decisions.

What it provides:

  • Additional form pages after the trigger
  • Form Ending options (completion screen, redirect, custom HTML)
  • The same field types as Form Trigger
  • Ability to display processed data back to users

How They Work Together

Form Trigger → [Process] → Form → [Process] → Form → Form Ending
     ↓              ↓          ↓          ↓          ↓
   Page 1      Validate     Page 2    Route      Page 3

The Form Trigger always comes first. Form nodes chain after it. Between each Form node, you can insert any processing logic: validation, database lookups, conditional routing, API calls, or data transformation.

Test URL vs Production URL

Like the Webhook node, Form nodes provide two URLs:

AspectTest URLProduction URL
URL path/form-test/.../form/...
When activeOnly while testing in editorOnly when workflow is active
PurposeDevelopment and debuggingLive form collection
Data visibilityShows in editor immediatelyVisible in execution log

Critical: Test URLs stop working when you close the editor. Production URLs only work when the workflow is activated. Using the wrong URL is the most common form debugging issue.

Your First Form

Let’s build a working form from scratch.

Step 1: Add the Form Trigger Node

  1. Create a new workflow in n8n
  2. Click + to add a node
  3. Search for “Form Trigger”
  4. Click to add it as your starting node

Step 2: Configure Basic Settings

With the Form Trigger selected:

  1. Form Title: Enter “Contact Request”
  2. Form Description: Enter “Tell us how we can help”
  3. Form Fields: Add the following fields:
    • Name (Text, required)
    • Email (Email, required)
    • Message (Textarea)

Step 3: Test Your Form

  1. Click “Test step” to open the form
  2. A new browser tab opens with your form
  3. Fill out the fields and submit
  4. Return to n8n to see the submitted data

Step 4: View the Response Data

After submission, the Form Trigger outputs data like:

{
  "submittedAt": "2025-03-15T10:30:00.000Z",
  "formMode": "test",
  "Name": "Jane Smith",
  "Email": "[email protected]",
  "Message": "I'd like to discuss a project"
}

Access this data in subsequent nodes:

  • {{ $json.Name }} returns “Jane Smith”
  • {{ $json.Email }} returns “[email protected]”
  • {{ $json.Message }} returns the message text

For complex expressions, use our expression validator tool to test before running.

Step 5: Activate for Production

  1. Connect additional nodes to process submissions (send email, add to CRM, etc.)
  2. Save the workflow
  3. Toggle the workflow to “Active”
  4. Copy the production URL and share it

Form Field Types

The Form node supports 12 field types covering virtually any data collection need.

Field Types Overview

Field TypeInput FormatBest For
TextSingle lineNames, short answers
TextareaMulti-lineLong responses, descriptions
EmailEmail formatContact emails (with validation)
NumberNumeric onlyQuantities, ages, amounts
PasswordHidden inputSensitive data collection
DateDate pickerAppointments, deadlines
DropdownSelect menuSingle choice from options
CheckboxMultiple selectionMulti-select options
RadioSingle selectionExclusive choices
FileFile uploadDocuments, images
HiddenInvisibleTracking data, metadata
Custom HTMLRendered HTMLInstructions, images, videos

Configuring Each Field Type

Text and Textarea

Basic text input for short or long responses:

{
  "fieldLabel": "Full Name",
  "fieldType": "text",
  "placeholder": "Enter your name",
  "requiredField": true
}
{
  "fieldLabel": "Project Description",
  "fieldType": "textarea",
  "placeholder": "Describe your project in detail",
  "defaultValue": ""
}

Email

Validates email format automatically:

{
  "fieldLabel": "Email Address",
  "fieldType": "email",
  "placeholder": "[email protected]",
  "requiredField": true
}

Number

Accepts only numeric input:

{
  "fieldLabel": "Budget",
  "fieldType": "number",
  "placeholder": "5000"
}

Date

Provides a date picker with format options:

{
  "fieldLabel": "Preferred Date",
  "fieldType": "date",
  "formatDate": "mm/dd/yyyy",
  "requiredField": true
}

Available formats: mm/dd/yyyy, dd/mm/yyyy, yyyy-mm-dd

Dropdown (Single Select)

Single choice from predefined options:

{
  "fieldLabel": "Department",
  "fieldType": "dropdown",
  "fieldOptions": {
    "values": [
      { "option": "Sales" },
      { "option": "Support" },
      { "option": "Engineering" }
    ]
  },
  "defaultValue": "Sales",
  "requiredField": true
}

Dropdown (Multi-Select)

Multiple selections allowed:

{
  "fieldLabel": "Interests",
  "fieldType": "dropdown",
  "multiselect": true,
  "fieldOptions": {
    "values": [
      { "option": "Product Updates" },
      { "option": "Company News" },
      { "option": "Technical Tips" }
    ]
  }
}

Checkboxes

Multiple independent options:

{
  "fieldLabel": "Services Needed",
  "fieldType": "checkbox",
  "fieldOptions": {
    "values": [
      { "option": "Consulting" },
      { "option": "Development" },
      { "option": "Training" }
    ]
  },
  "defaultValue": ["Consulting"]
}

Radio Buttons

Mutually exclusive choices:

{
  "fieldLabel": "Priority",
  "fieldType": "radio",
  "fieldOptions": {
    "values": [
      { "option": "Low" },
      { "option": "Medium" },
      { "option": "High" }
    ]
  }
}

File Upload

Accept file submissions:

{
  "fieldLabel": "Resume",
  "fieldType": "file",
  "multipleFiles": false,
  "acceptFileTypes": ".pdf, .doc, .docx"
}

File data becomes available as binary data for processing with nodes like Google Drive, S3, or Email.

Hidden Fields

Pass data through the form without displaying it:

{
  "fieldLabel": "Campaign Source",
  "fieldType": "hiddenField",
  "fieldValue": "google-ads-spring"
}

Hidden fields are useful for tracking form sources, passing context between pages, or including metadata in submissions.

Custom HTML

Display rich content within your form:

{
  "fieldType": "html",
  "elementName": "instructions",
  "html": "<div style='padding: 10px; background: #f0f0f0;'><strong>Important:</strong> Please complete all sections.</div>"
}

Custom HTML renders in the normal form flow. Note that <script>, <style>, and <input> elements are not supported for security reasons.

Multi-Step Forms

Single-page forms work for simple cases, but complex data collection benefits from multiple steps. Multi-step forms reduce cognitive load, improve completion rates, and allow processing between pages.

Building a Multi-Step Form

  1. Start with a Form Trigger (Page 1)
  2. Add processing nodes if needed
  3. Add a Form node (Page 2)
  4. Repeat for additional pages
  5. End with a Form node using Form Ending

Example: Lead Qualification Wizard

Form Trigger → Edit Fields → Form → Switch → Form → Send Email
   (Contact)     (Validate)   (Company)   (Route)   (Thanks)

Data Persistence Across Steps

All data from previous pages remains accessible throughout the workflow. In page 3, you can still access page 1 data:

{{ $('Form Trigger').item.json.Email }}
{{ $('Form').item.json.CompanySize }}

Processing Between Pages

Between Form nodes, you can:

  • Validate data with an IF node
  • Look up existing records in your database
  • Calculate values based on inputs
  • Fetch related data from APIs
  • Route users down different paths

Example: Lookup existing customer

Form Trigger → HTTP Request → IF → Form (existing) / Form (new)
   (Email)    (CRM lookup)   (exists?)

Form Ending Options

Every form workflow needs an ending. The final Form node provides three options:

Show Completion Screen

Displays a confirmation message to the user:

Page Type: Form Ending
Form Ending: Show Completion Screen
Title: "Thank you!"
Message: "We've received your request and will respond within 24 hours."

Redirect to URL

Sends users to another page after submission:

Page Type: Form Ending
Form Ending: Redirect to URL
URL: "https://yoursite.com/thank-you"

Show Custom HTML/Text

Display fully customized content:

Page Type: Form Ending
Form Ending: Show Text
Text: "<h2>All Done!</h2><p>Your reference number is: {{ $json.referenceId }}</p>"

You can include n8n expressions in custom text to show personalized confirmations.

Branching Logic and Conditional Forms

Dynamic forms adapt based on user responses. n8n supports this through branching workflows.

Mutually Exclusive Branches

When only one path executes based on a condition:

Form Trigger → Switch → Form (Path A) / Form (Path B)

The Switch node evaluates the condition and routes to one branch. Only that branch’s Form Ending displays.

Example: Support Ticket Routing

// Switch node routing logic
if ({{ $json.IssueType }} === "Billing") {
  // Route to billing form
} else if ({{ $json.IssueType }} === "Technical") {
  // Route to technical form
}

Each path collects different follow-up information relevant to the issue type.

Parallel Branches

When multiple branches receive data, n8n executes them sequentially. The last branch’s Form Ending displays.

Important: For forms, mutually exclusive branches (using Switch or IF) provide cleaner user experiences. Parallel execution is better suited for processing workflows, not form display.

Conditional Field Display

Within a single form page, you cannot conditionally show/hide fields based on other answers. This requires multiple pages:

  1. Page 1: Ask the qualifying question
  2. Switch node: Evaluate the answer
  3. Page 2A or 2B: Show relevant follow-up fields

Custom Form Styling

Default n8n forms are functional but generic. Custom CSS lets you match your brand.

Accessing Custom Styling

  1. Select your Form Trigger node
  2. Expand Options
  3. Find Custom Form Styling

The field pre-populates with default CSS. Modify only what you need.

CSS Override Examples

Change primary colors:

:root {
  --color-primary: #6136ff;
  --color-primary-hover: #4d2bcc;
}

Update button styling:

.n8n-form-button {
  background-color: #6136ff;
  border-radius: 8px;
  font-weight: 600;
}

Customize form container:

.n8n-form-container {
  max-width: 600px;
  font-family: 'Inter', sans-serif;
}

Branding Considerations

Keep forms consistent with your website:

  • Use your brand colors for buttons and accents
  • Match font families when possible
  • Maintain consistent border-radius values
  • Test on mobile devices (forms are responsive by default)

For CSS fundamentals, see MDN’s CSS basics guide.

Pre-filling Forms with Query Parameters

Pre-populate fields by adding parameters to your form URL. This is useful for personalized links, tracking campaigns, or reducing friction for known users.

URL Parameter Format

Append parameters to the production URL:

https://your-n8n.com/form/my-form?email=jane%40example.com&name=Jane%20Doe

Important: Query parameters only work with production URLs, not test URLs.

URL Encoding

Special characters must be percent-encoded:

CharacterEncoded
@%40
space%20
&%26
=%3D
+%2B

Dynamic URL Generation

Generate pre-filled URLs dynamically in your workflows:

// In a Code node or expression
const baseUrl = "https://your-n8n.com/form/feedback";
const email = encodeURIComponent($json.customerEmail);
const name = encodeURIComponent($json.customerName);
const formUrl = `${baseUrl}?email=${email}&name=${name}`;

Use Cases

  • Email campaigns: Pre-fill subscriber email from your mailing list
  • UTM tracking: Pass utm_source, utm_medium, utm_campaign via hidden fields
  • CRM integration: Include customer ID for automatic record linking
  • Referral tracking: Pass referrer information through the form

Protecting Forms with Authentication

By default, n8n forms are publicly accessible. Anyone with the URL can submit data. For internal forms or sensitive data collection, add authentication.

Enabling Basic Authentication

  1. Select your Form Trigger node
  2. Set Authentication to “Basic Auth”
  3. Create credentials with username and password

Users must enter credentials before seeing the form. A browser login prompt appears when they access the URL.

When to Use Form Authentication

ScenarioAuthentication?Why
Public contact formNoYou want anyone to reach you
Customer feedbackNoReduce friction for responses
Internal request formYesRestrict to employees
Sensitive data intakeYesProtect confidential submissions
Client portal formsYesVerify identity before access

Authentication Limitations

Basic Auth only: n8n forms support basic authentication, not OAuth or API keys. For advanced access control, consider:

  • Embedding forms behind your own authenticated application
  • Using a Webhook node with custom authentication instead
  • Adding a password field as the first form question (less secure, but no browser prompt)

No per-user tracking: Basic auth validates access but does not identify individual users. If you need to know who submitted the form, add a name or email field.

Self-Hosted URL Configuration

For self-hosted n8n, forms require proper URL configuration to work externally. Set these environment variables:

WEBHOOK_URL=https://your-domain.com
N8N_HOST=your-domain.com
N8N_PROTOCOL=https

Without correct URL configuration, form links may point to localhost or internal addresses that external users cannot access.

Handling File Uploads

File uploads add complexity but open powerful use cases: document collection, image submissions, application attachments.

Configuring File Fields

{
  "fieldLabel": "Upload Documents",
  "fieldType": "file",
  "multipleFiles": true,
  "acceptFileTypes": ".pdf, .doc, .docx, .jpg, .png"
}

Options:

  • multipleFiles: Allow multiple file selection
  • acceptFileTypes: Comma-separated list of allowed extensions

Accessing Uploaded Files

Uploaded files become binary data items. Access them in subsequent nodes:

// Reference binary data
{{ $binary.data }}

// Get file name
{{ $binary.data.fileName }}

// Get MIME type
{{ $binary.data.mimeType }}

Processing Uploaded Files

Common patterns for file handling:

Save to Google Drive:

  1. Add Google Drive node after form
  2. Select “Upload” operation
  3. Map binary data to file input

Attach to Email:

  1. Add Send Email node
  2. Enable attachments
  3. Select binary data from form

Store in Database:

  1. Convert binary to Base64 if needed
  2. Store in blob column or reference external storage

File Size Considerations

n8n has payload limits (default 16MB). For large files:

  • Increase N8N_PAYLOAD_SIZE_MAX on self-hosted instances
  • Consider external upload services (S3 presigned URLs) for very large files
  • Compress files before upload when possible

Common Issues and Solutions

Based on n8n community discussions, these are the problems that trip up most users.

Issue 1: Form Not Appearing

Symptom: Sharing the URL shows an error or blank page.

Causes and fixes:

  1. Using test URL: Switch to the production URL (without -test in the path)
  2. Workflow not active: Toggle the workflow to Active in the top right
  3. URL typo: Copy the exact URL from the node, paths are case-sensitive

Issue 2: Fields Not Pre-filling

Symptom: Query parameters in URL, but fields remain empty.

Causes and fixes:

  1. Using test URL: Query parameters only work on production URLs
  2. Encoding issues: Special characters like @ must be percent-encoded (%40)
  3. Field name mismatch: Parameter names must match field names exactly

Issue 3: Multi-Step Data Missing

Symptom: Can’t access data from previous pages.

Causes and fixes:

  1. Wrong node reference: Use $('Form Trigger') or $('Form') to reference specific nodes
  2. Execution path: Ensure data flows through connected nodes, not parallel paths

Issue 4: Custom Styling Not Applying

Symptom: CSS changes don’t appear on the form.

Causes and fixes:

  1. Cache: Hard refresh the form page (Ctrl+Shift+R)
  2. Specificity: Add more specific selectors if defaults override yours
  3. Syntax errors: Validate CSS syntax before saving

Issue 5: File Uploads Failing

Symptom: Form submits but files are missing.

Causes and fixes:

  1. Size limit: Check payload size limits (16MB default)
  2. Type restriction: Ensure file extension matches acceptFileTypes
  3. Binary handling: Verify subsequent nodes properly handle binary data

For systematic debugging, try our workflow debugger tool.

Real-World Examples

Example 1: Contact Form with Email Notification

Scenario: Collect inquiries and notify your team instantly.

Form Trigger → Send Email → Respond with Confirmation

Form Trigger Configuration:

  • Title: “Contact Us”
  • Fields: Name (text), Email (email), Subject (dropdown), Message (textarea)

Email Node Configuration:

To: [email protected]
Subject: New Contact: {{ $json.Subject }}
Body:
Name: {{ $json.Name }}
Email: {{ $json.Email }}
Message: {{ $json.Message }}

Example 2: Multi-Step Onboarding Wizard

Scenario: Collect client information across multiple focused pages.

Form Trigger → Form → Form → Google Sheets → Form Ending
   (Contact)   (Company)  (Project)  (Save)     (Thanks)

Page 1 (Form Trigger):

  • Name, Email, Phone

Page 2 (Form):

  • Company Name, Industry (dropdown), Company Size (radio)

Page 3 (Form):

  • Project Description (textarea), Budget (dropdown), Timeline (date)

Google Sheets Node:

  • Append row with all collected data

Example 3: Feedback Form with Conditional Questions

Scenario: Show different follow-up questions based on initial rating.

Form Trigger → Switch → Form (Low Rating) / Form (High Rating) → Save
   (Rating)   (Evaluate)

Form Trigger:

  • “How would you rate your experience?” (radio: 1-5)

Switch Logic:

  • If rating is 2 or below: Route to “What can we improve?” form
  • If rating is 4 or above: Route to “What did you love?” form

Example 4: File Request with Google Drive Upload

Scenario: Collect documents and store them automatically.

Form Trigger → Google Drive Upload → Send Confirmation Email
   (File upload)

Form Trigger Configuration:

{
  "fieldLabel": "Document",
  "fieldType": "file",
  "acceptFileTypes": ".pdf, .doc, .docx",
  "multipleFiles": false
}

Google Drive Node:

  • Folder: Submissions/{{ $now.format('yyyy-MM') }}
  • File Name: {{ $json.Name }}_{{ $json.DocumentType }}.pdf

Pro Tips and Best Practices

1. Keep Forms Simple

Every additional field reduces completion rates. Ask only what you need. If you need extensive information, break it into logical multi-step sections.

2. Use Hidden Fields for Tracking

Pass UTM parameters, referral sources, or campaign IDs through hidden fields:

{
  "fieldType": "hiddenField",
  "fieldLabel": "source",
  "fieldValue": "{{ $json.query.utm_source || 'direct' }}"
}

3. Test on Mobile Devices

n8n forms are responsive, but always verify your custom styling works on phones and tablets. Many users complete forms on mobile.

4. Log Submissions During Development

Add a Set node to log raw submissions during testing:

{
  "timestamp": "{{ $now }}",
  "formData": {{ JSON.stringify($json) }},
  "source": "{{ $json.headers?.referer || 'direct' }}"
}

Send to Google Sheets or a database for debugging.

5. Validate Early

Add validation logic immediately after form submission. Catch bad data before it enters your systems:

// Check email domain
if (!$json.Email.includes('@company.com')) {
  throw new Error('Please use your company email');
}

6. Design for Errors

What happens when your form workflow fails? Use the Error Trigger node to catch failures and notify your team. Never leave users hanging.

For comprehensive guidance, see our n8n workflow best practices guide.

When to Get Help

The Form node handles most data collection needs. Some scenarios benefit from expert assistance:

  • Complex conditional logic with many branching paths
  • Integration with legacy systems requiring custom data transformation
  • High-volume forms needing performance optimization
  • Enterprise compliance requirements for data handling

Our workflow development services can build production-ready form systems. For strategic guidance on form automation architecture, explore our consulting packages.

Frequently Asked Questions

What is the difference between Form Trigger and Form node?

Form Trigger:

  • Starts your workflow
  • Displays the first page of fields
  • Provides the URL users visit
  • Required for any form-based workflow

Form Node:

  • Adds additional pages after the trigger
  • Creates multi-step form experiences
  • Provides Form Ending options (completion screen, redirect, custom HTML)

You can have one Form Trigger followed by multiple Form nodes.

How do I create a multi-step form in n8n?

  1. Add a Form Trigger node with your first page of fields
  2. Add a Form node for the second page
  3. Optionally add processing nodes between them (validation, lookups)
  4. Repeat for additional pages
  5. On the final Form node, set Page Type to “Form Ending”

Data access: All pages remain accessible using expressions like $('Form Trigger').item.json.fieldName.

Can I style n8n forms to match my brand?

Yes. In the Form Trigger node:

  1. Expand Options
  2. Find Custom Form Styling
  3. Add CSS to override defaults

Common customizations:

  • Button colors and styling
  • Font families
  • Spacing and container width
  • Border radius

Tip: Use a hard refresh (Ctrl+Shift+R) to bypass cache when testing style changes.

How do I handle file uploads in forms?

Setup:

  1. Add a field with type “file”
  2. Set acceptFileTypes (e.g., “.pdf, .doc, .jpg”)
  3. Enable multipleFiles if needed

Processing:

  • Files become binary data after submission
  • Use Google Drive, S3, or Email nodes to handle them

Limits: Default payload is 16MB. Increase N8N_PAYLOAD_SIZE_MAX on self-hosted instances for larger files.

Why is my form not showing when I share the URL?

Check these in order:

  1. URL type: Test URLs (/form-test/) only work with editor open. Use production URL (/form/).
  2. Workflow status: Toggle must be set to Active (top right).
  3. URL accuracy: Paths are case-sensitive. Copy directly from the node.
  4. Execution log: Check for errors preventing the form from rendering.

Ready to Automate Your Business?

Tell us what you need automated. We'll build it, test it, and deploy it fast.

âś“ 48-72 Hour Turnaround
âś“ Production Ready
âś“ Free Consultation
⚡

Create Your Free Account

Sign up once, use all tools free forever. We require accounts to prevent abuse and keep our tools running for everyone.

or

You're in!

Check your email for next steps.

By signing up, you agree to our Terms of Service and Privacy Policy. No spam, unsubscribe anytime.

🚀

Get Expert Help

Add your email and one of our n8n experts will reach out to help with your automation needs.

or

We'll be in touch!

One of our experts will reach out soon.

By submitting, you agree to our Terms of Service and Privacy Policy. No spam, unsubscribe anytime.