n8n-binary-and-data について
n8n のワークフロー構築者向けに、`$json` と `$binary` の役割の違いや、AI エージェントのツール境界をバイナリが通過できない理由を説明するスキルです。ファイルの保持、ストレージキーや URL による受け渡し、チャットでの画像表示の方法を扱います。
主な機能
- 01`$json` と `$binary` の区別
- 02バイナリデータの読み書き
- 03変換時のファイル消失防止
- 04ストレージ経由のエージェント連携
- 05URL によるチャット画像表示
活用シーン
- 01ダウンロード先フィールドの調査
- 02データ変換後の添付ファイル保持
- 03アップロードファイルのツール処理
- 04生成画像のチャット表示
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ czlonkowski/ n8n-skills --skill n8n-binary-and-dataインストール後、Claude Code で/n8n-binary-and-dataを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
AGENT_TOOL_BINARY.mdBINARY_BASICS.mdCDN_REQUIREMENT.mdMERGE_FOR_CONTEXT.mdREADME.md詳細
n8n のバイナリデータとデータ
n8n の各アイテムには、構造化データ用の $json とファイルのバイトデータ用の $binary という、独立した2つの領域があります。この2つはワークフロー内を並行して流れます。ファイルの内容、つまり実際の PDF、画像、zip は $binary に格納され、$json には格納されません。この区別を誤ると、空のフィールドを読み込んだり、フローの途中でファイルを失ったり、AI エージェントに使用できないツール入力を渡したりすることになります。
このスキルでは、バイナリデータの格納場所、読み書きの方法、気付かないうちに削除されないようにする方法、バイナリデータと AI エージェントのツール境界の厳格な分離、そしてチャット画面で生のバイトデータではなく URL が必要な理由を説明します。
バイナリデータのバグの90%を防ぐ3つのルール
-
ファイルの内容は
$jsonではなく$binaryにあります。 HTTP ダウンロード、「Read Files」、またはメール添付ファイルのトリガーの後、バイトデータは$binary.<key>に格納されます。$jsonに格納されるのは、あってもメタデータだけです。ファイルの内容を取得するために$json.dataを読み込んでも、何も得られません。 -
バイナリデータは、どちらの方向にも AI エージェントのツール境界を越えられません。 ツールの引数と戻り値は JSON のみです。アップロードされた画像をファイルとしてツールに渡すことはできず、ツールから生のバイトデータを返すこともできません。ストレージに事前に保存し、代わりにキーまたは URL を JSON 経由で渡してください。
AGENT_TOOL_BINARY.mdを参照してください。 -
チャット画面では、画像は
$binaryではなく URL で表示されます。 Slack、Discord、Teams、Telegram、埋め込み型の Webhook チャットはいずれも、バイナリ領域を読み取りません。画像は URL から取得できる場所に保存する必要があります。CDN_REQUIREMENT.mdを参照してください。
2つの領域
各アイテムは次のような構造です。
{
"json": { "customerId": 42, "status": "sent" },
"binary": {
"invoice": {
"data": "<base64-encoded bytes>",
"mimeType": "application/pdf",
"fileName": "invoice-42.pdf",
"fileExtension": "pdf"
}
}
}
binary 内のキー(ここでは invoice)がバイナリプロパティ名です。ほとんどのファイル処理ノードには、その名前を指定する binaryPropertyName パラメーターがあります。生成側が領域に名前を付け、処理側がその名前で参照します。ほとんどのノードでは既定のキーが data なので、別の指定がなければ $binary.data と考えてください。
$json と $binary は別々の名前空間です。{{ $binary.invoice.fileName }} のような式はファイルのメタデータを読み込み、{{ $json.customerId }} はデータを読み込みます。この2つが混ざることはありません。
この区別は、Webhook に関する注意点も説明しています。multipart/form-data を受信した Webhook トリガーでは、アップロードされたファイルは $binary に、付随するフォームフィールドは $json.body に格納されます。つまり、アップロードされたファイルは $json の下にはありません。(Webhook の $json.body というネスト構造は n8n-expression-syntax の領域です。)
領域の構造、MIME タイプ、サイズ制限の詳細については BINARY_BASICS.md を参照してください。
バイナリデータの生成
$binary の領域を手動で作成することはほとんどありません。ノードが自動で設定します。
| 入力元 | バイナリデータの格納方法 |
|---|---|
responseFormat: "file" を指定した HTTP Request | レスポンス本文が $binary.data(または指定した名前)に格納されます |
| Read/Write Files from Disk | 読み込んだファイルの内容が $binary に格納されます |
| ストレージからのダウンロード(S3、Google Drive、Dropbox など) | ダウンロードしたファイルが $binary.<key> に格納されます |
| 添付ファイル付きのメールトリガー | 各添付ファイルが $binary に格納されます |
| プロバイダーの AI メディアノード(画像/音声の生成) | options.binaryPropertyOutput を設定して、後続ノードが参照する場所にバイトデータを格納します |
HTTP でダウンロードする場合、重要なのは responseFormat の1つのフィールドです。nodes-base.httpRequest に対して get_node を実行して確認してください。既定の JSON/文字列形式のままにしておくと、ダウンロードしたファイルが $binary にきれいなバイトデータとしてではなく、$json に文字化けしたテキストとして格納されるのが典型的な原因です。
Code ノードでのバイナリの読み書き
ほとんどのワークフローでは、バイト列を直接扱う必要はありません。メールの添付ファイル、ファイルのアップロード、Slack のファイルなど、通常はそのまま利用先に渡します。多くのバイト処理には、ネイティブノードがあります。Extract From File(CSV、XLSX、PDF のテキスト、JSON、プレーンテキスト → アイテムまたはフィールド)、Convert To File(アイテム → CSV/XLSX/JSON/テキストファイル)、Crypto(binaryData: true でファイルをハッシュ化)、Compression(zip/gzip)です。対応するノードがない形式の場合に限り、Code ノードで生のバイト列を読み書きし、「Why Code:」の注記を付けてください。
読み取りには getBinaryDataBuffer を使います。$binary.<key>.data を手作業で base64 デコードしないでください。
// Code node, "Run Once for Each Item"
const buffer = await this.helpers.getBinaryDataBuffer(0, 'data'); // (itemIndex, propertyName)
const text = buffer.toString('utf-8');
const length = buffer.length;
return [{
json: { ...$json, length },
binary: $input.item.binary, // pass the binary through, or it's gone
}];
書き込みはスロットを自分で作成します。バイト列を base64 に変換し、MIME タイプとファイル名を指定します。
const text = 'Hello, world!';
return [{
json: { ok: true },
binary: {
report: {
data: Buffer.from(text).toString('base64'),
mimeType: 'text/plain',
fileName: 'report.txt',
fileExtension: 'txt',
},
},
}];
Code ノードのサンドボックス、ヘルパー、実行モードについては、n8n-code-javascript(および n8n-code-python)が扱います。言語レベルの詳細には、そちらを参照してください。ここで覚えておくべきバイナリ固有の点は、[{ json: {...} }] を返す Code ノードは、binary を再度付与しないと ファイルを通知なく破棄することです。BINARY_BASICS.md を参照してください。
変換処理の途中でバイナリを維持する
Edit Fields(Set)、Code、IF など、JSON のみを扱うノードは、出力から $binary スロットを削除することがあります。ワークフローは正常と検証され、エラーなく実行されますが、メールノードが添付しようとした時点で、後続の処理にファイルが存在しません。
維持する方法は 2 つあります。
- 変換ノードのパススルーオプションを使う。 Edit Fields には
includeOtherFieldsがあり、Code ノードはbinary: $input.item.binaryを明示的に返せます。利用できる場合は、これが最も手軽な修正方法です。 - 分岐させて、位置で Merge する。 ソースを変換側とバイパス側の両方にルーティングし、
combineByPositionモードの Merge で再結合します。JSON は変換側から取得し、バイナリはバイパス側で維持します。
[Source with binary] ─┬─→ [Edit Fields: change JSON] ─┐
│ (binary stripped here) ├─→ [Merge: combineByPosition] ─→ [Email: attach]
└──────────────────────────────────┘
(bypass — binary passes through untouched)
combineByPosition は各入力の N 番目のアイテム同士を組み合わせるため、フィールド数を揃える必要があります。接続の配線方法と、多数の処理を経由するチェーンでの代替案(早めのアップロード、サブワークフロー)については、MERGE_FOR_CONTEXT.md を参照してください。
エージェントツールにおけるバイナリの境界
ここが最も注意すべき点です。AI Agent は JSON を介してツール(Custom Code Tool、Call n8n Workflow Tool、HTTP Request Tool、MCP tools)とやり取りします。この経路では、どちらの方向でもバイナリを渡せません。どちらの場合も解決方法は同じです。バイト列をストレージに一時保存し、JSON 経由でキーまたは URL を渡して、受け取り側で取得します。
受信 — エージェントのツールで処理するファイルをユーザーがアップロードする場合:
- チャットトリガーから
files[]配列を受け取ります。ファイルを分割し、それぞれをハッシュ化したキーでプライベートストレージにアップロードします。 - エージェントの実行前に、その分岐を再結合します(これは同期バリアであり、飾りではありません)。N 個のファイルによってエージェントが N 回実行されないよう、エージェントに
executeOnce: trueを設定します。 - エージェントのシステムプロンプトにキーを挿入し、元の名前(人間が文脈を把握するため)とストレージキー(ツールが必要とするもの)の両方を記載したうえで、「このキーを正確に使用する」と明示します。
- ツールはキーを文字列引数として受け取り、ストレージからファイルをダウンロードします。
送信 — ツールがエージェントから返すファイルを生成する場合:
- ツールのサブワークフローでバイナリを生成し、ストレージにアップロードして、
{ "ok": true, "key": "...", "url": "https://...", "mimeType": "image/png" }のような JSON を返します。 - エージェントは返信に URL を埋め込むか、別のツールにキーを渡します。
エージェントの passthroughBinaryImages: true は、ビジョン機能で LLM が見る内容を変えるだけです。ツールがファイルを受け取れるようにはなりません。また、対象は画像のみで、PDF、音声、動画には対応しません。どのツールにも、引き続きアップロードしてキーを渡すパターンが必要です。パターンの全容、ハッシュ戦略、ストレージの選択肢、長時間実行ツール向けの方法については、AGENT_TOOL_BINARY.md を参照してください。
ツール自体を構築していますか?Custom Code Tool の契約については n8n-code-tool を、AI Agent とツールを組み合わせる構成については n8n-workflow-patterns を参照してください。
チャット画面でのCDN要件
ワークフローで画像を生成し、ユーザーがチャットメッセージ内に表示したい場合:
- アイテムにバイナリがあるだけでは不十分です。 チャットクライアントは、URLで画像を参照するメッセージをレンダリングするか、プラットフォーム独自のファイルアップロードAPIを通じてバイト列を送信します。
$binaryを読み取ることはありません。 - バイト列は、HTTPS経由でURLから取得できる場所に保存する必要があります。 まずオブジェクトストアまたはドライブにアップロードし、返されたURLを埋め込みます。
- n8nには組み込みのCDNがありません。 ストレージはユーザーが用意します。
S3を前提にせず、すでに利用しているストレージを尋ねてください。オブジェクトストレージ(S3、R2、GCS、Azure Blob、Backblaze B2、Supabase Storage)とドライブ型サービス(Dropbox、Google Drive、OneDrive、Box)はどれも利用できますが、URLの形式はサービスによって異なります。まだストレージがない場合は、Cloudflare R2が最も手軽な出発点です。機密性の高いコンテンツには、恒久的に公開するURLではなく、有効期限付きの署名付きURLを使用してください。CDN_REQUIREMENT.md を参照してください。
利用できない機能
$fromAI()ではバイナリを渡せません。 ツールのパラメーターに設定できるのは、文字列、数値、ブール値、オブジェクトです。ファイルのバイト列は渡せません。代わりにストレージキーを渡してください。- ツールの引数と戻り値はJSONのみです。 エージェントツールには、入力にも出力にも「バイナリパラメーター」はありません。
- n8nにはCDNも、公開ファイルホストもありません。 URL経由でのファイル配信は常にユーザーのストレージが担い、n8nは担いません。
getBinaryDataBufferはCodeノード用のヘルパーです。 Custom Code Toolのサンドボックスでは利用できません(n8n-code-tool を参照)。
Data Tablesの保存場所
ステージングしたファイルの参照カウント、使用中のキーの追跡、重複排除など、永続的な表形式ストレージには、n8n-mcp-tools-expert が管理する n8n_manage_datatable サーフェスを使用します。このスキルではData Tablesを扱いません。
アンチパターン
| アンチパターン | 問題点 | 修正方法 |
|---|---|---|
$json からファイルの内容を読み取る | バイト列は $binary に保存されます。$json は空か、メタデータのみです | $binary.<key> から読み取るか、Codeノードで getBinaryDataBuffer を使用します |
responseFormat: "file" を指定せずにHTTPでダウンロードする | バイト列がクリーンなバイナリではなく、加工されたテキストとして $json に届きます | HTTP Requestノードで responseFormat: "file" を設定します |
Codeノードが [{json:{...}}] を返し、binary を含めない | ファイルが後続の処理で気付かれないまま失われます | 戻り値で binary: $input.item.binary を再度付与します |
| JSON変換(Edit Fields/IF)でバイナリが失われる | Email/Uploadノードで添付するものが見つかりません | パススルーオプションを使うか、分岐させてMerge by positionでマージします |
アップロードしたファイルを $fromAI でツールに渡す | $fromAI ではバイナリを渡せないため、ツールには何も届きません | 事前にストレージへ配置し、システムプロンプトにキーを挿入して、ツールがキーで取得するようにします |
passthroughBinaryImages を使えばツールがファイルを参照できると思い込む | これはLLMに見える内容にのみ影響し、しかも画像だけが対象です | ツールには引き続き、アップロードしてキーを渡すパターンが必要です |
| ツールが生のバイナリをエージェントに返す | ツールの出力はJSONです。バイト列は保持されず、コンテキストも膨らみます | アップロードし、JSONで { key, url } を返します |
$binary をチャット画面に投稿すれば画像が表示されると思い込む | チャットクライアントは生のバイト列ではなく、URLを使ってレンダリングします | ストレージ/CDNにアップロードし、URLを埋め込むか、プラットフォームのファイルAPIを使用します |
| Codeノードにbase64をハードコードする | ワークフローJSONが巨大になり、処理が遅くなり、情報漏えいの危険も生じます | $binary で参照するか、アップロードしてURLで参照します |
参考ファイル
| ファイル | 読むタイミング |
|---|---|
BINARY_BASICS.md | バイナリを初めて扱う場合、または $binary スロット、MIMEタイプ、サイズ制限を読み書きする場合 |
AGENT_TOOL_BINARY.md | エージェントツールでアップロードしたファイルを使う場合、またはファイルを生成する場合。いずれの方向にも適用される境界について |
MERGE_FOR_CONTEXT.md | JSON変換後にバイナリが失われ、再度付与する必要がある場合 |
CDN_REQUIREMENT.md | チャット画面や、URLで画像を参照する必要のある場所に画像を表示する場合 |
他のスキルとの連携
n8n-code-javascript / n8n-code-python: Code ノードは、生のバイトデータを読み書きする場所です(getBinaryDataBuffer、Buffer.from(...).toString('base64'))。これらのスキルでは、サンドボックス、ヘルパー、実行モードの詳細を扱います。このスキルでは、返すときにバイナリを再度アタッチする必要があるというルールを扱います。
n8n-code-tool: Custom Code Tool のサンドボックスは、さらに制限されています。$binary、getBinaryDataBuffer、$fromAI は使えません。ツールでファイルが必要な場合は、このスキルのストレージキーのパターンを使って取得します。
n8n-workflow-patterns: エージェントツールのバイナリ境界は、AI-Agent-with-tools パターンの中にあります。CDN フローは、生成 → アップロード → 返信の連鎖です。
n8n-node-configuration: responseFormat、binaryPropertyName、includeOtherFields、binaryPropertyOutput はすべて条件付きフィールドです。get_node を使って、ユーザーのバージョンでの正確な名前を確認してください。
n8n-expression-syntax: $binary.<key>.fileName と $json.body のどちらで参照するか(特に Webhook のアップロード)は、式に関する領域です。
n8n-validation-expert: バイナリスロットが破棄されても、エラーは表面化しません。validate_workflow では検出されないため、実行を調べて存在を確認してください。
n8n-mcp-tools-expert: n8n_manage_datatable(Data Tables)と n8n_executions を扱います。後者を使って、特定のノードを通過した後も binary スロットが残っていることを確認してください。
n8n-error-handling: ストレージへのアップロードとダウンロードは失敗することがあります。キーが見つからない場合に気付かないまま 404 にならないよう、受信側と送信側のステージング手順にエラーブランチが必要です。
using-n8n-mcp-skills: 各スキルの連携方法をまとめたインデックスです。
バイナリが残っていることの確認
検証では、バイナリスロットが削除されても検出されません。エラーが表面化しないため、正しく実行されたことを確認してください。
n8n_test_workflow(または実際の実行をトリガー)で、実行データを生成します。n8n_executionsでその実行データを取得し、ノードごとの出力を調べてbinaryスロットを確認します。base64 が大きすぎて表示できない場合でも、存在とメタデータは確認できます。binaryが最後に現れるノードが、削除される直前のノードです。パススルーまたは Merge を追加するのはその場所です。
クイックリファレンスチェックリスト
- ファイルの内容は
$binary.<key>から読み取ること。$jsonは使わない - HTTP ダウンロードでは
responseFormat: "file"を使う - ファイルを引き続き渡す必要がある場合、Code ノードは返すときに
binaryを再度アタッチする - JSON の変換では、バイナリをそのまま渡すか、Merge で再度結合する(
combineByPosition) - バイナリをエージェントツールに渡したり、エージェントツールから受け取ったりしない。代わりに JSON 経由でキーや URL を渡す
-
passthroughBinaryImagesは LLM のビジョン機能にのみ使用し、ツールとの受け渡しには使わない - チャット画面に表示する画像はストレージにアップロードし、バイトデータではなく URL を埋め込む
- ストレージバックエンドはユーザーと相談して選ぶ(S3 をデフォルトにしない)。機密コンテンツには署名付き URL を使う
- バイナリの有無は検証ではなく、実行データを調べて確認する
覚えておいてください: スロットは2つあり、並んでいます。データは $json に、ファイルは $binary に格納されます。ファイルをエージェントツールに渡す、またはチャット画面に表示する必要が生じた時点で、バイトデータではなく URL として渡します。