Metadata-Version: 2.5
Name: steamdataapi
Version: 1.0.0
Summary: Steam Market API and Steam Inventory API client for Python — live CS2 and Rust skin prices from Steam and 10 marketplaces, daily price history back to 2013, and whole-inventory valuation with floats. Zero dependencies.
Project-URL: Homepage, https://steamdataapi.com
Project-URL: Documentation, https://steamdataapi.com/docs
Project-URL: Get an API key, https://steamdataapi.com/app
Project-URL: Source, https://github.com/Frobski/steamdataapi-python
Project-URL: Issues, https://github.com/Frobski/steamdataapi-python/issues
Project-URL: Changelog, https://github.com/Frobski/steamdataapi-python/blob/main/CHANGELOG.md
Author-email: Steam Data API <support@steamdataapi.com>
License: MIT
License-File: LICENSE
Keywords: api client,buff163,cs2,cs2 market api,cs2 skin api,csfloat,csgo,doppler,float,inventory,rust,rust market api,rust skin api,sdk,skin prices,skinport,skins,steam,steam api,steam inventory api,steam market api,trading bot
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Games/Entertainment
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.9
Provides-Extra: async
Requires-Dist: httpx>=0.25; extra == 'async'
Provides-Extra: dev
Requires-Dist: build>=1.0; extra == 'dev'
Requires-Dist: httpx>=0.25; extra == 'dev'
Requires-Dist: pytest>=7; extra == 'dev'
Description-Content-Type: text/markdown

# steamdataapi

**Steam Market API and Steam Inventory API client for Python.**

Live CS2 and Rust skin prices from the Steam Community Market and 10 third-party marketplaces (Skinport, CSFloat, Buff163, DMarket, Waxpeer, Lis-Skins, SkinBaron, WhiteMarket, YouPin, C5Game), daily price history back to 2013, Doppler phase prices, case drop tables, and whole-inventory valuation with floats and patterns — through one small client with **no dependencies**.

Backed by [steamdataapi.com](https://steamdataapi.com). Free API key, no card.

```bash
pip install steamdataapi            # sync client, standard library only
pip install "steamdataapi[async]"   # adds the httpx-based AsyncSteamDataApi
```

Python 3.9+.

## Quick start

```python
from steamdataapi import SteamDataApi

api = SteamDataApi("sdk_your_api_key")  # https://steamdataapi.com/app

# One item — every price field, plus where it is cheapest right now
item = api.items.get("AK-47 | Redline (Field-Tested)", game="cs2")
print(item["prices"]["best"], item["prices"]["bestSource"])  # 1690 'csfloat'  (integer cents)

# A whole public inventory, valued — with floats, pattern seeds and Doppler phases
inv = api.inventory("76561198305185709", game="cs2", currency="EUR")
print(inv["summary"]["totalValue"]["steamPrice"], len(inv["items"]))

# 30 days of daily prices on every marketplace
history = api.items.history("★ Karambit | Doppler (Factory New)", source="markets", days=30)
print(list(history["markets"]))  # ['steam', 'skinport', 'csfloat', …]
```

All prices are **integers in minor units** (cents) of the response's `currency`, never floats. A price is `None` when a market has no current listing.

## What's covered

| Method | Endpoint | Notes |
| --- | --- | --- |
| `api.items.get(name, ...)` | `GET /items/:name` | Metadata, all price fields, Doppler `variants`; `markets=True` embeds per-marketplace rows |
| `api.items.all(...)` | `GET /items/all` | The price sheet — every item for a game in one call (~4 MB) |
| `api.items.prices(names, ...)` | `POST /items/prices` | Up to 500 items in one request |
| `api.items.markets(name, ...)` | `GET /items/:name/markets` | Every marketplace's current price, the best one and the spread |
| `api.items.markets_bulk(names, ...)` | `POST /items/markets` | Same, up to 100 items |
| `api.items.history(name, ...)` | `GET /items/:name/history` | `source="steam" \| "markets" \| "phases"`; `days` or `from_`/`to`; `metric="close" \| "low" \| "avg"` |
| `api.items.history_bulk(names, ...)` | `POST /items/history` | Per-market daily series, up to 100 items |
| `api.inventory(steamid, ...)` | `GET /inventory/:steamid` | SteamID64, profile URL or vanity name; `fresh=True` bypasses the cache; `markets=True` adds per-market rows |
| `api.collections.list(...)` / `.get(name)` | `GET /collections[/:name]` | Collections with set icons; items inside one collection |
| `api.crates.list(...)` / `.get(name)` | `GET /crates[/:name]` | Cases, capsules and packages with full drop tables; `rare="only"` for the knife/glove pool |
| `api.currencies()` · `api.plans()` | `GET /currencies` · `/plans` | Accepted currency codes; plan limits |

Every method returns the API's JSON as a `dict`. Full reference with every parameter and a sample response for each: [steamdataapi.com/docs](https://steamdataapi.com/docs).

## Examples

**Cheapest marketplace for a list of items** — one request, not a hundred:

```python
res = api.items.markets_bulk(["AWP | Asiimov (Field-Tested)", "M4A4 | Howl (Minimal Wear)"], game="cs2")
for row in res["data"]:
    if row["found"]:
        print(row["marketHashName"], row["best"]["market"], row["best"]["price"], "spread", row["spread"])
print("not in catalog:", res["missing"])
```

**Mirror every price locally** — poll the sheet, join by `marketHashName`:

```python
sheet = api.items.all(game="cs2")
by_name = {r["marketHashName"]: r["prices"] for r in sheet["data"]}
print(sheet["count"], "items as of", sheet["cachedAt"])
```

**Value an inventory in your currency**, with the uncapped third-party total:

```python
inv = api.inventory("https://steamcommunity.com/id/someone", currency="EUR", markets=True)
print("Steam:", inv["summary"]["totalValue"]["steamPrice"] / 100, "EUR")
print("Markets:", inv["summary"]["totalValue"].get("realAvg", 0) / 100, "EUR")
for it in inv["items"]:
    print(it["marketHashName"], it.get("float"), it.get("phase") or "", it["prices"].get("value"))
```

**Rust works the same way** — pass `game="rust"`:

```python
rust = api.items.all(game="rust")                      # every Rust item, priced
door = api.items.get("Metal Door", game="rust")
```

## Async

```python
import asyncio
from steamdataapi import AsyncSteamDataApi

async def main():
    async with AsyncSteamDataApi("sdk_your_api_key") as api:
        sheet, inv = await asyncio.gather(
            api.items.all(game="cs2"),
            api.inventory("76561198305185709"),
        )
        print(sheet["count"], inv["summary"]["totalValue"])

asyncio.run(main())
```

The async client mirrors the sync one method for method and needs `httpx` (`pip install "steamdataapi[async]"`).

## Errors and retries

Every non-2xx response raises `SteamDataApiError` carrying the API's `error` code and message, plus a few helpers:

```python
from steamdataapi import SteamDataApiError

try:
    api.items.history("x", source="markets")
except SteamDataApiError as e:
    e.status             # 429
    e.code               # 'quota_exceeded'
    e.quota_group        # 'history' — which endpoint group ran out
    e.is_quota_exceeded  # True — do not retry until it resets
    e.is_rate_limited    # per-minute limiter — the client already retried this
    e.is_plan_forbidden  # endpoint not in your plan
    e.reason             # for 401: 'missing' | 'scheme' | 'api_key' | 'session'
```

The client **retries automatically** — honouring `Retry-After` — on the per-minute rate limit, on Steam's transient `503 rate_limited` during inventory reads, on 502/504 and on connection failures. It never retries an exhausted daily or monthly quota. Tune with `max_retries` (default 2) and `timeout` (default 30 s).

## Options

```python
api = SteamDataApi(
    "sdk_…",
    currency="EUR",                               # default for every price-bearing call; per-call currency wins
    timeout=30.0,
    max_retries=2,
    base_url="https://steamdataapi.com/api/v1",  # self-hosted instances
    headers={"X-Trace": "…"},
)
```

`transport=` accepts any callable `(method, url, headers, body, timeout) -> (status, headers, raw_bytes)` if you want to route requests through your own HTTP stack or stub them in tests.

## Links

- Docs: https://steamdataapi.com/docs
- Get a key: https://steamdataapi.com/app
- Pricing and per-endpoint limits: https://steamdataapi.com/pricing
- CS2 skin API: https://steamdataapi.com/cs2-api · Rust skin API: https://steamdataapi.com/rust-api
- Steam market API: https://steamdataapi.com/steam-market-api · Steam inventory API: https://steamdataapi.com/steam-inventory-api
- Node.js client: https://www.npmjs.com/package/steamdataapi

## License

MIT © Steam Data API. Not affiliated with Valve or Steam.
