n8n Code Node: Write JavaScript Inside Your Workflow
```html
Most n8n workflows fall apart at the same spot. You've chained together five nodes with no code at all, and then you hit a step that needs a small piece of logic no built in node covers. That's what the n8n code node javascript feature is for. It lets you drop real JavaScript into the middle of your workflow instead of bolting on three extra nodes to fake it.
What the Code Node Actually Does
The code node gives you a plain JavaScript sandbox with access to the items coming into that step. You write a function, return an array of items, and the workflow keeps moving. No separate service, no webhook back to your own server, no extra hosting bill. It runs right there in n8n.
When you add a code node to your workflow, n8n exposes the incoming data as an items array. Each item is an object with a json property that holds your actual data. Your job is to transform it and hand back an array of items in the same shape. The n8n runtime handles the rest.
Where I Actually Use It
In practice I reach for the code node javascript step for a handful of jobs:
- Cleaning and normalizing messy data from a form or a scraped page
- Building a custom payload shape for an API that doesn't match n8n's default format
- Doing math or date logic that would take four separate nodes otherwise
- Filtering or deduplicating arrays before they hit the next step
None of these are exotic. They're the boring plumbing every workflow needs, and JavaScript does it in five lines instead of five nodes.
A Real Example: Phone Number Normalization
Let me walk you through something I actually do all the time. A client sends in a form with phone numbers in every format you can imagine. Some have dashes, some have parentheses, some have country codes, most have none. Before it hits Twilio, I need them all in the same shape: plus sign, country code, and ten digits. No extra characters.
Here's the code node I'd write:
return items.map(item => {
const phone = item.json.phone_number.replace(/\D/g, '');
const normalized = '+1' + phone.slice(-10);
item.json.normalized_phone = normalized;
return item;
});
That's it. One code node handles what would otherwise be an Extract, a Replace, a Slice, and a Set Field node. The workflow stays readable because I'm not burying that logic in four separate steps. When someone asks why phone numbers look weird, I have one place to check.
The Mistake I See Most Often
People try to make the code node do too much. It should hold logic, not architecture. If you're writing forty lines with three nested API calls inside one code node, that's not a shortcut anymore, it's a workflow hiding inside a workflow. When that happens, break it back into real nodes so you can see what's failing when something breaks at 2am.
The second mistake is writing code without thinking about what happens when an item fails. If your code node doesn't handle an edge case and someone passes in a null value or a string instead of a number, the whole workflow stops. Use try-catch blocks. Check types. Don't assume the data is clean just because it usually is.
How to Structure a Code Node That Won't Bite You Later
Here's my formula for a code node that stays maintainable:
Start with a guard clause. Check that the data you expect is actually there:
return items.map(item => {
if (!item.json.email) {
item.json.error = 'Missing email address';
return item;
}
// rest of your logic here
});
Do one transformation per code node. If you need to normalize the phone, build the payload, and filter the results, that's three code nodes, not one. It costs you nothing and saves you everything when you need to debug.
Leave a comment that explains the why. Not what the code does, that's obvious. Why does this step exist? Is it working around a bug in the upstream API? Is it a business rule from the client? Write that down in one line.
Test the edge cases in the n8n test mode. Add a test input that has a missing field, a number as a string, an empty array, something that will break it. Fix those breaks now, not in production.
The Esipick Take
We build a lot of client automations on n8n at Esipick, and the code node is where half our real debugging time goes. Not because it's unreliable, but because it's the one place clients can't see what's happening without opening the code. My rule now is simple: if a code node is doing something a non technical teammate would need to understand later, I leave a one line comment above it explaining the why, not the what. That single habit has saved us more support tickets than any amount of clever JavaScript ever has.
I've also learned to add a console log statement during testing and then remove it before the workflow goes live. That thirty-second habit has caught so many logic errors before they hit real data.
A Few Practical Tips
- Use Run Once for Each Item mode when you're transforming one record at a time, it keeps the logic simpler to read
- Console log during testing, then strip it out before you ship the workflow
- Keep one code node per job. Two small nodes beat one node doing two things
- Set a timeout on your code node if it's calling external services. n8n will hang forever if you don't.
- Remember that the code node sees ALL items coming in, not just one. Use map if you're transforming each one, not filter unless you're actually reducing the set
The code node won't replace good workflow design, but it fills the gap between what n8n's nodes cover and what your business actually needs. Once you're comfortable writing a few lines of JavaScript in there, you'll stop reaching for workarounds and start building workflows that just do the thing.
FAQ
Q: What happens if my code node throws an error?
A: The entire workflow execution stops and marks that run as failed. That's why wrapping risky logic in try-catch is not optional. If you're doing something that might fail, like parsing JSON or calling an external API, catch that error and handle it gracefully. Log it, pass it downstream, whatever makes sense for your workflow. Just don't let it crash the whole thing.
Q: Can I call external APIs or webhooks from inside a code node?
A: You can, but you shouldn't. Use the HTTP node for that instead. The code node is for logic, not I/O. If you need to call an external service, you're already at the point where breaking it into a separate node makes your workflow clearer and easier to debug. Plus, the HTTP node has built-in retries and error handling that you'd have to write yourself in a code node.
Q: How do I know if my code node is too big?
A: If you can't read it on one screen without scrolling, or if it's doing more than one conceptual job, it's too big. Split it up. I've never regretted breaking a code node into two smaller nodes. I've regretted plenty the other way.
Want this automated for your business?
I build n8n workflows, WhatsApp automations, and AI pipelines — starting from $300. Most go live in under a week.
Get a Free Audit →