FlowRunbook

Automation runbooks that actually run — every workflow tested, with the file to download.

n8n: fetch an RSS feed on a schedule and save only the new items

Checked 9 November 2026 · n8n 2.46.7 · Node.js 24.22.1 · 10 min read

A workflow that reads a blog's RSS feed every morning and appends the new posts to a file — without adding the same post twice. The deduplication is the whole point: a feed reader that re-saves yesterday's posts is a log file with duplicates. The workflow file below is the exact file that was imported and run for this guide.

What you need

Key result: every morning at 8:00, the workflow fetches the feed and appends only the posts it has not seen before to n8n-posts.csv. In the test run, three scheduled runs in a row left the file at 16 lines — a header plus the same 15 posts, added once.

The workflow at a glance

Node versions in the file: Schedule Trigger 1.4, RSS Read 1.2, Code 2, Edit Fields 3.5, Convert to File 1.2, Read/Write Files 1.1.

Download the workflow: workflow.json — import it into n8n in step 3. It is the exact file that was imported and run for this guide, including the file path used on the test machine (change it in step 4).

1. Install and start n8n

Run n8n from the terminal. n8n Docs, Install with npm describes this as the quick way to try n8n locally: the command downloads what it needs and serves the editor at http://localhost:5678.

Command

npx n8n

Open http://localhost:5678. The first start asks you to create an owner account (an email address and a password, kept on your own machine). Note that npm-based installs are deprecated from n8n 3.0, per the same install page — if you are on 3.0 or later, use the Docker install it links to instead, and re-check the node versions above before importing.

2. Make the file

On a default n8n 2 install, the Read/Write Files node can only write under ~/.n8n-files. That is the default value of N8N_RESTRICT_FILE_ACCESS_TO from n8n 2.0 (n8n Docs, Read/Write Files from Disk). Create the folder and the file with its header row now — the workflow appends data rows only, so the header has to exist first.

Command

mkdir -p ~/.n8n-files
printf 'title,link,pubDate\n' > ~/.n8n-files/n8n-posts.csv

3. Import the workflow

In n8n, open the workflow menu (the ⋯ at the top right of the canvas) and choose Import from file, then pick workflow.json. The canvas shows seven nodes in a line. What each node does:

Config — Keep only new items, JavaScript

// Keep only feed items not seen in an earlier run.
// Seen links live in the workflow's static data, which n8n saves after each run.
const staticData = $getWorkflowStaticData('global');
staticData.seen = staticData.seen || [];
const seen = new Set(staticData.seen);
const fresh = [];
for (const item of $input.all()) {
  const key = item.json.guid || item.json.link;
  if (key && !seen.has(key)) {
    seen.add(key);
    fresh.push(item);
  }
}
staticData.seen = [...seen];
return fresh;

The key is the item's guid, falling back to its link. Static data is the workflow's own small persistent store: the same object in every node of the workflow, saved by n8n after the run. The seen list grows by one entry per new post, so it stays small for a daily feed; for a feed with hundreds of new items a day, store the list in a database instead.

Config — Build CSV lines, JavaScript

const esc = (v) => {
  const s = String(v ?? '');
  return /[",\n]/.test(s) ? '"' + s.replace(/"/g, '""') + '"' : s;
};
const lines = $input.all().map(({ json }) =>
  [json.title, json.link, json.pubDate].map(esc).join(','),
);
return [{ json: { line: lines.join('\n') + '\n' } }];

4. Set the file path

Open the Append to file node and set File Path and Name to the absolute path of the file you made in step 2 — for example /home/alex/.n8n-files/n8n-posts.csv. The downloaded file carries the path used on the test machine (/home/hatch/.n8n-files/n8n-posts.csv); change it to yours. Keep the file under ~/.n8n-files unless you have changed N8N_RESTRICT_FILE_ACCESS_TO, or the write is refused.

5. Activate it

Click Publish. The schedule only fires on a published workflow — the Schedule Trigger docs say so directly (n8n Docs, Schedule Trigger). The first run lands at the next 8:00.

6. Prove the deduplication works

Do not wait a day to find out whether the dedup works. Temporarily change the schedule to run every minute, watch two runs, then set it back:

  1. Open the Every morning node, switch the trigger interval to Custom (Cron), and set the expression to */1 * * * *.
  2. Publish the workflow again and wait about two minutes.
  3. Open the Executions tab. You should see two scheduled runs, both with status success.
  4. Set the expression back to 0 8 * * * and publish again.

In the test run for this guide, three scheduled runs fired at 21:34, 21:35, and 21:36 UTC. The first added 15 posts; the second and third added none. The workflow's stored seen list held 15 entries afterwards.

Trap — manual runs do not deduplicate. If you click Execute workflow in the editor to test, every run re-adds all the items. That is expected, not a bug in the Code node: n8n saves static data only when the published workflow runs from its trigger, not on manual runs. The docs say the same — static data is not available when testing workflows; the workflow must be active and called by a trigger or webhook to save static data. Judge the dedup on scheduled runs only, as in this step.

7. Check the file

Command

cat ~/.n8n-files/n8n-posts.csv

Output (first three rows from the test run)

title,link,pubDate
"Send contracts for e-signature from n8n, with TurboDocx, Slack approval and SharePoint filing",https://blog.n8n.io/spotlight-turbodocx/,"Sun, 08 Nov 2026 14:07:15 GMT"
Throttling vs. rate limiting: Backoff strategies for workflows,https://blog.n8n.io/throttling-vs-rate-limiting/,"Fri, 30 Oct 2026 16:30:34 GMT"
Why we're moving n8n's automation team beyond the service desk model,https://blog.n8n.io/why-were-moving-n8ns-automation-team-beyond-the-service-desk-model/,"Thu, 29 Oct 2026 07:10:00 GMT"

The file held 16 lines after the test: the header plus 15 posts, each once. Titles and dates containing commas are quoted, so the file still parses as CSV. Run wc -l ~/.n8n-files/n8n-posts.csv after the next scheduled run — the count should grow only when the blog publishes something new.

Key result: three scheduled runs, 15 posts saved once, zero duplicates. The first run added 15 rows; the second and third added 0, and the file stayed at 16 lines. Two manual runs before that each re-added all 15 — which is how the manual-run trap above was found.

Traps

Trap — manual runs do not save static data. Covered in step 6: clicking Execute workflow runs the whole workflow, including the file write, but the seen list is not saved. Every manual run looks like the first run. Test the flow manually; test the dedup on the schedule.

Trap — Convert to File's CSV mode is wrong for appending. The first version of this workflow used Convert to File's Convert to CSV operation. Each chunk started with a byte-order mark and had no trailing newline, so rows glued together. Build the lines in a Code node and convert them with Convert to Text File and Add BOM off, as in step 3.

Trap — the header row must already exist. The workflow appends data rows only. If n8n-posts.csv does not exist, the first run creates it without a header, and the file has no column names. Make the file with the header first, as in step 2.

Trap — 8:00 means the instance timezone unless you set one. The Schedule Trigger uses the workflow timezone if set, otherwise the instance timezone, which defaults to America/New_York for self-hosted instances. If the workflow fires at the wrong hour, set the timezone in the workflow settings.

Trap — the seen list never shrinks. Every new post adds one entry to the workflow's static data, and nothing in this workflow removes entries. That is fine for a daily blog feed. If you point this at a high-volume feed, the list grows without bound — switch the store to a database or a file, and keep only the newest hundred keys.

Summary

A Schedule Trigger fires daily at 8:00, RSS Read fetches the feed, a Code node drops every item already in the workflow's static seen list, Edit Fields keeps title, link, and pubDate, a second Code node builds CSV lines, Convert to File turns them into a file, and Read/Write Files appends them. Three scheduled runs saved 15 posts exactly once. The two mistakes that cost time during the build — manual runs re-adding everything because static data is only saved on scheduled runs, and Convert to File's CSV mode adding a byte-order mark with no trailing newline — are both in the traps above, with the working fix in the workflow file.

Sources

Verified 9 November 2026 on n8n 2.46.7 (Node.js 24.22.1) by importing workflow.json, publishing it, and running it on a one-minute schedule: three scheduled executions (21:34, 21:35, 21:36 UTC), all status success. The first added 15 rows to n8n-posts.csv; the second and third added 0; the stored seen list held 15 entries. The feed read was the live https://blog.n8n.io/rss/. The schedule was restored to 0 8 * * * after the test.