AI業務活用 2026.04.22
Claude API高額請求を防ぐ4つの方法【2026年版】レート制限・使用量監視・バジェットアラート実装
高額請求が起きる典型パターン
# ❌ 危険なコード(無限ループ)
while True: # ← 止まらない
response = client.messages.create(
model="claude-opus-5", # 最高額モデル
max_tokens=4096, # 最大出力
messages=[{"role": "user", "content": large_file}] # 大きなファイル
)
# エラーハンドリングなし → 例外で止まらない
# ✅ 安全なコード
MAX_CALLS = 100
calls = 0
while calls < MAX_CALLS:
try:
response = client.messages.create(
model="claude-haiku-4-5-20251001", # コスト最小のモデルを選ぶ
max_tokens=512, # 必要最小限のmax_tokens
messages=[{"role": "user", "content": prompt[:5000]}] # 入力を制限
)
calls += 1
except Exception as e:
print(f"エラー: {e}")
break # エラーで停止
対策1: レート制限ラッパー
# rate_limiter.py
# APIコールに1日の上限とレート制限を設けるラッパー
import time
import json
from pathlib import Path
from datetime import date
import anthropic
client = anthropic.Anthropic()
class BudgetedClaude:
"""コスト上限付きのClaude APIラッパー"""
PRICES = {
"claude-haiku-4-5-20251001": (0.80, 4.00),
"claude-sonnet-4-5": (3.00, 15.00),
"claude-opus-5": (15.00, 75.00),
}
def __init__(self, daily_budget_usd: float = 5.0, min_interval_s: float = 1.0):
self.daily_budget_usd = daily_budget_usd
self.min_interval_s = min_interval_s
self._last_call = 0.0
self._stats_file = Path(".claude_usage.json")
def _load_today_cost(self) -> float:
if not self._stats_file.exists():
return 0.0
stats = json.loads(self._stats_file.read_text())
if stats.get("date") != str(date.today()):
return 0.0
return stats.get("cost_usd", 0.0)
def _save_cost(self, additional_cost: float) -> None:
today_cost = self._load_today_cost() + additional_cost
self._stats_file.write_text(json.dumps({
"date": str(date.today()),
"cost_usd": today_cost
}))
def create(self, model: str, max_tokens: int, messages: list) -> dict:
"""予算チェック付きAPIコール"""
# 予算チェック
today_cost = self._load_today_cost()
if today_cost >= self.daily_budget_usd:
raise RuntimeError(f"1日の予算上限 ${self.daily_budget_usd} に達しました(使用額: ${today_cost:.2f})")
# レート制限(最小間隔)
elapsed = time.time() - self._last_call
if elapsed < self.min_interval_s:
time.sleep(self.min_interval_s - elapsed)
response = client.messages.create(
model=model, max_tokens=max_tokens, messages=messages
)
# コスト記録
inp, out = self.PRICES.get(model, (3.00, 15.00))
cost = (response.usage.input_tokens * inp + response.usage.output_tokens * out) / 1_000_000
self._save_cost(cost)
self._last_call = time.time()
print(f"[コスト] この呼び出し: ${cost:.4f} / 今日の合計: ${self._load_today_cost():.2f} / 上限: ${self.daily_budget_usd}")
return response
# 使用例
budgeted = BudgetedClaude(daily_budget_usd=2.0)
response = budgeted.create(
model="claude-haiku-4-5-20251001",
max_tokens=512,
messages=[{"role": "user", "content": "こんにちは"}]
)
対策2: Batches APIで50%削減
# batch_processing.py
# リアルタイム不要な処理はBatches APIで半額にする
import anthropic
client = anthropic.Anthropic()
def create_analysis_batch(items: list[str]) -> str:
"""大量のテキストをバッチ処理(通常料金の50%)"""
requests = [
{
"custom_id": f"item-{i}",
"params": {
"model": "claude-haiku-4-5-20251001",
"max_tokens": 256,
"messages": [{
"role": "user",
"content": f"以下のレビューを「ポジティブ」「ネガティブ」「ニュートラル」に分類してください: {item}"
}]
}
}
for i, item in enumerate(items)
]
batch = client.beta.messages.batches.create(requests=requests)
print(f"バッチID: {batch.id}")
print(f"件数: {len(items)}件(通常料金の50%で処理)")
return batch.id
# 1000件のレビューを分類(通常$0.40 → バッチで$0.20)
reviews = ["素晴らしい!", "最悪でした", "普通です"] * 333
batch_id = create_analysis_batch(reviews)
対策3: コンソールで予算上限を設定する
Anthropicコンソール → Billing → Usage Limits で設定:
月間上限例:
開発環境: $10/月
ステージング: $50/月
本番(小規模): $200/月
本番(大規模): 要検討
上限到達時: APIが自動停止(429エラー)
→ コード側で429を適切にハンドリングする