この記事でできること:SteamのStorefront appdetails(非公開仕様)を使って、価格・割引・ジャンル/タグ・発売情報・対応OSなどのストア情報をPythonで取得し、記事やダッシュボードで使いやすい形に整えます。前回の Step2: 公式Web API と併用し、ストア由来の“見せる情報”を補完します。
全体の位置づけは Steamガイド(入口ページ)、AppIDの基本は Step1: AppIDの見つけ方 を参照してください。
appdetailsとは(要点)
- エンドポイント:
https://store.steampowered.com/api/appdetails?appids=<APPID>&cc=jp&l=japanese - 非公開仕様のため、将来的な変更リスクあり(堅牢化と監視が前提)。
- 価格情報(
price_overview)、タグ/ジャンル、発売日、対応プラットフォーム(Win/Mac/Linux)、スクショ/動画URL 等を返します。 typeでgame/dlc/softwareなどを判定できます(DLC/サントラの誤選択を回避)。- 地域/言語は
cc(国)とl(言語)で切替(例:cc=jp,l=japanese)。
よく使うフィールド(抜粋)
| 欲しい情報 | JSONパス例 | 補足 |
|---|---|---|
| 正式名称 | data.name | 言語 l に依存 |
| タイプ(game/dlc/...) | data.type | DLC/バンドル除外に重要 |
| 発売日 | data.release_date.date | coming_soon で未発売判定 |
| 価格/割引 | data.price_overview.final | final_formatted(例:¥1,980)も便利 |
| 対応OS | data.platforms.{windows,mac,linux} | 真偽値 |
| ジャンル | data.genres[].description | 上位ジャンル |
| タグ | data.categories[].description | “マルチプレイ”などカテゴリ側にも特徴 |
| サムネ/スクショ | data.header_image, data.screenshots[] | 記事のOGP/カード化に |
| メタスコア | data.metacritic.score | 無い場合もあり |
| おすすめ件数 | data.recommendations.total | “レビュー総量”の目安 |
クイックスタート(Python最小サンプル)
1タイトルを取得して主要項目を抜き出す
import requests
def appdetails(appid:int, cc="jp", lang="japanese"):
url = "https://store.steampowered.com/api/appdetails"
r = requests.get(url, params={"appids": appid, "cc": cc, "l": lang}, timeout=30).json()
node = r.get(str(appid), {})
if not node.get("success"):
return None
return node.get("data")
def pick_fields(d):
if not d: return {}
price = (d.get("price_overview") or {})
return {
"name": d.get("name"),
"type": d.get("type"),
"release_date": (d.get("release_date") or {}).get("date"),
"coming_soon": (d.get("release_date") or {}).get("coming_soon"),
"is_free": d.get("is_free"),
"price_final": price.get("final"),
"price_currency": price.get("currency"),
"price_display": price.get("final_formatted"),
"platforms": {k:v for k,v in (d.get("platforms") or {}).items()},
"genres": [g.get("description") for g in (d.get("genres") or [])],
"categories": [c.get("description") for c in (d.get("categories") or [])],
"header_image": d.get("header_image"),
"metacritic": (d.get("metacritic") or {}).get("score"),
"recommendations": (d.get("recommendations") or {}).get("total"),
}
appid = 2420510 # 例:HoloCure
data = appdetails(appid)
print(pick_fields(data))
実行結果を確認
{'name': 'HoloCure - Save the Fans!', 'type': 'game', 'release_date': '2023年8月16日', 'coming_soon': False, 'is_free': True, 'price_final': None, 'price_currency': None, 'price_display': None, 'platforms': {'windows': True, 'mac': False, 'linux': False}, 'genres': ['アクション', 'アドベンチャー', 'カジュアル', 'インディー'], 'categories': ['シングルプレイヤー', 'Steam実績', '部分的コントローラサポート', 'Steamクラウド'], 'header_image': 'https://shared.akamai.steamstatic.com/store_item_assets/steam/apps/2420510/header.jpg?t=1740642230', 'metacritic': None, 'recommendations': None}
複数タイトルを一括取得(ループ)→ DataFrame化
import time, pandas as pd
def fetch_many(appids:list[int], cc="jp", lang="japanese", sleep=0.3):
rows = []
for aid in appids:
d = appdetails(aid, cc=cc, lang=lang)
row = {"appid": aid} | pick_fields(d)
rows.append(row)
time.sleep(sleep) # マナー
return pd.DataFrame(rows)
df = fetch_many([570, 730, 1172470]) # Dota2, CS2, Apex
print(df[["appid","name","price_display","release_date","platforms"]])
実行結果を確認
appid name price_display release_date \
0 570 Dota 2 None 2013年7月9日
1 730 Counter-Strike 2 None 2012年8月21日
2 1172470 エーペックスレジェンズ None 2020年11月4日
platforms
0 {'windows': True, 'mac': True, 'linux': True}
1 {'windows': True, 'mac': False, 'linux': True}
2 {'windows': True, 'mac': False, 'linux': False}
非公開仕様のため「まとめ取得」の挙動は将来変わる可能性があります。堅実なのは“1タイトルずつ”のループです。
DLC/バンドルの誤選択を避けるチェックリスト
data.type == "game"を基本条件に(DLCやmusicを除外)。data.fullgameが存在する場合は“本体に紐づく追加物”の可能性。data.dlcの配列が長い=本体である可能性が高い(逆にDLC側はfullgameを持つ)。- 名称が近い候補は Step1 の手順(あいまい一致→appdetails検証)で確定。
地域・言語(cc / l)の指定
日本向け表示にするには cc=jp と l=japanese を付けます。価格通貨や説明文が日本語に寄ります。グローバル比較をする場合は、cc/lを固定して集計するのが無難です。
- 例:
?appids=730&cc=jp&l=japanese - 北米比較用:
?cc=us&l=english
堅牢化のコツ(実務)
- successフラグを必ず確認(
success==Trueでない場合はデータ無し扱い)。 - ネットワーク/一時的障害に備えてリトライ+タイムアウト。
- レスポンスが大きいのでローカルキャッシュ(例:日次更新)。
- キー存在チェック(
get(...,{}))で欠損に強く。 - スクショURLは枚数制限して保存(記事での読み込みを軽くする)。
- 価格履歴・CCU履歴はappdetails単体では取れないため、別記事(CCU時系列)や外部参照で補完。
小ワザ:記事カード用の最小データ整形
カード辞書の例(タイトル・価格・タグ上位3・ヘッダー画像)
def to_card(d:dict):
if not d: return {}
tags = [c.get("description") for c in (d.get("categories") or [])][:3]
price = (d.get("price_overview") or {})
return {
"title": d.get("name"),
"price": price.get("final_formatted") or ("無料" if d.get("is_free") else None),
"tags": " / ".join(tags),
"img": d.get("header_image"),
"release": (d.get("release_date") or {}).get("date")
}
card = to_card(appdetails(730))
print(card)
実行結果を確認
{'title': 'Counter-Strike 2', 'price': '無料', 'tags': 'マルチプレイヤー / クロスプラットフォームマルチプレイヤー / Steamトレーディングカード', 'img': 'https://shared.akamai.steamstatic.com/store_item_assets/steam/apps/730/header.jpg?t=1749053861', 'release': '2012年8月21日'}
カード化は Steamガイド の「やりたいこと別」導線にも流用できます。
よくある質問(FAQ)
- Q. 一括取得は可能?
A. 将来的な互換性のため、ループで1件ずつ取得する方針を推奨します(非公開仕様のため)。 - Q. 年齢制限タイトルで取れないことがある?
A. Store側の判定により情報が薄くなる場合があります。取得失敗時はリトライ+代替の地域/言語で再試行し、最終的に欠損処理。 - Q. 正式タグはどこに?
A.genresは上位ジャンル、categoriesは“機能タグ”に近い(マルチプレイ対応 等)。より“人気度”を見る場合は SteamSpy 側のタグ集計も併用。
この先に進む(関連How-to)
入口に戻る:Steamガイド / 前の記事:Steam公式Web APIの使い方 / さらに前:AppIDの見つけ方
免責とポリシー:appdetails は公式ドキュメント外のエンドポイントです。挙動は予告なく変わる可能性があります。利用規約・法令・引用ルールを遵守の上でご利用ください。