Mutations and purchasing
Market mutations are form POSTs against steamcommunity.com, authenticated by the cookies of a
signed-in session. They are not a JSON API, and they are not tolerant of a bare HTTP client.
Two ways to buy
| Operation | Behaviour |
|---|---|
POST /market/buylisting/{listingid} | Buys one specific listing outright, at its asking price, from the Steam Wallet. Immediate. |
POST /market/createbuyorder/ | Places a standing order at a price you name. Fills when a seller meets it, possibly never, possibly partially. |
buylisting is the instant-buy path. It targets a listing ID, so the listing must still exist at
the price you read — losing the race to another buyer is a normal outcome, not an error condition.
Amounts must reconcile
buylisting requires the buyer to send the price breakdown, and Steam validates it:
total = subtotal + fee
subtotal is the seller's take, fee is the combined Steam and publisher cut, total is what the
buyer pays. Read all three off the listing rather than computing them: the publisher's share varies
per application, so the split is not derivable from the total alone.
curl 'https://steamcommunity.com/market/buylisting/1234567890123456789' \
-H 'Cookie: steamLoginSecure=<redacted>; sessionid=<redacted>' \
-H 'Referer: https://steamcommunity.com/market/listings/730/AK-47%20%7C%20Redline%20%28Field-Tested%29' \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data 'sessionid=<redacted>¤cy=1&subtotal=1200&fee=180&total=1380&quantity=1'Success is reported inside wallet_info, not at the top level:
{ "wallet_info": { "success": 1, "wallet_balance": "4320" } }A failure returns HTTP 200 with a top-level message and no wallet_info.success of 1. Check
the nested field; a 200 alone means nothing here.
Required headers
Steam rejects mutations that do not look like they came from the Market UI. The sessionid CSRF
field is necessary but not sufficient.
| Header | Value |
|---|---|
Cookie | steamLoginSecure and sessionid for the signed-in session |
Referer | The page the action would have come from — see below |
Content-Type | application/x-www-form-urlencoded |
Origin | https://steamcommunity.com |
X-Requested-With | XMLHttpRequest |
Referer is checked per operation, and a generic one is not accepted:
| Operation | Referer |
|---|---|
buylisting, createbuyorder, getbuyorderstatus | /market/listings/{appid}/{market_hash_name} |
sellitem | The inventory page for the account |
removelisting, cancelbuyorder | /market/ |
The market_hash_name in the Referer must be URL-encoded exactly as the listing page encodes it.
Selling is two steps
POST /market/sellitem/ does not publish a listing. It stages one and tells you what is still
required:
{
"success": true,
"requires_confirmation": 1,
"needs_mobile_confirmation": true,
"needs_email_confirmation": false,
"email_domain": ""
}While requires_confirmation is set, the item is not on the Market. Completing the listing means
accepting the matching Steam Guard confirmation:
GET /mobileconf/getlist— list pending confirmations. Match yours bycreator_id, which carries the asset ID for a sell listing.GET /mobileconf/ajaxopwithop=allow, plus thecidandckfrom that entry.
These routes sit under /mobileconf, not /market, and they authenticate differently: instead of
the sessionid CSRF field they take an HMAC-SHA1 of the request tag and a Unix timestamp, keyed by
the account's identity_secret from its mobile authenticator.
| Parameter | Meaning |
|---|---|
p | Device ID derived from the SteamID |
a | SteamID64 |
k | Base64 HMAC over tag and t, keyed by identity_secret |
t | Unix seconds the key was generated for |
m | android |
tag | conf to list, details{id} for detail, allow or cancel to respond |
The signature covers the tag, so a key minted for conf will not work for allow. Generate a new
one per request.
Watching a buy order fill
Buy orders fill over time and partially. GET /market/getbuyorderstatus is the only view of that:
{ "success": 1, "active": 1, "purchased": 2, "quantity": 5, "quantity_remaining": 3 }GET /market/mylistings lists open orders but does not break down fills.
Failure is quiet
Nothing here uses HTTP status to report application failure. createbuyorder returns success: 25
with a message when it is rejected, buylisting hides its result in wallet_info.success, and
cancelbuyorder returns success: 1. Read the body on every mutation.
Terms
Automating Market purchases is against the Steam Subscriber Agreement, which prohibits using automation software to modify or automate any Subscription Marketplace process. This page documents how the endpoints behave; whether to call them from a bot is a decision with account consequences.

