CLAUDE LABEN
WWDC — WWDC 2026でSiriはGoogle Geminiベースと確定。ChatGPT等への外部ハンドオフは廃止され、サードパーティAI選択はEU(DMA)で当面非対応にBILLING — 6/15の課金変更まで残り6日。Agent SDK・headless Claude Code・GitHub Actions・他社エージェントがAPIレート準拠の月次クレジットへ移行OUTAGE — claude.ai・Claude Code・Coworkで障害が報告(6月)。スケジュール実行はfallbackModelとリトライ前提の設計が安全ですDYNAMIC-WORKFLOWS — Max・TeamプランとAPIでdynamic workflowsがデフォルトON。コードベース横断のバグ探索や独立検証に活用ULTRACODE — Claude Codeの新設定ultracodeがeffortメニューに追加。xhigh固定でワークフロー判断はClaudeに委ねますOPUS4.8 — Claude Opus 4.8が主要プランのデフォルトとして定着。コーディング・エージェント・推論を強化WWDC — WWDC 2026でSiriはGoogle Geminiベースと確定。ChatGPT等への外部ハンドオフは廃止され、サードパーティAI選択はEU(DMA)で当面非対応にBILLING — 6/15の課金変更まで残り6日。Agent SDK・headless Claude Code・GitHub Actions・他社エージェントがAPIレート準拠の月次クレジットへ移行OUTAGE — claude.ai・Claude Code・Coworkで障害が報告(6月)。スケジュール実行はfallbackModelとリトライ前提の設計が安全ですDYNAMIC-WORKFLOWS — Max・TeamプランとAPIでdynamic workflowsがデフォルトON。コードベース横断のバグ探索や独立検証に活用ULTRACODE — Claude Codeの新設定ultracodeがeffortメニューに追加。xhigh固定でワークフロー判断はClaudeに委ねますOPUS4.8 — Claude Opus 4.8が主要プランのデフォルトとして定着。コーディング・エージェント・推論を強化
記事一覧/API & SDK
API & SDK/2026-04-11中級

Claude API バッチ処理 — API費用を最大90%削減する非同期バッチ実装パターン

Claude API のバッチ処理で大量リクエストを効率的に処理。費用削減とレート制限回避を実現する実装パターンを解説します。

Claude API99Batch Processing非同期処理5費用最適化大量リクエスト

Claude API を使った AI アプリケーション開発で、大量のテキスト処理やデータ分析を行う必要はありませんか?

従来のリアルタイムAPI呼び出しでは、各リクエストごとに通信コストがかかり、大規模運用では費用が膨らみます。そこで活躍するのが Claude API のバッチ処理機能 です。

このガイドでは、バッチ処理の仕組み、実装方法、そして実際のユースケースまで、わかりやすく解説します。

バッチ処理とは:リアルタイム処理との違い

リアルタイムAPI呼び出し

  • ユーザーが「今すぐ実行」したいときに、その場で API に送信
  • 数秒で結果が返ってくる
  • 1リクエスト = 1通信コスト(割高)

バッチ処理

  • 複数のリクエストをまとめてファイルにして、バッチ API に送信
  • 数分〜数時間後に結果がまとめて返ってくる
  • 複数リクエストを 1回の送信で効率化(最大90%割引)

使い分けの目安:

  • リアルタイム処理が必要 → 通常の API を使う
  • 結果が数時間後でも OK → バッチ処理を使う

バッチ処理で可能なこと:実践的なユースケース

バッチ処理は以下のようなシナリオで特に効果的です。

① 大量テキスト分析

例)1,000件のカスタマーレビューを一括分析
従来: 1,000件 × $0.003 = $3.00
バッチ: 1,000件 × $0.0003 = $0.30(90%削減)

② 定期的なデータ処理

夜間に毎日 5,000件のログを分析するなど、スケジュール化できるタスク。リアルタイムで結果が必要でないため、バッチ処理が最適です。

③ 研究・論文執筆の補助

学術論文数百編の要約作成、データセット全体の分析など、学生・研究者向けのアカデミックプランと組み合わせると特に効果的。

④ マルチランゲージ翻訳

複数言語への翻訳タスク 500〜 1,000件を一括処理。翻訳品質を確保しながら費用を最小化できます。

バッチ処理の実装:ステップバイステップ

Step 1: リクエストファイルの形式を理解する

バッチ API は JSONL 形式(JSON Lines:1行1オブジェクト)を期待します。

{"custom_id": "req-1", "params": {"model": "claude-3-5-sonnet-20241022", "max_tokens": 100, "messages": [{"role": "user", "content": "日本語で「こんにちは」と言ってください"}]}}
{"custom_id": "req-2", "params": {"model": "claude-3-5-sonnet-20241022", "max_tokens": 100, "messages": [{"role": "user", "content": "英語で「Hello」に関する短編を書いてください"}]}}

重要なポイント:

  • custom_id: 各リクエストを特定するためのユニークID(自由に命名OK)
  • params: 通常のメッセージ送信で使うパラメータと同じ構造

Step 2: JSONL ファイルを生成する(Node.js例)

const fs = require('fs');
 
// サンプルリクエスト群
const requests = [
  { id: 'review-1', text: 'この製品のレビューを分析してください:「とても良い製品ですが、送料が高い」' },
  { id: 'review-2', text: 'このレビュー分析:「価格は妥当だが、配送が遅い」' },
  { id: 'review-3', text: 'レビュー分析:「品質は最高。次も買う!」' },
];
 
// JSONL に変換
const jsonl = requests
  .map(req => JSON.stringify({
    custom_id: req.id,
    params: {
      model: 'claude-3-5-sonnet-20241022',
      max_tokens: 150,
      messages: [{
        role: 'user',
        content: req.text
      }]
    }
  }))
  .join('\n');
 
// ファイルに保存
fs.writeFileSync('batch_requests.jsonl', jsonl);
console.log('✅ JSONL ファイル生成完了');

Step 3: Anthropic SDK でバッチを送信

const Anthropic = require('@anthropic-ai/sdk');
const fs = require('fs');
 
const client = new Anthropic({
  apiKey: process.env.ANTHROPIC_API_KEY
});
 
async function submitBatch() {
  // JSONL ファイルを読み込み
  const fileContent = fs.readFileSync('batch_requests.jsonl');
  
  // ファイルをアップロード
  const response = await client.beta.files.upload(
    { file: new File([fileContent], 'batch_requests.jsonl') },
    { headers: { 'anthropic-beta': 'files-api-2025-04-14' } }
  );
  
  const fileId = response.id;
  console.log(`📤 ファイルアップロード完了: ${fileId}`);
  
  // バッチを作成・送信
  const batch = await client.beta.batches.create(
    { input_file_id: fileId },
    { headers: { 'anthropic-beta': 'files-api-2025-04-14' } }
  );
  
  console.log(`📋 バッチ作成完了: ${batch.id}`);
  console.log(`⏳ ステータス: ${batch.processing_status}`);
  
  return batch.id;
}
 
submitBatch().catch(console.error);

Step 4: バッチ結果を確認する

async function checkBatchStatus(batchId) {
  const batch = await client.beta.batches.retrieve(batchId, {
    headers: { 'anthropic-beta': 'files-api-2025-04-14' }
  });
  
  console.log(`📊 ステータス: ${batch.processing_status}`);
  console.log(`✅ 完了: ${batch.request_counts.succeeded} 件`);
  console.log(`❌ 失敗: ${batch.request_counts.failed} 件`);
  
  // 処理中の場合は後で再確認
  if (batch.processing_status === 'in_progress') {
    console.log('⏳ まだ処理中です。1分後に再確認してください。');
    return;
  }
  
  // 結果ファイルをダウンロード
  if (batch.result_file_id) {
    const results = await client.beta.files.retrieveContent(batch.result_file_id, {
      headers: { 'anthropic-beta': 'files-api-2025-04-14' }
    });
    console.log('✅ 結果ファイルを取得しました');
  }
}
 
// バッチID を指定して確認
checkBatchStatus('batch_xxxxx').catch(console.error);

バッチ処理の最適化テクニック

① リクエストの粒度を調整する

// ❌ 効率が低い:1リクエスト = 1件分析
{ custom_id: 'review-1', params: { messages: [{ role: 'user', content: 'レビューA を分析' }] } }
 
// ✅ 効率的:1リクエスト = 複数件分析
{ custom_id: 'batch-1-10', params: { messages: [{ role: 'user', content: 'レビューA〜J を分析\nレビューA: ...\nレビューB: ...' }] } }

複数のリクエストを 1 つの API リクエストに詰め込むことで、通信回数を削減できます。

② 同じ分析タスクは最初の 1〜2 件でテストする

// テスト: 10件だけバッチ送信して結果を確認
const testBatch = requests.slice(0, 10);
// → 結果がOK なら、全 1,000 件バッチを送信

③ 失敗パターンを事前に検証

不正なフォーマット、トークン超過などのエラーは、本バッチ前に小規模テストで検出しましょう。

全体を振り返ってと次のステップ

Claude API のバッチ処理を使うことで:

  • 費用を最大 90% 削減
  • 大量リクエストを効率的に処理
  • レート制限を気にせず運用

ができるようになります。

バッチ処理は「今すぐ結果が必要」というわけではない、定期的なタスクや研究・分析の場に特に向いています。

さらに詳しく学びたい場合は、Claude API 公式ドキュメントの Batch API セクションや、API 費用最適化ガイドもおすすめです。

まずは小規模なバッチから始めて、本番運用に向けてスケールしていってください!

きっかけは、数千枚の画像に説明文を付ける作業でした

壁紙アプリの素材を整理していたとき、手元には分類待ちの画像が数千枚たまっていました。一枚ずつ Claude に投げて説明文とカテゴリを付けることもできますが、リアルタイムの応答は必要ありません。夜のうちに走らせて、朝に結果が揃っていれば十分です。

こういう「急がないけれど量がある」処理にちょうど合うのが、Claude API の Message Batches です。リクエストをまとめて投げて非同期で処理してもらう仕組みで、通常の API 呼び出しより入出力トークンが 50% 安くなります。私の場合、夜間にまとめておけば、翌朝には全件の結果が手元に届いていました。

以下では単なる API の使い方ではなく、実際にまとまった件数を流したときにつまずいた点と、その回避の仕方を中心にまとめます。

まず最小構成で動かす

最初は 2〜3 件で形を確かめます。custom_id は後で結果を元データに突き合わせるための鍵になるので、必ず意味のある値を入れます。私は画像のファイル名をそのまま使いました。

import anthropic
 
client = anthropic.Anthropic()
 
batch = client.messages.batches.create(
    requests=[
        {
            "custom_id": "wallpaper_0001.jpg",
            "params": {
                "model": "claude-haiku-4-5-20251001",
                "max_tokens": 512,
                "messages": [
                    {"role": "user", "content": "この壁紙画像の雰囲気を一語のカテゴリで分類してください: 夜空に淡い光の輪"}
                ],
            },
        },
        {
            "custom_id": "wallpaper_0002.jpg",
            "params": {
                "model": "claude-haiku-4-5-20251001",
                "max_tokens": 512,
                "messages": [
                    {"role": "user", "content": "この壁紙画像の雰囲気を一語のカテゴリで分類してください: 朝もやの中の山並み"}
                ],
            },
        },
    ]
)
 
print(f"Batch ID: {batch.id}")

分類のような単純なタスクでは、無理に上位モデルを使わず Haiku で十分でした。バッチ割引と合わせると、ここでコストがもう一段下がります。

状態の確認は「ポーリングしすぎない」

作成した直後は処理中です。結果が返るのは数分のこともあれば、混雑時は時間単位のこともあります。ここで数秒おきに叩きにいくと無駄が多いので、私は最初の数分を空けてから、間隔を広げて確認するようにしました。

import time
 
while True:
    batch = client.messages.batches.retrieve(batch.id)
    if batch.processing_status == "ended":
        break
    counts = batch.request_counts
    print(f"処理中… 成功 {counts.succeeded} / 失敗 {counts.errored} / 処理中 {counts.processing}")
    time.sleep(60)
 
print("バッチ完了")

確認したいのは「全部成功したか」ではなく「処理が ended になったか」です。ended になっても、中身には成功と失敗が混在しています。ここを取り違えると、失敗分を取りこぼします。

結果は順番が保証されない — だから custom_id

最初につまずいたのがこれでした。結果は投げた順に返ってくるとは限りません。ストリームで流れてくる一件ずつを、custom_id をキーに元データへ突き合わせる前提で書くのが安全です。

results = {}
 
for item in client.messages.batches.results(batch.id):
    cid = item.custom_id
    if item.result.type == "succeeded":
        results[cid] = item.result.message.content[0].text
    elif item.result.type == "errored":
        # ここで握りつぶさず、再投入リストに積む
        print(f"失敗: {cid} -> {item.result.error}")
        results[cid] = None
    elif item.result.type == "expired":
        # 24時間以内に処理されなかった分
        print(f"期限切れ: {cid}")
        results[cid] = None
 
# custom_id をファイル名にしておいたので、そのまま元画像に紐づく
ok = sum(1 for v in results.values() if v is not None)
print(f"取得 {ok} / {len(results)} 件")

result.type には succeeded 以外に erroredexpiredcanceled があります。expired は 24 時間以内に処理が終わらなかったケースです。実運用では、失敗・期限切れの custom_id だけを集めて、もう一度小さなバッチに分けて投げ直す流れにしておくと、取りこぼしがなくなります。

大量にあるときは分割する

1 つのバッチには最大 10,000 リクエストまで入れられます。私はこれを上限ぎりぎりまで詰めるのではなく、数千件ずつに区切って投げました。理由は単純で、途中で投げ直したくなったときに、巻き戻す単位が小さいほうが扱いやすいからです。ファイル名の連番でチャンクを切り、チャンクごとにバッチ ID をログに残しておくと、後から「どこまで終わったか」が一目で分かります。

def chunk(items, size=2000):
    for i in range(0, len(items), size):
        yield items[i:i + size]
 
for n, group in enumerate(chunk(all_requests)):
    b = client.messages.batches.create(requests=group)
    print(f"chunk {n}: {b.id} ({len(group)}件)")

コストの考え方

バッチ割引は入力・出力の両方のトークンに効きます。私が実際に効いたと感じたのは、次の三つを重ねたときでした。

一つ目は、分類や要約のような定型タスクを Haiku に寄せたこと。二つ目は、max_tokens を実際に必要な長さまで絞ったこと。一語のカテゴリを返すだけなら、512 もあれば十分で、ここを大きくしておく理由はありません。三つ目が、急がない処理をすべてバッチに回したことです。リアルタイム性を捨てられる作業を見極めるほど、月末の請求が静かになっていきました。

逆に、ユーザーの操作に同期して即座に返したい処理までバッチに寄せると、体験を損ないます。バッチは「人が待っていない処理」に絞るのが、私なりの線引きです。

宮大工だった祖父は、材料をまとめて寸法を当たってから一気に刻んでいました。一本ずつ場当たりに切るより、段取りを揃えてから流すほうが、結局きれいに早く終わる。バッチ処理を組んでいると、その感覚に近いものを感じます。

次の一手としては、まず手元の「急がない処理」を一つだけ選んで、2〜3 件の最小バッチで往復を確かめてみてください。custom_id を元データのキーに合わせておけば、そのまま件数を増やしていけます。

シェア

お読みいただきありがとうございます

Claude Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

API & SDK2026-05-31
Claude 非同期パイプラインで「毒メッセージ」を隔離する — デッドレターキュー設計の実装メモ
1件の壊れた入力がバッチ全体を止める「毒メッセージ」問題を、Cloudflare Queues のデッドレターキューで隔離する設計と実装。Claude API 特有の失敗パターンの切り分けまで実体験ベースでまとめます。
API & SDK2026-04-01
Claude API Python asyncio — 非同期処理で並列リクエストを最適化する
Claude API を Python asyncio で非同期・並列処理する方法を徹底解説。複数リクエストの同時実行、レート制限対応、エラーハンドリングまで実践コード付きで紹介します。
API & SDK2026-06-02
MCP の tools 以外の3つの能力を使い分ける:resources・prompts・sampling の設計
MCP サーバーで何でも tools にしてしまう設計の限界を、resources・prompts・sampling という3つの primitive で解きほぐします。壁紙アプリのアセット管理サーバーを題材に、判断基準と実装、クライアント対応の現実的な制約までまとめました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →