steampy
Писал это для себя — хотел сделать бота который показывает статистику друзей в CS2, полез в официальную документацию Steam и чуть не сошёл с ума. Там надо руками собирать URL, разбираться в каком interface/method/version, парсить вложенный JSON... В общем написал обёртку, чтобы больше к этому не возвращаться.
from steampy import SteamClient
steam = SteamClient(api_key="...")
user = steam.user.get_profile("76561198000000000")
print(user.nickname)
games = steam.games.get_owned("76561198000000000")
print(f"игр в библиотеке: {len(games)}")
print(games[0].name, games[0].playtime_hours, "ч") # топ по времени уже отсортирован
Установка
pip install steampy-api
Для async-версии нужен ещё aiohttp:
pip install "steampy-api[async]"
API-ключ
Идёшь на steamcommunity.com/dev/apikey, вводишь любой домен (хоть localhost), получаешь ключ. Бесплатно.
Что умеет
Профили
user = steam.user.get_profile("76561198000000000")
user.nickname # имя
user.country # "RU", "UA", "DE"...
user.is_public # False если профиль закрыт
user.avatar_full # ссылка на аватарку
# если знаешь только ник из url типа steamcommunity.com/id/gaben
steam_id = steam.user.resolve_vanity_url("gaben")
# несколько профилей за один запрос, до 100
profiles = steam.user.get_profiles(["id1", "id2", "id3"])
# VAC-баны
bans = steam.user.get_bans("76561198000000000")
print(bans["VACBanned"]) # True/False
print(bans["NumberOfVACBans"]) # сколько раз
Игры
# библиотека, отсортирована по времени в игре
games = steam.games.get_owned("76561198000000000")
for g in games[:5]:
print(g.name, "—", g.playtime_hours, "ч")
# только то, во что играл последние 2 недели
recent = steam.games.get_recent("76561198000000000")
# достижения. app_id 730 — это CS2
achievements = steam.games.get_achievements("76561198000000000", app_id=730)
done = [a for a in achievements if a.achieved]
print(f"{len(done)} из {len(achievements)}")
# статистика — убийства, смерти, матчи и т.д.
stats = steam.games.get_stats("76561198000000000", app_id=730)
print(stats["total_kills"])
print(stats["total_deaths"])
Друзья
friends = steam.friends.get_list("76561198000000000")
# get_list возвращает только id, профили грузи отдельно
ids = [f.steam_id for f in friends[:100]]
profiles = steam.user.get_profiles(ids)
Маркет
# для маркета ключ не нужен
item = steam.market.get_price(730, "AK-47 | Redline (Field-Tested)")
print(item.lowest_price) # "1 234 ₽"
print(item.median_price) # "1 300 ₽"
print(item.volume) # сколько продали за сутки
# app_id игр которые чаще всего нужны:
# 730 CS2
# 570 Dota 2
# 440 TF2
# 252490 Rust
# 578080 PUBG
Инвентарь
# инвентарь CS2. для других игр меняй app_id
items = steam.inventory.get("76561198000000000", app_id=730)
print(f"предметов: {len(items)}")
for item in items[:5]:
print(item.name, item.rarity)
print(item.get_icon_url()) # ссылка на картинку
print(item.tradable, item.marketable)
# только tradable
tradable = [i for i in items if i.tradable]
# app_id других игр:
# 570 Dota 2
# 440 TF2
# 252490 Rust
# 753 Steam (карточки, фоны, смайлики — context_id=6)
Steam Store
# подробная инфа об игре
game = steam.store.get_game(730)
print(game.name) # Counter-Strike 2
print(game.genres) # ["Экшены", "Бесплатно"]
print(game.metacritic_score) # 83
print(game.platforms) # {"windows": True, "mac": False, "linux": True}
# цена и скидка
game = steam.store.get_game(1091500) # Cyberpunk
print(game.price_original) # 1999.0
print(game.price_final) # 999.5
print(game.discount_percent) # 50
print(game.on_sale) # True
# текущие акции (топ скидок)
sales = steam.store.get_sales()
for s in sales:
print(f"{s.name} -{s.discount_percent}% ({s.price_final}₽)")
# поиск игры по названию
results = steam.store.search("half-life")
for r in results:
print(r["name"], r["id"])
Async (для ботов)
import asyncio
from steampy import AsyncSteamClient
async def main():
async with AsyncSteamClient(api_key="...") as steam:
user = await steam.get_profile("76561198000000000")
print(user.nickname)
games = await steam.get_owned_games("76561198000000000")
print(games[0].name, games[0].playtime_hours, "ч")
asyncio.run(main())
С aiogram:
from steampy import AsyncSteamClient
steam = AsyncSteamClient(api_key="...")
@router.message(Command("profile"))
async def profile_cmd(message: Message):
steam_id = message.text.split()[-1]
user = await steam.get_profile(steam_id)
await message.answer(f"{user.nickname} | {user.country}")
# при остановке бота
async def on_shutdown():
await steam.close()
Несколько запросов параллельно через asyncio.gather:
profile, friends, bans = await asyncio.gather(
steam.get_profile(steam_id),
steam.get_friends(steam_id),
steam.get_bans(steam_id),
)
Кэш
По умолчанию включён с TTL 5 минут — Steam не банит за повторные запросы и не тратишь лимиты на одни и те же данные.
steam = SteamClient(api_key="...", cache_ttl=60) # 1 минута
steam = SteamClient(api_key="...", cache_ttl=0) # выключить кэш
# сбросить вручную
steam.clear_cache()
Работает одинаково для SteamClient и AsyncSteamClient.
Ошибки
from steampy.exceptions import SteamAPIError, SteamRateLimitError, SteamPrivateProfile
try:
user = steam.user.get_profile("76561198000000000")
except SteamPrivateProfile:
print("профиль закрыт")
except SteamRateLimitError:
print("слишком много запросов, подожди")
except SteamAPIError as e:
print(e) # неверный ключ и прочее
except ValueError as e:
print(e) # пользователь не найден
| Исключение | Когда |
|---|---|
SteamAPIError |
базовый класс, неверный ключ, неожиданный ответ сервера |
SteamRateLimitError |
превышен лимит запросов (HTTP 429) |
SteamPrivateProfile |
профиль или инвентарь скрыт (HTTP 403) |
SteamUserNotFound |
пользователь не найден |
ValueError |
неверные входные данные |
Что планирую добавить
- Пагинация для инвентаря (сейчас максимум 5000 предметов)
- Кэш для маркета и инвентаря (сейчас работает только для основного API)
Если нашёл баг
Открывай issue, постараюсь ответить. PR тоже принимаю.
MIT
Metadata
Release files for steampy-api 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| steampy_api-0.2.1.tar.gz | 18.3 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| steampy_api-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 37.6 kB
Release files / steampy_api-0.2.1.tar.gz
| Download URL | steampy_api-0.2.1.tar.gz |
|---|---|
| Size | 18.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8d2698846ce2f3bd587df99fb165db4af5f5328365c30731694b5d6af77aabcc
|
|
BLAKE2b-256 checksum How to use checksums |
1e802474c2804485e721fc14f6453b87783b6279d2dac365f1ad60b497dc3e10
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.2
|
Release files / steampy_api-0.2.1-py3-none-any.whl
| Download URL | steampy_api-0.2.1-py3-none-any.whl |
|---|---|
| Size | 19.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
628f6857292fedac092558e92cd60509d894f2a42f887624f13d3e5d52da6a28
|
|
BLAKE2b-256 checksum How to use checksums |
7992851efa459fd67935cc1055a9e90649c8d0f8a67bbe682cb1d36e9bf9a674
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.2
|
Security for steampy-api 0.2.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.