Files APIで日本語ファイル名・日本語メタデータは正しく扱えるか
Files APIの禁止文字リストに日本語文字は含まれず、仕様上はアップロードできます。ただし「メタデータ」に任意タグは存在せず、アップロード時のファイル名がClaudeの応答に自動で出るわけでもありません。
Files APIのファイル名バリデーションが禁止する文字に、日本語の文字は含まれません。仕様上は「請求書_2026年8月.pdf」のようなファイル名もそのままアップロードできます。
落とし穴は2つあります。Files APIが返す「メタデータ」に任意のキー・値タグは存在しないこと。そして、引用に文書名を出す経路として公式が示しているのはdocumentブロックのtitleフィールドで、filenameを渡すだけではその経路に乗らないことです。
Files APIのファイル名バリデーションに日本語は引っかかるか
公式のエラーリファレンスは、ファイル名の不正(400 Invalid filename)が起きる条件を次の2つに限定しています。
- 長さが1〜255文字の範囲外
- 禁止文字(
<>:"|?*\/、またはUnicodeの制御文字0〜31)を含む
このリストにひらがな・カタカナ・漢字は含まれません。禁止されているのは記号の一部と、目に見えない制御文字だけです。公式のバリデーション仕様では、日本語ファイル名だからという理由でアップロードが拒否されることはありません。
FILE_ID=$(curl -X POST https://api.anthropic.com/v1/files \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-F "file=@請求書_2026年8月.pdf" | jq -r '.id')
echo "$FILE_ID"curlは日本語ファイル名を実際どんな形で送るのか
-F "file=@請求書_2026年8月.pdf"と書いたとき、ファイル名はローカルのパスから自動で取り出され、multipart/form-dataのContent-Dispositionヘッダーに載って送られます。この変換は手元のHTTPクライアント側の仕事で、Files APIの仕様ページには書かれていません。そこで、手元のcurl 8.7.1から自分のPCの待ち受けポート(127.0.0.1)へ同じ形のアップロードを送り、実際に流れたヘッダーを見ました。
Content-Disposition: form-data; name="file"; filename="\xe8\xab\x8b\xe6\xb1\x82\xe6\x9b\xb8_2026\xe5\xb9\xb48\xe6\x9c\x88.pdf"
Content-Type: application/pdf上は受信側でバイト列をそのまま出力した結果です。filename="..."の中身は\xe8\xab\x8bのようなUTF-8のバイト列で、パーセントエンコードもfilename*=UTF-8''...形式も使われていません。日本語はUTF-8の生バイトのまま送られます。Content-Typeは.pdfの拡張子からapplication/pdfが自動で付きました。
Files APIは、betaヘッダーを付けない呼び出しではContent-Typeを省略でき、省略すると型が検出されます。この自動付与とは別に型の判定が働きます。サーバーがこの生バイトのファイル名をどう読むかは仕様ページに記載がなく、実際に受理されたかどうかはアップロード後の応答でしか分かりません。次の節の検証手順が、その確認です。
SDKを使うと、この暗黙の取り出しを避けられます。Pythonならclient.files.upload(file=("請求書.pdf", open(path, "rb"), "application/pdf"))のようにタプルの先頭でファイル名を指定できます。TypeScriptのtoFile()では、公式のアップロード例の第2引数にundefinedが入っています。日本語ファイル名を確実に付けたいときは、ここに文字列を渡します。
濁点・半濁点は文字数もバイト数も増える
日本語ファイル名には、見た目が同じでも中身が違う場合があります。「ガ」は1文字(U+30AC)でも、「カ」と濁点(U+3099)の2文字でも表せます。前者をNFC、後者をNFDと呼ぶ正規化形式の違いで、どちらも画面では同じ「ガ」に見えます。
手元のPythonで、同じ「ガイド.pdf」を2つの形式に変換して数えました。
NFC: 7文字 / 13バイト
NFD: 9文字 / 19バイト
NFC == NFD: False画面では同じ名前でも、NFDだと文字数は2つ、バイト数は6つ増えます。濁点・半濁点を含む名前が多いほど、前の節の255という上限に近づきやすくなり、==での比較も一致しません。アップロード後にfilenameを読み戻して元の名前と突き合わせるときは、両方をNFCにそろえてから比べると、見た目が同じなのに不一致と判定される誤検知を避けられます。
import unicodedata
def same_name(local: str, remote: str) -> bool:
nfc = lambda s: unicodedata.normalize("NFC", s)
return nfc(local) == nfc(remote)
meta = client.files.retrieve_metadata(file_id)
assert same_name("請求書_2026年8月.pdf", meta.filename)アップロード後に文字化けしていたらどう確かめ、どう直すか
アップロードしたファイルはdownloadableがfalseで、ダウンロードして中身を目視する経路がありません。ファイル名を見る手段は、メタデータ取得(GET /v1/files/{file_id})だけです。この制約の背景はFiles APIでダウンロードできない理由にまとめています。
日本語ファイル名の検証と修復
- 1
アップロードして file_id を受け取る
応答の
filenameも見ておきます。ここに意図した日本語が返っていれば、保存時点では正しく扱われています。 - 2
メタデータを取り直して突き合わせる
GET /v1/files/{file_id}(SDKではretrieve_metadata)でfilenameを引き、元のファイル名と一致するかを比べます。 - 3
ずれていたら削除して上げ直す
ファイルは作成後に内容も名前も変更できません。直す手段は
DELETE /v1/files/{file_id}で消して、正しい名前で再アップロードすることだけです。削除したファイルは復元できません。
curl https://api.anthropic.com/v1/files/$FILE_ID \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01"一時的な検証用のファイルなら、アップロード時にexpires_in_secondsフォームフィールドで有効期限を付けておく手があります。値は3,600秒(1時間)から7,776,000秒(90日)までの整数です。期限を過ぎたファイルも、メタデータが最長30日は読め、一覧にも残ります。一覧ではexpires_atを現在時刻と比べて除外します。期限を付けておけば、試し打ちのファイルが自動で使えなくなり、容量枠も解放されます。
「日本語メタデータ」は存在するか — アップロード応答のフィールド
Files APIにアップロードすると、レスポンスはid type filename mime_type size_bytes created_at downloadable expires_atの8フィールドを返します。ファイルに任意のキー・値を追加するカスタムメタデータの項目は、この8つの中にありません。
つまり「日本語メタデータを設定できるか」という問いは、実質的に「filenameフィールドに日本語を書けるか」という問いと同じです。部署名やプロジェクト名をタグ付けする目的でFiles APIを使っても、その置き場所はありません。用途・カテゴリー・担当者のような分類情報は、file_idと紐づけて自社側のデータベースで持つことになります。
一覧取得(GET /v1/files)も同じ事情です。公式ページに載っているパラメーターは、ページ送り用のpageとlimit(既定20件・最大1,000件、新しい順)、既知のfile_idを最大100件まとめて引くids[]の3つです。ids[]はpageやlimitと同時に使えず、手元に無いIDは黙って結果から外れます。ファイル名で絞るパラメーターは載っていないので、日本語ファイル名で探すなら、全件を引いてクライアント側で絞るか、アップロード時にfile_idと名前の対応表を持っておくことになります。
容量上限やライフサイクルはClaude Files APIの容量上限とファイルライフサイクルで扱っています。file_idの管理上の注意はClaude Files APIのfile_idセキュリティリスクと対策にあります。
Claudeに文書名を見せるのはtitleとcontext
Files APIのfilenameは、アップロードしたファイルを人間や自社システムが識別するための管理用フィールドです。Claudeに文書名を認識させ、引用に反映させる経路として公式が示しているのは、documentブロックのtitleフィールドを別に指定する方法です。filenameをそのままdocumentブロックに渡したときの扱いは、公式のFiles APIページにもCitationsのページにも書かれていません。
{
"type": "document",
"source": { "type": "file", "file_id": "file_011CNha8iCJcU1wXNR6q4V8w" },
"title": "2026年8月分請求書",
"citations": { "enabled": true }
}Citationsのページによると、titleとcontextは任意項目で、どちらもモデルには渡されますが、引用の対象テキストにはなりません。引用の応答ではtitleがdocument_titleとして返ります。titleには長さの制限があるため、長い説明はcontextに文字列やJSON(文字列化したもの)で持たせる使い方が案内されています。
管理用の名前とClaude向けの名前
filename
アップロード時に決まる管理用の名前です。社内の命名規則に合わせて日本語のまま付けられ、後から変更はできません。一覧のフィルターにも使えません。
title / context
リクエストごとに付け替えられる、Claude向けの文書名と補足です。titleは引用のdocument_titleに出ます。長い説明はcontextに入れます。
同じ文字列で兼用しようとすると、管理のしやすさとClaudeへの伝わりやすさのどちらかを削ることになります。日本語で管理し、引用に出したい名前はtitleで別に作る分け方なら、ファイル名の命名規則を変えずに済みます。
まとめ
日本語ファイル名は仕様上アップロードできます。長い名前はバイト数換算に備えて85文字以内にしておくと安全です。アップロードごとにメタデータでfilenameを読み戻し、ずれていたら削除して上げ直します。分類情報は自社側で持ち、Claudeに見せる文書名はtitleで別に指定します。