API VERSION 1

Steam inventories,
minus the sharp edges.

ItemData exposes fresh, normalized Steam inventory data through one cursor-paginated HTTP endpoint with a stable response model.

BASE URL/v1HTTPS
Durable caching for public inventories.

Normal public requests can reuse a durable page snapshot. Use no_cache=true to force a coordinated refresh; requests carrying a Steam session bypass shared-cache reads and writes.

Credit pricing

Base cost: 1 credit per successful inventory page or confirmed private result. no_cache=true, try_first_seven_days_blocked_items=true, steam_login_secure, or trade_url add +1 credit for a billable result. Fresh-fetch additions never stack, so the maximum price is 2 credits per request. Failed requests and non-authoritative success=false results cost 0; confirmed Steam HTTP 403 results use normal pricing.

01 · QUICKSTART

Make your first request

Create a key in the dashboard, keep it in an environment variable, then send it as a Bearer token. A successful call returns one Steam page with assets and descriptions; continue with its cursor.

RequestcURL
curl "/v1/inventory?steam_id=76561198000000000&game=cs2" \
  -H "Authorization: Bearer $ITEMDATA_API_KEY"
02 · AUTHENTICATION

Keep the key server-side

Send your key in the Authorization header. Query-string keys are supported for compatibility, but Bearer authentication avoids leaking credentials into logs and browser history.

RecommendedAuthorization: Bearer isk_…
Never expose keys

Call ItemData from your backend, not public browser code.

03 · ENDPOINT
GET

/inventory

Fetch one inventory using a SteamID64, SteamID3, SteamID2, vanity name, or Steam Community profile URL.

A single-inventory request returns exactly one Steam page. Follow the cursor to retrieve another page.

Do not send last_assetid after a response with more_items=false: that response is terminal and has no next page.

API authentication is required through Authorization: Bearer or the legacy key query parameter. steam_id is required only when neither a Steam login cookie nor a trade URL supplies the target. Every other inventory query parameter is optional; defaults are documented below.

Each accepted query parameter may appear only once. Unknown parameters are rejected with HTTP 400 before credit reservation or any Steam request.

PARAMETERTYPEDESCRIPTION
steam_idstringConditionally required. Accepts a SteamID64, SteamID3, SteamID2, vanity name, or Steam Community profile URL. Omit it when a Steam login cookie or trade URL supplies the target; it is ignored when either credential supplies it.
gameenumOptional. One of cs2, rust, dota2, tf2, or pubg. dota is accepted as an alias for dota2. Defaults to cs2.
languagestringOptional. Language requested from Steam for descriptions. Defaults to english.
start_assetidstringOptional. Omit for the first page. For a later page, use the exact last_assetid cursor from the preceding response only when more_items is true.
include_non_tradablebooleanOptional; defaults to false. Include assets that cannot currently be traded.
no_cachebooleanBypasses the default 3-day shared cache and fetches fresh inventory data directly from Steam. Adds +1 credit to a billable request. Default: 0.
try_first_seven_days_blocked_itemsbooleanCS2 only. Tries the trade inventory first to include 7–10 day trade-locked items, then falls back to the normal inventory when the partner path cannot return a usable first page. This may increase response time and failure rate. Adds +1 credit to a billable request. Default: 0.
steam_login_securestringOptional. Preferred header: X-Steam-Login-Secure. A structurally valid cookie must contain its owner SteamID64. It is supported for every game; for CS2, it fetches that authorized owner's inventory without the normal 10-day visibility delay. It bypasses shared cache state. Additional cost: +1 credit for a billable result, including a confirmed Steam HTTP 403.
trade_urlstringOptional. Preferred header: X-Steam-Trade-URL. CS2 only. Accepts a canonical HTTPS steamcommunity.com/tradeoffer/new/ URL with partner and token, derives the target from partner, includes 7–10 day trade-locked items, and bypasses shared cache state. Additional cost: +1 credit after success. It cannot be combined with try_first_seven_days_blocked_items.
with_no_tradablealiasbooleanOptional; defaults to false. Equivalent switches for including non-tradable assets; if both are supplied, their values must match.
formatenumOptional; defaults to json. Accepted values are json, prettyjson, or pretty. All variants return JSON.
prettyaliasbooleanOptional; defaults to false. Set to true or 1 for indented JSON output; alias for a pretty format.
Response headers
X-ItemData-More-Itemsmore_items
X-ItemData-Next-Cursorlast_assetid
X-ItemData-CacheHIT, MISS, STALE, or BYPASS for the public page or account-wide private state returned.
X-ItemData-Inventory-Sourcepublic for the normal endpoint, partner when the internal session pool succeeded, or public-fallback when the first partner page fell back to a fresh public request.
AgeWhole seconds since the public page or confirmed private state was observed at Steam.
X-ItemData-Billing-Statusconfirmed after durable accounting. A rare pending value means the successful payload is returned while an ambiguous database COMMIT is handled with at-most-once billing; charged-credit headers are then omitted.
X-ItemData-Credits-ChargedActual total charged for a billable result: 1 base credit plus at most 1 fresh-fetch credit, with a maximum of 2. Present only for confirmed billing.
X-ItemData-Credit-Pricing-VersionVersion of the server-side credit rules used for this request.
Request cookbook

Examples for every parameter

These examples cover every accepted inventory query parameter without combining incompatible modes. In Python, the GET query is passed as params=payload; it is not a JSON request body. Query payloads are serialized into the URL, so keep live secrets in environment variables and prefer the documented credential headers in production.

Public inventory with explicit options

cURL · public page

Fetch a fresh Dota 2 page, include non-tradable items, choose the Steam response language, and request indented JSON.

  • key
  • steam_id
  • game
  • language
  • include_non_tradable
  • no_cache
  • format
RequestcURL · public page
curl --fail-with-body --include --get \
  -H "Authorization: Bearer $ITEMDATA_API_KEY" \
  --data-urlencode "steam_id=76561198000000000" \
  --data-urlencode "game=dota2" \
  --data-urlencode "language=english" \
  --data-urlencode "include_non_tradable=true" \
  --data-urlencode "no_cache=true" \
  --data-urlencode "format=prettyjson" \
  "/v1/inventory"
RequestPython · payload
import os
import requests

payload = {
    "key": os.environ["ITEMDATA_API_KEY"],
    "steam_id": "76561198000000000",
    "game": "dota2",
    "language": "english",
    "include_non_tradable": True,
    "no_cache": True,
    "format": "prettyjson",
}

response = requests.get(
    "/v1/inventory",
    params=payload,
    timeout=30,
)
response.raise_for_status()
print(response.json())

no_cache=true bypasses shared cache state. Additional cost: +1 credit for a billable result, including a confirmed Steam HTTP 403.

Next public page with compatibility aliases

cURL · next page

Continue the same Dota 2 inventory using the exact cursor returned by the previous response. Preserve every option that defines the page.

  • key
  • steam_id
  • game
  • language
  • start_assetid
  • with_no_tradable
  • pretty
RequestcURL · next page
curl --fail-with-body --include --get \
  -H "Authorization: Bearer $ITEMDATA_API_KEY" \
  --data-urlencode "steam_id=76561198000000000" \
  --data-urlencode "game=dota" \
  --data-urlencode "language=english" \
  --data-urlencode "start_assetid=$NEXT_CURSOR" \
  --data-urlencode "with_no_tradable=true" \
  --data-urlencode "pretty=true" \
  "/v1/inventory"
RequestPython · payload
import os
import requests

payload = {
    "key": os.environ["ITEMDATA_API_KEY"],
    "steam_id": "76561198000000000",
    "game": "dota",
    "language": "english",
    "start_assetid": os.environ["NEXT_CURSOR"],
    "with_no_tradable": True,
    "pretty": True,
}

response = requests.get(
    "/v1/inventory",
    params=payload,
    timeout=30,
)
response.raise_for_status()
print(response.json())

dota is an alias for dota2. with_no_tradable aliases include_non_tradable, and pretty=true aliases indented JSON output.

Try recently trade-blocked CS2 items first

cURL · blocked-item mode

Try the internal Steam-session pool before a fresh public fallback. The mode automatically includes non-tradable items.

  • key
  • steam_id
  • game
  • language
  • try_first_seven_days_blocked_items
RequestcURL · blocked-item mode
curl --fail-with-body --include --get \
  -H "Authorization: Bearer $ITEMDATA_API_KEY" \
  --data-urlencode "steam_id=76561198000000000" \
  --data-urlencode "game=cs2" \
  --data-urlencode "language=english" \
  --data-urlencode "try_first_seven_days_blocked_items=true" \
  "/v1/inventory"
RequestPython · payload
import os
import requests

payload = {
    "key": os.environ["ITEMDATA_API_KEY"],
    "steam_id": "76561198000000000",
    "game": "cs2",
    "language": "english",
    "try_first_seven_days_blocked_items": True,
}

response = requests.get(
    "/v1/inventory",
    params=payload,
    timeout=30,
)
response.raise_for_status()
print(response.json())

Additional cost: +1 credit for a billable result, including a confirmed Steam HTTP 403 from public fallback. For the next cursor, retain this flag only after X-ItemData-Inventory-Source: partner; omit it after public-fallback.

Inventory authorized by steamLoginSecure

cURL · caller Steam session

Fetch the cookie owner's inventory. The owner SteamID64 is read from the cookie, so steam_id is not required and would be ignored.

  • key
  • steam_login_secure
  • game
  • language
  • format
  • X-Steam-Login-Secure
RequestcURL · caller Steam session
curl --fail-with-body --include --get \
  -H "Authorization: Bearer $ITEMDATA_API_KEY" \
  -H "X-Steam-Login-Secure: $STEAM_LOGIN_SECURE" \
  --data-urlencode "game=rust" \
  --data-urlencode "language=english" \
  --data-urlencode "format=json" \
  "/v1/inventory"
RequestPython · payload
import os
import requests

payload = {
    "key": os.environ["ITEMDATA_API_KEY"],
    "steam_login_secure": os.environ["STEAM_LOGIN_SECURE"],
    "game": "rust",
    "language": "english",
    "format": "json",
}

response = requests.get(
    "/v1/inventory",
    params=payload,
    timeout=30,
)
response.raise_for_status()
print(response.json())

Repeat X-Steam-Login-Secure on every cursor request. This fresh BYPASS mode supports every listed game. Additional cost: +1 credit for a billable result, including a confirmed Steam HTTP 403.

CS2 inventory authorized by a Trade URL

cURL · Trade URL

Fetch the partner inventory through the authenticated trade path. The target SteamID64 is derived from partner, so steam_id is not required and would be ignored.

  • key
  • trade_url
  • game
  • language
  • format
  • X-Steam-Trade-URL
RequestcURL · Trade URL
curl --fail-with-body --include --get \
  -H "Authorization: Bearer $ITEMDATA_API_KEY" \
  -H "X-Steam-Trade-URL: $STEAM_TRADE_URL" \
  --data-urlencode "game=cs2" \
  --data-urlencode "language=english" \
  --data-urlencode "format=json" \
  "/v1/inventory"
RequestPython · payload
import os
import requests

payload = {
    "key": os.environ["ITEMDATA_API_KEY"],
    "trade_url": os.environ["STEAM_TRADE_URL"],
    "game": "cs2",
    "language": "english",
    "format": "json",
}

response = requests.get(
    "/v1/inventory",
    params=payload,
    timeout=30,
)
response.raise_for_status()
print(response.json())

Repeat X-Steam-Trade-URL on every cursor request. This mode is CS2-only and never falls back to the public endpoint. Additional cost: +1 credit after success.

Legacy credential query forms

Reference only · do not execute

Syntax reference only. These aliases remain compatible, but credentials in URLs can leak through history and access logs.

  • key
  • steam_login_secure
  • trade_url
RequestReference only · do not execute
GET /v1/inventory?key=REDACTED_NON_WORKING_KEY&steam_login_secure=REDACTED_NON_WORKING_COOKIE
GET /v1/inventory?key=REDACTED_NON_WORKING_KEY&trade_url=REDACTED_NON_WORKING_URL
RequestPython · payload
import requests

# Syntax reference only: replace these values through your secret manager.
payload = {
    "key": "REDACTED_NON_WORKING_KEY",
    "steam_login_secure": "REDACTED_NON_WORKING_COOKIE",
    "game": "cs2",
}

response = requests.get(
    "/v1/inventory",
    params=payload,
    timeout=30,
)
print(response.status_code)

Use Authorization: Bearer, X-Steam-Login-Secure, and X-Steam-Trade-URL in production. Never place live credentials in a URL.

LIVE EXPLORER

Try the endpoint

Enter your own key to send a real request. The key stays in this page's memory and is never saved by the explorer.

GET/v1/inventory?game=cs2&pretty=1&steam_id=76561198000000000
Steam credentials stay in this page's memory, are sent only in request headers, and are never added to the URL. ItemData does not persist them.Sent only to your configured ItemData API origin and never stored.
ResponseExample response
{
  "success": true,
  "steam_id": "76561198000000000",
  "game": "cs2",
  "appid": 730,
  "total_inventory_count": 184,
  "items": [
    {
      "assetid": "34589211402",
      "market_hash_name": "AK-47 | Slate (Field-Tested)",
      "tradable": true
    }
  ],
  "last_assetid": "34589211402",
  "more_items": true
}
04 · STEAMWEBAPI COMPATIBILITY

Compatible where semantics stay honest

ItemData accepts SteamWebAPI-style parameters when their semantics match, including no_cache=true for a forced public refresh. It rejects or omits only unsupported enrichment and global operations.

Open the SteamWebAPI inventory reference

Supported compatibility

start_assetidLive Steam cursor from last_assetid, valid only while more_items is true.
include_non_tradable / with_no_tradableEquivalent switches for including non-tradable assets; if both are supplied, their values must match.
pretty=1Returns indented JSON; the response format remains JSON.
game=dotaAccepted as an alias for dota2.
steam_login_secure / X-Steam-Login-SecureOptional. Preferred header: X-Steam-Login-Secure. A structurally valid cookie must contain its owner SteamID64. It is supported for every game; for CS2, it fetches that authorized owner's inventory without the normal 10-day visibility delay. It bypasses shared cache state. Additional cost: +1 credit for a billable result, including a confirmed Steam HTTP 403.
trade_url / X-Steam-Trade-URLOptional. Preferred header: X-Steam-Trade-URL. CS2 only. Accepts a canonical HTTPS steamcommunity.com/tradeoffer/new/ URL with partner and token, derives the target from partner, includes 7–10 day trade-locked items, and bypasses shared cache state. Additional cost: +1 credit after success. It cannot be combined with try_first_seven_days_blocked_items.
no_cacheSupported for public inventories. true forces a fresh upstream fetch. Additional cost: +1 credit for a billable result, including a confirmed Steam HTTP 403.
try_first_seven_days_blocked_itemsSupported for CS2. On a partner response, continue with the flag and returned cursor. After public-fallback, continue with the public cursor without this flag.

Not supported

stateItemData does not expose an alternate inventory-state selector.
parse, raw, mode, currency, markets, with_prices, phase, sort-by-priceItemData does not perform price, float, or market enrichment.
offset, search, group, selectThese would require global semantics across multiple live cursor pages, so ItemData does not promise them.
other blocked modesUse trade_url for an authorized CS2 trade partner, steam_login_secure for the cookie owner, or the explicit try_first_seven_days_blocked_items mode. Other blocked-inventory selectors are rejected.

Responses are JSON only; XML and other output formats are not supported.

Filtering, grouping, selecting, or offsetting one live page would produce misleading results for the full inventory. Fetch pages by cursor and apply global operations only after collecting them.

05 · GAME VALUES

Supported economies

cs2Counter-Strike 2730 / 2
dota2Dota 2570 / 2
rustRust252490 / 2
tf2Team Fortress 2440 / 2
pubgPUBG: BATTLEGROUNDS578080 / 2
06 · ERRORS

Errors you can act on

Every error uses the same envelope with a stable machine-readable code and a human-readable message.

400invalid_request / invalid_steam_idA query parameter or Steam identifier is missing, unsupported, or malformed.
401missing_api_key / invalid_api_keyThe API key is missing or invalid.
402insufficient_creditsThe account does not have enough credits.
403inactive_api_key / plan_expiredThe key has been revoked or disabled, or its assigned plan has expired.
429rate_limit_exceededThe Steam account's shared fixed-window minute, UTC-day, or UTC-month request limit has been exceeded. All replicas and rotated keys share these counters; honor Retry-After.
502invalid_upstream_response / upstream_error / pagination_limitSteam returned an invalid or unexpected response, or the response exceeded a safety limit.
503cache_unavailable / refresh_in_progress / upstream_unavailable / rate_limiter_unavailableA refresh is already in progress or a dependency is temporarily unavailable; honor Retry-After before retrying.
504upstream_timeoutThe upstream request exceeded its deadline.