- 動作確認日:2026-10-01
- n8nのバージョン:2.41.3(Docker、セルフホスト)
① 結論:このワークフローでできること
ブログのRSSフィードを読み、まだ通知していない記事だけを、1通のメッセージにまとめてLINEに送ります。
- LINE Notifyは2025年3月にサービスが終わったので、「LINE公式アカウント」のMessaging APIを使います。
- 送った記事のURLをn8nに覚えさせているので、何回実行しても、同じ記事は2回送りません。
- 新しい記事がないときは、LINEには何も送りません。
- 何件あっても1通にまとめるので、無料プランの通数(月200通)を節約できます。
- 動作確認のため、起動にはWebhookを使っています。実際に使うときは、Schedule Triggerで定期的に実行する想定です。
② 完成イメージ

WebhookのURLにGETでアクセスすると、LINEにメッセージが届きます。

届いたメッセージは、次のとおりです(実際の内容です)。
📰 新着記事 3件
【n8nでGoogleカレンダーの今日の予定をDiscordに通知するワークフロー】
10/01 07:16
https://automatelabo.com/2026/10/01/n8n-google-calendar-discord/
【n8nで今日の天気予報をDiscordに通知するワークフロー(APIキー不要)】
10/01 07:16
https://automatelabo.com/2026/10/01/n8n-weather-discord/
【n8nでブログの新着記事をDiscordに通知するワークフロー(重複なし)】
10/01 07:16
https://automatelabo.com/2026/10/01/n8n-rss-discord/
続けてもう一度実行すると、LINEには何も届かず、呼び出し元には次の文章が返ってきました。
| 実行 | 返ってきた文章 | LINE |
|---|---|---|
| 1回目 | 3件をLINEに送りました | 1通届いた |
| 2回目 | 新着記事はありませんでした | 何も届かない |
2回実行したあと、LINEのAPIで確かめた今月の送信数は 1通 でした。
動かしてみて気づいた点が2つあります。
- LINEでは、メッセージの中のURLに、記事のタイトルと画像のプレビューが自動で付きました。3件分のプレビューが、メッセージの下にまとめて表示されています。
- 公式アカウントを友だちに追加したときに、「このアカウントでは、最新情報を定期的に配信していきます」というあいさつが自動で届きました。これは、公式アカウントを作ったときに最初から入っている「あいさつメッセージ」です。LINE Official Account Managerの「あいさつメッセージ」の設定で、変えたり止めたりできます。
実行したときの件数の流れは、次のとおりです。
| ノード | 1回目 | 2回目 |
|---|---|---|
| Webhook | 1 | 1 |
| RSS Read | 10 | 10 |
| Pick New | 1(3件をまとめた1通分) | 1(0件) |
| Has New | 1(true側) | 1(false側) |
| LINE Broadcast(HTTP Request) | 1 | 動かない |
| Respond Sent / Respond None | Respond Sent:1 | Respond None:1 |
③ 使うノードと必要なもの
必要なもの
- n8n(今回はバージョン2.41.3をDockerで動かしました)
- 読み込みたいRSSフィードのURL(今回は
https://automatelabo.com/feed) - LINE公式アカウント(無料で作れます。未認証のままで使えます)と、その「チャネルアクセストークン(長期)」
- 認証情報:Header Auth(
Authorization: Bearer チャネルアクセストークン)
LINE側の準備
今回は、次の順に準備しました。
- https://entry.line.biz/start/jp/ から、LINEアカウントでログインして、通知用の公式アカウントを作る
- LINE Official Account Manager(https://manager.line.biz/ )で、「設定」→「Messaging API」→「Messaging APIを利用する」を押す(プロバイダーは新しく作る。プライバシーポリシーなどのURLは空欄のままで進められました)
- LINE Developersコンソール(https://developers.line.biz/console/ )で、作ったチャネルの「Messaging API設定」タブを開き、一番下の「チャネルアクセストークン(長期)」を発行する
- 同じタブのQRコードをスマホのLINEで読み取り、公式アカウントを友だちに追加する
チャネルアクセストークンを知っている人は、この公式アカウントからメッセージを送れてしまいます。n8nの認証情報(Credentials)に登録しておけば、ワークフローのJSONにトークンが入らないので、JSONを人に渡しても安心です。
送り先について:一斉送信(broadcast)を使った理由
Messaging APIには、主に次の2つの送り方があります。
| 送り方 | エンドポイント | 送り先 | 必要なもの |
|---|---|---|---|
| 一斉送信(broadcast) | /v2/bot/message/broadcast | 友だち全員 | トークンだけ |
| 個別送信(push) | /v2/bot/message/push | 指定した1人 | トークンと、相手のユーザーID(U…) |
今回は、自分だけが友だちになっている通知専用の公式アカウントを作ったので、一斉送信を使いました。ユーザーIDを調べなくて済むぶん、準備が簡単です。
ただし、一斉送信は友だち全員に届きます。ほかの人が友だちに追加すると、その人にも届くので、公式アカウントのQRコードやIDは人に教えないようにしてください。
使うノード
| ノード | 役割 | 設定したこと |
|---|---|---|
| Webhook | 動作確認用の起動ボタン | Path:test-rss-line、Respond:Using 'Respond to Webhook' Node |
| RSS Read | フィードを読み込む | URL:https://automatelabo.com/feed |
| Code(Pick New) | まだ送っていない記事を選び、メッセージの文章を作る | 下のコード |
| If(Has New) | 送る記事があるか確かめる | count が 0 より大きい |
| HTTP Request(LINE Broadcast) | LINEに一斉送信する | 下の表のとおり |
| Respond to Webhook(Respond Sent / Respond None) | 結果を返す | 送ったとき:○件をLINEに送りました、送らなかったとき:新着記事はありませんでした |

Pick Newでは、次の処理をしています。
// まだ送っていない記事だけを選ぶ(送った記事のURLを覚えておく)
const state = $getWorkflowStaticData('global');
const items = $input.all()
.map(i => ({ ...i.json, url: i.json.link.split('?')[0] }))
.sort((a, b) => b.isoDate.localeCompare(a.isoDate));
const sent = state.sentUrls || [];
// 初回は最新3件だけ送り、残りは送ったことにする
const fresh = state.sentUrls ? items.filter(a => !sent.includes(a.url)) : items.slice(0, 3);
state.sentUrls = [...new Set([...items.map(a => a.url), ...sent])].slice(0, 100);
// LINEは太字が使えないので、【】で見出しを目立たせる
const lines = fresh.map(a => {
const date = DateTime.fromISO(a.isoDate).setZone('Asia/Tokyo').toFormat('MM/dd HH:mm');
return `【${a.title}】\n${date}\n${a.url}`;
});
const text = `📰 新着記事 ${fresh.length}件\n\n` + lines.join('\n\n');
return [{ json: { count: fresh.length, text } }];
$getWorkflowStaticData('global')は、実行が終わっても消えない、ワークフロー専用の保存場所です。ここに、送った記事のURLを覚えさせています。- LINEのテキストメッセージは、Discordのような
太字が使えません。そこで、タイトルを【】で囲んで目立たせています。

LINE Broadcastでは、次のように設定しています。
| 項目 | 値 |
|---|---|
| Method | POST |
| URL | https://api.line.me/v2/bot/message/broadcast |
| Authentication | Generic Credential Type → Header Auth(Name:Authorization、Value:Bearer チャネルアクセストークン) |
| Send Body | オン、Body Content Type:JSON、Specify Body:Using JSON |
| JSON | {{ JSON.stringify({ messages: [{ type: 'text', text: $json.text }] }) }} |
送信に成功すると、LINEのAPIからは空の {} が返ってきました。
④ JSON
n8nの公開API(POST /api/v1/workflows)でこのJSONからワークフローを作成し、有効化してから、上の結果を確認しました。
使うときは、次の箇所を自分の環境に合わせて書き換えてください。
YOUR_LINE_CREDENTIAL_ID:n8nに登録したHeader Authの認証情報のID。読み込んだあとに、ノードの画面で認証情報を選び直しても大丈夫です。- RSS ReadのURL:通知したいブログのフィードに変えてください。
{
"name": "test-rss-line",
"nodes": [
{ "parameters": { "path": "test-rss-line", "responseMode": "responseNode", "options": {} },
"id": "b4000000-0001-4000-8000-000000000001", "name": "Webhook", "type": "n8n-nodes-base.webhook", "typeVersion": 2, "position": [0, 0], "webhookId": "b4000000-aaaa-4000-8000-000000000001" },
{ "parameters": { "url": "https://automatelabo.com/feed", "options": {} },
"id": "b4000000-0002-4000-8000-000000000002", "name": "RSS Read", "type": "n8n-nodes-base.rssFeedRead", "typeVersion": 1.2, "position": [220, 0] },
{ "parameters": { "jsCode": "// まだ送っていない記事だけを選ぶ(送った記事のURLを覚えておく)\nconst state = $getWorkflowStaticData('global');\nconst items = $input.all()\n .map(i => ({ ...i.json, url: i.json.link.split('?')[0] }))\n .sort((a, b) => b.isoDate.localeCompare(a.isoDate));\nconst sent = state.sentUrls || [];\n// 初回は最新3件だけ送り、残りは送ったことにする\nconst fresh = state.sentUrls ? items.filter(a => !sent.includes(a.url)) : items.slice(0, 3);\nstate.sentUrls = [...new Set([...items.map(a => a.url), ...sent])].slice(0, 100);\n\n// LINEは太字が使えないので、【】で見出しを目立たせる\nconst lines = fresh.map(a => {\n const date = DateTime.fromISO(a.isoDate).setZone('Asia/Tokyo').toFormat('MM/dd HH:mm');\n return `【${a.title}】\\n${date}\\n${a.url}`;\n});\nconst text = `📰 新着記事 ${fresh.length}件\\n\\n` + lines.join('\\n\\n');\nreturn [{ json: { count: fresh.length, text } }];" },
"id": "b4000000-0003-4000-8000-000000000003", "name": "Pick New", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [440, 0] },
{ "parameters": {
"conditions": {
"options": { "caseSensitive": true, "leftValue": "", "typeValidation": "loose", "version": 2 },
"conditions": [ { "id": "n1", "leftValue": "={{ $json.count }}", "rightValue": 0, "operator": { "type": "number", "operation": "gt" } } ],
"combinator": "and"
},
"looseTypeValidation": true,
"options": {} },
"id": "b4000000-0004-4000-8000-000000000004", "name": "Has New", "type": "n8n-nodes-base.if", "typeVersion": 2.2, "position": [660, 0] },
{ "parameters": {
"method": "POST",
"url": "https://api.line.me/v2/bot/message/broadcast",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify({ messages: [{ type: 'text', text: $json.text }] }) }}",
"options": {} },
"id": "b4000000-0005-4000-8000-000000000005", "name": "LINE Broadcast", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [880, -100],
"credentials": { "httpHeaderAuth": { "id": "YOUR_LINE_CREDENTIAL_ID", "name": "LINE Messaging API token" } } },
{ "parameters": { "respondWith": "text", "responseBody": "={{ $('Pick New').item.json.count }}件をLINEに送りました", "options": {} },
"id": "b4000000-0006-4000-8000-000000000006", "name": "Respond Sent", "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1.1, "position": [1100, -100] },
{ "parameters": { "respondWith": "text", "responseBody": "新着記事はありませんでした", "options": {} },
"id": "b4000000-0007-4000-8000-000000000007", "name": "Respond None", "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1.1, "position": [880, 120] }
],
"connections": {
"Webhook": { "main": [[{ "node": "RSS Read", "type": "main", "index": 0 }]] },
"RSS Read": { "main": [[{ "node": "Pick New", "type": "main", "index": 0 }]] },
"Pick New": { "main": [[{ "node": "Has New", "type": "main", "index": 0 }]] },
"Has New": { "main": [[{ "node": "LINE Broadcast", "type": "main", "index": 0 }], [{ "node": "Respond None", "type": "main", "index": 0 }]] },
"LINE Broadcast": { "main": [[{ "node": "Respond Sent", "type": "main", "index": 0 }]] }
},
"settings": { "executionOrder": "v1" }
}
⑤ つまずきポイントと対処
このワークフロー自体は、1回目の実行でエラーなく動きました。ここでは、LINE側の準備で迷ったことを書きます。
「あなたのユーザーID」が表示されない
- 起きたこと:個別送信(push)に使うユーザーIDを確かめようとしたところ、LINE Developersコンソールの「チャネル基本設定」タブに、「あなたのユーザーID」の欄が出ていませんでした。
- 原因:コンソールに、LINEアカウントではなくメールアドレス(ビジネスアカウント)でログインしていたためと考えられます。ユーザーIDは、LINEアカウントでログインしたときに表示されます。
- 対処:今回は、ユーザーIDのいらない一斉送信(broadcast)に切り替えました。
別の公式アカウントのチャネルを開いてしまう
- 起きたこと:すでにほかの公式アカウントを持っていたので、コンソールで最初に開いたのは、そちらのチャネルでした。
- 対処:通知専用の公式アカウントを新しく作り、そのチャネルでトークンを発行しました。トークンはチャネルごとに違うので、使いたい公式アカウントのチャネルかどうかを、画面上部のチャネル名で確かめてください。
友だちの数が、APIではすぐに増えない
- 起きたこと:送る前に、APIで友だちの数を確かめたところ、前日までの数(0人)しか取れませんでした。
- 対処:友だちの数は、LINE Official Account Managerの画面上部(人のマークの横)で確かめました。自分1人だけであることを確かめてから、一斉送信しました。
⑥ 応用アイデア
どれも、まだ試していないアイデアです。
- Webhookを「Schedule Trigger」に替えて、1時間ごとに新着を確かめる
- 一斉送信を個別送信(push)に替えて、決まった人だけに送る
- 天気予報やカレンダーの予定を、同じ公式アカウントから毎朝送る
- テキストの代わりに「Flex Message」を使って、記事ごとにカード形式で送る
