How to Install Custom npm Packages to Use in n8n Code Nodes

AI Tools, Templates & Resources\\Apr 12, 2025

Yes, even on self-hosted setups like Railway

So this came up again today while I was wrapping up a small feature for the Smart Page Analyzer workflow I’m building for a client with n8n + OpenAI.

A while back, I needed to use cheerio inside an n8n Function node to scrape and clean content from a blog post. The default setup obviously didn’t support it, because n8n doesn’t let you use external packages in function/code nodes out of the box.

Back then, I figured out how to get it working on a self-hosted n8n setup (mine’s running on Railway now). I did that again today and figured I’d document the process properly this time, in case someone’s searching for this and wants a straight answer that actually works.

Why You’d Even Want This

n8n’s built-in Function nodes are great — but kind of limited if you’re trying to do anything more complex like HTML parsing, date formatting, or HTTP chaining inside code.

That’s where external npm packages like:

  • cheerio (for parsing HTML)
  • moment or dayjs (for date/time)
  • axios (for extra HTTP control)
  • lodash (for data cleanup)

…become super useful.

But without adding them manually, you’ll get the classic:

Error: The expression evaluated to a falsy value: a.ok(nodeExists)

Or worse, a full crash because the module isn’t available in your container.

Here’s How I Installed Cheerio for n8n (Clean & Repeatable)

I’m running self-hosted n8n on Railway using Docker

This won’t work on n8n Cloud, but if you’re hosting it yourself — this works reliably.

Step 1: Enable external packages in n8n

In your Railway environment variables, add:

NODE_FUNCTION_ALLOW_EXTERNAL=cheerio

This tells n8n “Hey, I’m allowing this package to be used inside Function nodes.”

You can also comma-separate multiple ones:

NODE_FUNCTION_ALLOW_EXTERNAL=cheerio,moment,axios

Step 2: Modify your Dockerfile

If you deployed n8n using Railway’s template, it doesn’t expose the Dockerfile — so I switched to a custom GitHub repo with this Dockerfile:

FROM n8nio/n8n

# Install external modules
RUN npm install cheerio

You can add any other packages you need here.

Step 3: Deploy from GitHub → Railway

  1. Push your custom Dockerfile to a GitHub repo
  2. Create a new Railway project → Link GitHub
  3. Add the NODE_FUNCTION_ALLOW_EXTERNAL env var again
  4. Done – Railway will build your custom image

Step 4: Use the Package in n8n

Once deployed, open your n8n instance and use cheerio like this in a Function node:

const cheerio = require('cheerio');
const $ = cheerio.load($input.first().json.data);

const text = $('article').text(); // Or any tag you want

return [
  {
    json: {
      cleanText: text
    }
  }
];

It works perfectly and doesn’t require any weird workarounds. This is exactly what I used in my Smart Page Analyzer client workflow.

👇 Here’s the Workflow Example

You can download the JSON here and import it into your n8n instance. Change the variables in the workflow.

It does the following:

  1. Pulls the latest post from your blog’s RSS feed
  2. Fetches the HTML
  3. Uses cheerio to extract clean article text
  4. Sends it to OpenAI for SEO and structure analysis
  5. Pushes the output to Slack

You can modify step 5 to store it in Notion or Google Docs easily.

Quick Tip: Testing Locally First

If you’re running n8n locally with Docker Compose, you can build it with cheerio like this:

FROM n8nio/n8n
RUN npm install cheerio

Run to build the custom image:

docker build -t n8n-custom .

Run to the container from the image we just created

docker run -it --name n8n-custom -p 5678:5678 --env-file .env -v "$(pwd)/n8n_data:/home/node/.n8n" n8n-custom

Works great for local debugging before pushing to production.

Final Thoughts

I’ve had to do this more than once now and with a lot of things going on, its hard to remember everything, I’m glad it’s finally documented to quickly find the steps.

If you’re using n8n as more than a simple Zapier clone, especially for dev-heavy stuff – being able to drop in your favorite npm packages can save you a lot of time.

If this helped or you want to see more of these behind-the-scenes posts, let me know. I’ll share more of the workflows I’ve built that go beyond just “connect this to that.”

Get In Touch

Have a question or just want to say hi? I'd love to hear from you.

Use this form to send me a message, and I aim to respond within 24 hours.

Stay in the loop

Get a weekly update on everything I'm building with AI and automation — no spam, just real stuff.

Goes out once a week. Easy unsubscribe. No fluff.
© 2025All rights reserved
MohitAneja.com