はじめに / 対象と前提
Claude API で PDF や画像を扱うとき、毎回 Base64 エンコードして messages に埋め込んでいた。同じ 10MB の PDF に質問を 5 回投げると、5 回とも同じデータを送信することになる。リクエストが重い・遅い・コードが汚い、の三重苦。
Files API を使うと、ファイルを一度アップロードして file_id で参照できるようになる。この記事では実装手順と、自分が実際にハマった 3 点をまとめる。
想定読者:
- Claude API(Messages API)を Python で叩いたことがある
- PDF / 画像入力(Vision)を使っている、または使いたい
環境:
- Python 3.13
- anthropic SDK 1.x
- モデル: claude-opus-5(2026-09 時点)
TL;DR
-
client.beta.files.upload()でアップロード → 返ってきたidを{"type": "document", "source": {"type": "file", "file_id": ...}}で参照する - beta 指定
files-api-2025-04-14は アップロードと Messages 呼び出しの両方に必要 - アップロードしたファイルは API 経由で再ダウンロードできない(取れるのはメタデータのみ)。元ファイルは自分で保管する
手順 / 動かし方
1. ファイルをアップロードする
import anthropic
client = anthropic.Anthropic()
uploaded = client.beta.files.upload(
file=("report.pdf", open("report.pdf", "rb"), "application/pdf"),
)
print(uploaded.id)
print(uploaded.size_bytes)
file 引数は (ファイル名, バイナリ, MIME タイプ) のタプルのほか、pathlib.Path をそのまま渡してもよい。アップロード側の beta ヘッダーは SDK が自動で付けてくれる。
実行結果:
file_011CNha8iCJcU1wXNR6q4V8w
1048576
2. Messages API から file_id で参照する
response = client.beta.messages.create(
model="claude-opus-5",
max_tokens=16000,
messages=[{
"role": "user",
"content": [
{"type": "text", "text": "このレポートの要点をまとめて"},
{
"type": "document",
"source": {"type": "file", "file_id": uploaded.id},
},
],
}],
betas=["files-api-2025-04-14"],
)
print(response.content[0].text)
ポイントは 2 つ。
-
client.messages.createではなくclient.beta.messages.createを使い、betas=["files-api-2025-04-14"]を渡す - Base64 のときの
"source": {"type": "base64", ...}が"source": {"type": "file", "file_id": ...}に変わるだけで、content block の構造は同じ
同じ file_id は何度でも使い回せるので、「1 つの PDF に質問を 10 回」のようなユースケースでもアップロードは 1 回で済む。
3. ファイルの管理(一覧・メタデータ・削除)
# 一覧(SDK が自動でページネーションする)
for f in client.beta.files.list():
print(f.id, f.filename, f.size_bytes)
# メタデータ取得
info = client.beta.files.retrieve_metadata(uploaded.id)
print(info.mime_type)
# 削除
client.beta.files.delete(uploaded.id)
ファイルは削除するまで残り続ける。上限は 1 ファイル 500MB、組織全体で 100GB。アップロード・一覧・削除の操作自体は無料で、課金されるのは Messages で参照したときに入力トークンとして数えられる分だけ。
ハマりどころ
1. beta 指定は「2 箇所」に必要
最初にハマったのがこれ。アップロードは SDK が勝手にヘッダーを付けるので成功する。ところが Messages 側で betas=["files-api-2025-04-14"] を渡し忘れると、file_id を参照した時点で 400 系エラーになる。
「アップロードは成功しているのに参照で落ちる」ため、file_id の値が間違っていると勘違いして 30 分溶かした。アップロードと参照は別リクエストで、beta 指定はそれぞれに必要、と覚えておく。
2. content block の型と MIME タイプの不一致
PDF・テキストは "type": "document"、画像(PNG / JPEG など)は "type": "image" で参照する必要がある。image/png でアップロードしたファイルを document ブロックで参照するとエラーになる。
Base64 時代は media_type を毎回自分で書くので意識するが、file_id 参照だと「どの MIME でアップロードしたか」がコード上から見えなくなる。変数名で区別できるようにしておくと事故らない。迷ったら retrieve_metadata() の mime_type で確認できる。
3. アップロードしたファイルは再ダウンロードできない
client.beta.files.download() という API はあるが、ダウンロードできるのはコード実行ツールや Skills が生成したファイルだけ。自分がアップロードしたファイルを取り出そうとするとエラーになる。
つまり Files API は「ストレージ」ではなく「Messages 参照用の置き場」。ローカルの元ファイルを消して file_id だけ控えておく、という運用は詰むのでやってはいけない。元ファイルの保管は別途自分で行う。
補足
- Amazon Bedrock / Google Vertex AI では Files API は使えない(2026-09 時点)。Anthropic API を直接叩いている場合のみ
- PDF のページ上限(600 ページ、200K コンテキストのモデルは 100 ページ)は Base64 送信のときと同じく適用される
-
documentブロックに"citations": {"enabled": True}を付ければ引用機能もそのまま併用できる
まとめ
- Files API は「一度アップロードして
file_idで使い回す」仕組み。同じファイルへの複数質問で特に効く - beta 指定
files-api-2025-04-14はアップロードと Messages の両方に必要 - ブロック型(document / image)は MIME タイプと一致させる
- アップロードしたファイルは再取得不可。元ファイルは自分で保管する
- 操作は無料、課金は参照時の入力トークンのみ。使い終わったら
deleteでストレージを空ける