Claude Files APIとは? — 「一度アップロード、何度でも参照」の仕組み
Claude APIを使ってドキュメントや画像を分析する際、毎回同じファイルをリクエストに含めていませんか? Files APIを使えば、ファイルを一度Anthropicのセキュアなストレージにアップロードするだけで、固有のfile_idを通じて何度でも参照できるようになります。
これにより、以下のメリットが得られます。
- 通信コストの削減: 同じPDFを何十回も再送信する必要がなくなる
- コードのシンプル化: Base64エンコードやマルチパートの処理が不要に
- ワークスペース共有: 同じワークスペース内のAPIキーであれば、誰でもアップロード済みファイルを利用可能
Files APIは現在ベータ版として提供されており、anthropic-beta: files-api-2025-04-14 ヘッダーを付けることで利用できます。
個人開発でアプリの問い合わせ対応を整理していたとき、ユーザーから届いた不具合報告のスクリーンショットを毎回リクエストへ添付し直していて、同じ画像を何度も送り直している無駄に気づきました。Files APIに切り替えてからは、一枚アップロードしたfile_idを「分類用」と「返信文面の下書き用」で使い回せるようになり、処理を書くときの気持ちがずいぶん軽くなりました。小さな改善ですが、こうした積み重ねが運用の安定につながると感じています。
対応ファイル形式とサイズ制限
Files APIがサポートするファイル形式は、用途によって異なります。
| ファイル種別 | MIMEタイプ | コンテンツブロック | 主な用途 |
| PDF | application/pdf | document | 文書分析・要約・引用抽出 |
| プレーンテキスト | text/plain | document | テキスト解析・処理 |
| 画像(JPEG, PNG, GIF, WebP) | image/jpeg 等 | image | 画像認識・ビジュアルタスク |
| データセット等 | 各種 | container_upload | データ分析・可視化(Code Execution Tool併用) |
サイズ制限は以下の通りです。
- 1ファイルあたり: 最大500MB
- 組織全体のストレージ: 最大500GB
前提条件 — 始める前に準備するもの
Files APIを利用するには、以下が必要です。
- Anthropic APIキー: Anthropic Consoleから取得
- Python SDK(v0.40以降)またはTypeScript SDK(v0.35以降): ベータ機能をサポートするバージョン
- ベータヘッダー:
anthropic-beta: files-api-2025-04-14
# Python SDKのインストール・更新
pip install --upgrade anthropic
# TypeScript SDKのインストール・更新
npm install @anthropic-ai/sdk@latest
ステップバイステップ — Files APIの基本操作
1. ファイルをアップロードする
まず、分析したいファイルをアップロードします。アップロードが成功すると、一意のfile_idが返されます。
Python:
import anthropic
client = anthropic.Anthropic()
# PDFファイルをアップロード
uploaded = client.beta.files.upload(
file=("report.pdf", open("report.pdf", "rb"), "application/pdf"),
)
print(f"ファイルID: {uploaded.id}")
# 出力例: ファイルID: file_011CNha8iCJcU1wXNR6q4V8w
print(f"ファイル名: {uploaded.filename}")
# 出力例: ファイル名: report.pdf
print(f"サイズ: {uploaded.size_bytes} bytes")
# 出力例: サイズ: 1024000 bytes
TypeScript:
import Anthropic, { toFile } from "@anthropic-ai/sdk";
import fs from "fs";
const anthropic = new Anthropic();
// PDFファイルをアップロード
const uploaded = await anthropic.beta.files.upload({
file: await toFile(
fs.createReadStream("report.pdf"),
undefined,
{ type: "application/pdf" }
),
betas: ["files-api-2025-04-14"],
});
console.log(`ファイルID: ${uploaded.id}`);
// 出力例: ファイルID: file_011CNha8iCJcU1wXNR6q4V8w
2. アップロードしたファイルをMessagesで参照する
取得したfile_idを使って、Claudeにファイルの内容を分析させます。
Python:
# アップロード済みPDFをClaudeに要約させる
response = client.beta.messages.create(
model="claude-sonnet-4-6",
max_tokens=2048,
messages=[
{
"role": "user",
"content": [
{
"type": "text",
"text": "この文書の要点を3つにまとめてください。"
},
{
"type": "document",
"source": {
"type": "file",
"file_id": uploaded.id,
},
"title": "四半期レポート", # 任意
"citations": {"enabled": True}, # 引用機能を有効化
},
],
}
],
betas=["files-api-2025-04-14"],
)
print(response.content[0].text)
TypeScript:
const response = await anthropic.beta.messages.create({
model: "claude-sonnet-4-6",
max_tokens: 2048,
messages: [
{
role: "user",
content: [
{
type: "text",
text: "この文書の要点を3つにまとめてください。",
},
{
type: "document",
source: {
type: "file",
file_id: uploaded.id,
},
},
],
},
],
betas: ["files-api-2025-04-14"],
});
console.log(response.content[0]);
3. 画像ファイルを参照する
画像の場合はimageコンテンツブロックを使います。
# 画像をアップロード
img = client.beta.files.upload(
file=("screenshot.png", open("screenshot.png", "rb"), "image/png"),
)
# 画像の内容をClaudeに説明させる
response = client.beta.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": "このスクリーンショットに写っているUIの改善点を指摘してください。"},
{
"type": "image",
"source": {
"type": "file",
"file_id": img.id,
},
},
],
}
],
betas=["files-api-2025-04-14"],
)
4. ファイルの管理操作
アップロード済みファイルの一覧取得、メタデータ確認、削除が可能です。
# ファイル一覧を取得
files = client.beta.files.list()
for f in files.data:
print(f"{f.id}: {f.filename} ({f.size_bytes} bytes)")
# 特定ファイルのメタデータを取得
metadata = client.beta.files.retrieve_metadata("file_011CNha8iCJcU1wXNR6q4V8w")
print(f"作成日時: {metadata.created_at}")
# ファイルを削除
client.beta.files.delete("file_011CNha8iCJcU1wXNR6q4V8w")
実践パターン — 複数ファイルの一括分析
Files APIの真価は、同じファイルを複数のリクエストで使い回せる点にあります。たとえば、月次レポート12ヶ月分をアップロードしておき、それぞれ異なる観点で分析するワークフローが考えられます。
import anthropic
from pathlib import Path
client = anthropic.Anthropic()
# 12ヶ月分のレポートを一括アップロード
file_ids = []
for month in range(1, 13):
path = Path(f"reports/2025-{month:02d}.pdf")
uploaded = client.beta.files.upload(
file=(path.name, open(path, "rb"), "application/pdf"),
)
file_ids.append(uploaded.id)
print(f" アップロード完了: {path.name} → {uploaded.id}")
# 全レポートを横断して傾向分析
content_blocks = [
{"type": "text", "text": "以下の12ヶ月分のレポートを分析し、売上の傾向と改善ポイントを報告してください。"}
]
for fid in file_ids:
content_blocks.append({
"type": "document",
"source": {"type": "file", "file_id": fid},
})
response = client.beta.messages.create(
model="claude-sonnet-4-6",
max_tokens=4096,
messages=[{"role": "user", "content": content_blocks}],
betas=["files-api-2025-04-14"],
)
print(response.content[0].text)
# 12ファイル分の通信コストを節約しつつ、横断的な分析が可能
本番運用に耐えるアップロード処理を書く
上の基本コードは、ネットワークが安定し、ファイルが一度しか登録されない前提で書かれています。実際のパイプラインではそうはいきません。アップロードの途中で接続が切れる、レート制限に当たる、同じファイルを二重に登録してしまう——こうした事態に備えた処理が必要です。
まず、素朴な実装が抱える問題を確認します。
# Before — 失敗に弱く、二重登録も防げない
def upload_naive(client, path):
uploaded = client.beta.files.upload(
file=(path.name, open(path, "rb"), "application/pdf"),
)
return uploaded.id
この実装には2つの弱点があります。ひとつは、uploadが一時的なエラー(接続断や429)で例外を投げた瞬間に処理全体が止まること。もうひとつは、Files APIがサーバー側で内容の重複を排除しないため、同じファイルを再実行のたびに新しいfile_idとして登録してしまい、ストレージと管理コストが静かに膨らんでいくことです。
次の実装では、指数バックオフによる再試行と、ローカルの台帳(ledger)によるアップロード済み判定を加えています。
# After — 再試行 + 内容ハッシュによる冪等化
import hashlib
import json
import time
from pathlib import Path
import anthropic
def file_sha256(path: Path) -> str:
"""ファイル内容のSHA-256を計算(重複検知の鍵にする)。"""
h = hashlib.sha256()
with open(path, "rb") as f:
for chunk in iter(lambda: f.read(1024 * 1024), b""):
h.update(chunk)
return h.hexdigest()
def upload_idempotent(
client: anthropic.Anthropic,
path: Path,
media_type: str,
ledger_path: Path = Path(".files_ledger.json"),
max_retries: int = 4,
) -> str:
"""内容ハッシュ単位で一度だけアップロードし、file_idを台帳に記録する。"""
ledger = json.loads(ledger_path.read_text()) if ledger_path.exists() else {}
digest = file_sha256(path)
# すでに同じ内容を登録済みなら、その file_id を再利用する
if digest in ledger:
print(f" 再利用: {path.name} → {ledger[digest]}")
return ledger[digest]
last_error = None
for attempt in range(1, max_retries + 1):
try:
uploaded = client.beta.files.upload(
file=(path.name, open(path, "rb"), media_type),
)
ledger[digest] = uploaded.id
ledger_path.write_text(json.dumps(ledger, ensure_ascii=False, indent=2))
print(f" 新規登録: {path.name} → {uploaded.id}")
return uploaded.id
except (anthropic.APIConnectionError, anthropic.RateLimitError) as e:
last_error = e
wait = min(2 ** attempt, 30) # 2, 4, 8, 16 秒(上限30秒)
print(f" 再試行 {attempt}/{max_retries}({wait}秒待機): {e!r}")
time.sleep(wait)
except anthropic.APIStatusError as e:
# 413(容量超過)など、再試行しても直らないエラーは即座に中断
raise
raise RuntimeError(f"アップロードに失敗しました: {path.name}") from last_error
このヘルパーを通すだけで、再実行に強く、同じ内容を二度登録しないパイプラインになります。台帳はJSON1ファイルですが、規模が大きくなればSQLiteやKVストアに置き換えても構いません。重要なのは「内容ハッシュをキーに、アップロード済みかどうかを必ず確認してからuploadを呼ぶ」という設計です。さらに踏み込んだ重複排除と孤立ファイルの回収については、Files APIの内容ハッシュ台帳と孤立ファイル回収で具体的な実装を扱っています。
公式ドキュメントに書かれていない運用知見
ドキュメントどおりに動かすだけなら難しくありませんが、継続運用すると見えてくる点がいくつかあります。
重複は自動排除されません。 前述のとおり、同じ内容のファイルでもアップロードのたびに別のfile_idが振られます。バッチ処理を毎日回すような構成では、内容ハッシュによる冪等化を入れておかないと、同じPDFがストレージに何百個も積み上がります。500GBの上限に達してから慌てて消すより、登録時に台帳で防ぐほうがずっと楽です。
孤立ファイルは静かに溜まります。 一度アップロードしたファイルは、明示的にdeleteしない限り残り続けます。file_idを記録し損ねた登録は、もう一覧からしか辿れない「孤児」になります。定期的にfiles.list()で棚卸しし、台帳に存在しないfile_idを回収するジョブを用意しておくと安心です。私自身、ここを軽く見ていた時期があり、後から一覧を眺めて使われていない登録の多さに少し驚いた経験があります。
ワークスペースをまたぐと参照できません。 404 File not foundの多くは、別ワークスペースのAPIキーで登録したfile_idを参照しているケースです。本番・開発でキーを分けている場合は、file_idもワークスペース単位で管理する前提で設計してください。
ベータヘッダーの付け忘れに注意します。 uploadでは成功するのにmessages.createでだけ失敗する、という場合、betas=["files-api-2025-04-14"]の付け忘れを最初に疑うと早く解決します。
ユースケース別の推奨アプローチ
どの設計が適切かは、ファイルを「何回参照するか」でほぼ決まります。
- 同じファイルを1回しか使わない: Files APIを使わず、リクエストに直接
document/imageブロックで埋め込むほうがシンプルです。アップロードと削除の往復が無駄になります。
- 同じファイルを数回〜数十回参照する: Files APIの最も得意な領域です。アップロード1回+
file_id参照で、通信量とコードの両方が軽くなります。
- 同じ巨大ファイルを高頻度で参照し、プロンプト前半が共通している: Files APIに加えてプロンプトキャッシュの併用を検討します。Files APIは再送信を減らしますが、入力トークン課金そのものは減りません。キャッシュは入力トークン側のコストに効きます。
- 画像の前処理を挟みたい: 解像度やノイズで認識精度が揺れる場合は、アップロード前に画像の前処理を入れると安定します。
よくあるエラーと対処法
Files APIを利用する中で遭遇しやすいエラーと、その解決方法を紹介します。
| エラー | ステータス | 原因と対処法 |
| File not found | 404 | file_idが存在しないか、別のワークスペースのファイル。IDを再確認する |
| Invalid file type | 400 | ファイル形式とコンテンツブロックの不一致(例: 画像をdocumentブロックで指定)。正しいブロックタイプに変更する |
| File too large | 413 | 500MBの上限を超過。ファイルを分割するか圧縮する |
| Storage limit exceeded | 403 | 組織の500GB上限に到達。不要なファイルを削除する |
よくある落とし穴: .docxや.csvファイルをそのままdocumentブロックで使おうとするとエラーになります。.docxはPDFに変換してから、.csvはプレーンテキストとして読み込んでメッセージ本文に含めるか、Code Execution Toolのcontainer_uploadとして利用してください。
料金体系 — 実際のコストを見積もる
Files APIの管理操作自体は無料です。
- アップロード: 無料
- ダウンロード: 無料
- 一覧取得・メタデータ取得: 無料
- 削除: 無料
ただし、Messagesリクエストでファイルを参照した場合、その内容は入力トークンとして課金されます。つまり、同じファイルを10回参照すれば、10回分の入力トークンが発生します。ファイルの保存自体にはストレージ料金はかかりません。
ここを誤解すると見積もりを外します。Files APIは「再送信の通信量」を減らしますが、「Claudeが内容を読むための入力トークン」は参照のたびに発生します。PDFはテキスト量と図版の比率で変動しますが、運用上は1ページあたりおおよそ1,500〜3,000トークン程度を安全側で見込んでおくと予算が立てやすいです。
たとえば30ページのPDFを1回参照するなら、おおむね5万〜9万トークン前後の入力を見込みます。これを1日20回参照する分析パイプラインなら、1日あたり100万〜180万トークン規模になります。プロンプト前半(指示文や共通コンテキスト)が毎回同じなら、その部分はプロンプトキャッシュでキャッシュヒットさせることで、入力コストを実質的に圧縮できます。Files APIで通信を、プロンプトキャッシュで入力トークンを、それぞれ別の軸で削る——この2段構えが、ドキュメント処理を高頻度で回すときの基本形だと考えています。
次の一歩
まずは手元の小さなPDFを1つ用意し、本記事のupload_idempotentヘルパーを使ってアップロードしてみてください。二度実行してもfile_idが再利用される(=新規登録されない)ことを確認できれば、本番パイプラインに組み込む準備は整っています。引用付きで根拠を示したい場合は検索結果コンテンツブロックと引用グラウンディング、複数ツールを束ねたい場合は並列ツール実行の本番パターンへ進むと、ドキュメント処理の幅が一段広がります。
お読みいただきありがとうございました。同じようにAPIのコストと運用に向き合っている方の、小さな手がかりになれば幸いです。