Migrate from Zapier to n8n: map, rebuild, run in parallel

There's no import button that turns Zaps into n8n workflows. A migration is a rebuild, and that's a good thing, because it's a chance to merge duplicate Zaps and drop the ones nobody uses. This guide covers the method:

author
Zahara Schaefer
published
updated
read
7 min
tested
n8n 2.x (node names from the n8n docs). Zapier feature names as of late 2026; check your plan's UI.
outline {
  1. What you need
  2. 1. List every Zap
  3. 2. Learn the mapping
  4. 3. Rebuild the first workflow
  5. 4. Run both side by side
  6. 5. Cut over, with a way back
  7. 6. Repeat, then retire Zapier
  8. Troubleshooting
  9. References
  • list everything;
  • translate each Zapier feature to its n8n equivalent;
  • rebuild;
  • run both side by side;
  • switch over with a way back.

If you haven't decided yet, read Should you switch to n8n? first. You'll also need a running n8n instance: Self-host n8n covers that.

What you need

  • Admin access to your Zapier account.
  • A production n8n instance with HTTPS and a public URL, so apps can reach its webhooks.
  • A spreadsheet for the inventory.
  • Test accounts or test records in the apps you connect, where you can get them.

Step 1: List every Zap

In Zapier, go through each Zap and add a row to your spreadsheet:

Zap nameOn?Trigger app and eventSteps (in order)Filters or PathsRuns per monthOwnerKeep, merge or drop

Get run counts from Zap history. While you're there, sort out the obvious:

  • Zaps that are off, or haven't run in months: drop.
  • Several Zaps with the same trigger: merge into one n8n workflow with a Switch node.
  • Zaps that touch money, customers or legal records: mark them high risk, and migrate them last.

Check it worked: every Zap has a row and a decision, and you know which three to migrate first (frequent, low risk, simple).

Step 2: Learn the mapping

Most Zapier building blocks have a direct n8n equivalent:

Zapiern8nNotes
Trigger (app event)App trigger node, or WebhookPrefer webhooks where the app supports them. Polling triggers check on a schedule.
ActionApp node, or HTTP RequestHTTP Request covers any app with an API.
Filter by ZapierFilter or IfFilter drops items. If splits them into true and false branches.
Paths by ZapierSwitchOne output per rule, plus an optional fallback output.
Formatter by ZapierEdit Fields (Set), Date & Time, or CodeExpressions handle most text and number formatting inline.
Delay by ZapierWaitWait for a set time, until a date, or until a webhook call.
Webhooks by ZapierWebhook and Respond to Webhook
Looping by ZapierBuilt in, or Loop Over ItemsMost n8n nodes already run once per item.
Storage by ZapierA database node, or Data tables where availablePostgres, Google Sheets, or n8n's built-in data tables, depending on version.
Schedule by ZapierSchedule TriggerCron syntax is supported.
Sub-ZapExecute WorkflowCalled workflow starts with the Execute Workflow Trigger.
Zap error notificationsError Trigger workflowSee Make n8n workflows reliable.

The biggest shift is items. A Zapier trigger that returns 10 rows usually runs the Zap 10 times. An n8n trigger can pass 10 items into one execution, and each following node processes all 10. That's why you rarely need a loop node in n8n.

Check it worked: for each of your first three Zaps, write the n8n node for every step next to the Zapier step in your spreadsheet.

Step 3: Rebuild the first workflow

Take your first Zap, for example "New form entry > create CRM contact > post to Slack".

  1. Create credentials in n8n for each app. Self-hosted n8n sometimes needs your own OAuth app with the provider. The node's docs page explains how.
  2. Add the trigger. If the form tool supports webhooks, add a Webhook node, set it to POST, and copy its Test URL.
  3. Point the source app at the test URL, then click Listen for test event and submit a test entry. The data appears in the node's output.
  4. Add the steps. Map fields by dragging them from the input panel. A typical expression:
text
{{ $json.body.email.trim().toLowerCase() }}

That replaces a Formatter step: expressions accept JavaScript, so most small transformations happen inline.

  1. Recreate filters and paths. A Zapier filter "Only continue if Country is US" becomes a Filter node with the condition {{ $json.body.country }} *is equal to* US.
  2. Add error handling. Turn on Retry On Fail for the CRM and Slack nodes, and set the workflow's error workflow.

Check it worked: a test entry produces the same CRM record and Slack message as the Zap does.

Step 4: Run both side by side

Don't switch off the Zap yet. For a week or two, run both:

  • Keep the Zap live. It still does the real work.
  • Activate the n8n workflow in shadow mode. Point its final "write" steps at a test destination: a test Slack channel, a sandbox CRM, or a Google Sheet that logs what it would have done.
  • Send the same events to both. Many apps allow more than one webhook URL. If yours allows only one, put the n8n workflow on a schedule that reads the same source instead, or have the Zap forward the payload to n8n with a Webhooks by Zapier action.

At the end of each day, compare the outputs. Count runs on both sides, and check a few records field by field.

Check it worked: a full day, or several, where every event the Zap handled also shows up correctly in n8n's test destination.

Step 5: Cut over, with a way back

When the outputs match:

  1. Pick a quiet time.
  2. Switch the n8n workflow's write steps from the test destinations to the real ones.
  3. Point the source app's webhook at n8n's Production URL (the one with /webhook/, not /webhook-test/).
  4. Turn the Zap off, but don't delete it.
  5. Watch n8n's Executions for the first few hours.

To roll back: turn the Zap back on and point the webhook back at Zapier. Write these two steps down before you start, so anyone can do them.

Keep the old Zap switched off, but in place, for a few weeks, until you're sure nothing depends on it. Then delete it and mark it done in your spreadsheet.

Check it worked: the first real events go through n8n, and the Zap's history shows no new runs.

Step 6: Repeat, then retire Zapier

Work down your list: low-risk Zaps first, high-risk ones last, each with its own parallel run. When the last Zap is off and its notice period has passed, downgrade or cancel the plan. Check your billing cycle first, so you don't pay for a month you won't use.

Troubleshooting

ProblemLikely causeFix
The workflow runs once, but the Zap ran several timesn8n processed all items in one executionExpected. Check the item count in the output, not the execution count.
Fields are empty in n8n but filled in ZapierDifferent field paths. Webhook data sits under bodyLook at the real input data and fix the expression path.
The source app rejects the webhook URLThe URL isn't public HTTPSUse your production domain, not localhost.
OAuth credential fails on self-hosted n8nMissing redirect URL at the providerAdd the redirect URL shown in the n8n credential dialog to your OAuth app.
Duplicate records after cutoverBoth the Zap and n8n ranMake sure the Zap is off, and add the duplicate check from the reliability guide.

References