Jump to content

Most Liked Content

#889 Identifying Steam Items

Posted by Dr. McKay on 20 May 2016 - 12:40 AM

Sometimes it can be a little confusing to identify a specific item in the Steam economy. There are several different types of IDs present in one particular item, and a lot of vague terminology. This guide aims to clear all that up for you.

For starters, the "official" term for a Steam item is an asset. When I say a "Steam item", I mean a particular copy of an item. I'm not referring to the item's definition, name, image, or anything. I'm referring to a specific, unique copy of the item.

In a general sense, every item on Steam must be owned by an app. An "app" is a game, software, or whatever on Steam. Every app has its own unique AppID. You can find a particular game's AppID by going to its store page or community hub and looking at the URL. For example, TF2's AppID is 440 so TF2's store page can be found at http://store.steampowered.com/app/440. CS:GO's is 730, Dota 2's is 570, and so on. Note that Steam Community items, Steam gifts, and other "Steam" items are owned by the "Steam" app, which has AppID 753. To identify an item, you'll need the AppID of the game which owns it.

Of course, the AppID alone isn't enough. You also need two other IDs. Have you ever noticed how some games have multiple inventories, which appear in a drop-down list? An example is the Steam inventory, which has sub-inventories for "Community", "Gifts", "Coupons", etc. These "sub-inventories" are called contexts, and each context has its own context ID. If a game doesn't have a drop-down menu to select a context, that doesn't mean that it's without contexts. That only means that it has one single visible context. That single context still has an ID. For all current Valve games, the context ID for the publicly-visible context is 2.

Context IDs can be a bit tricky. It's entirely up to the game's developer to determine how they work. For example, Valve games take the "single shared inventory" model in which there's one context ID which is shared by everyone. Under this model, an item belongs to one particular context and never leaves that context. Consequently, the item's context ID never changes. It is, however, possible for game developers to create contexts in any way they choose. For example, Spiral Knights uses the "per-character inventory" model in which everyone who plays the game has their own context IDs for their characters. Creating a new character creates a new context ID. This means that when an item is traded between users, its context ID will change as it moved out of a particular character's inventory.

Those are the two different types of "containers" in the Steam economy. Apps own contexts, and contexts own assets. Every asset on Steam has, in addition to its AppID and context ID, an asset ID which is guaranteed to be unique inside of a given AppID+ContextID combination. Notice that this means that asset IDs are not unique across all of Steam. They aren't even unique across a particular app. They are only unique inside of a given context. For example, there could be two items with asset ID 1 in the same game, as long as they have different context IDs. An item's asset ID may be referred to as "assetid" or just plain "id".

Context IDs and asset IDs are assigned by the game developer and can follow any pattern. They can change when traded or not. They may both be up to 64 bits in size. Consequently, Steam returns them (like all other 64-bit values) in JSON as strings.

Still following? All of what we've learned so far leads us to this conclusion: in order to uniquely identify an item, you need its AppID, its context ID, and its asset ID. Once you have these three things, only then can you uniquely identify it. In fact, this is how you link to a particular item in a user's inventory: steamcommunity.com/profiles/steamid/inventory#appid_contextid_assetid. Here's an example: https://steamcommuni...440_2_134161610

What on Earth are these "classid" and "instanceid" values though??
The observant reader may have noticed that there are two more IDs attached to a particular item which I haven't mentioned. These are the "classid" and "instanceid". These IDs are used to map an asset to its description.

What's a description? A description is what you need in order to actually display an item. An item's description contains its name, image, color, market_name, whether it's tradable or not, whether it's marketable or not, and more. There are many endpoints on Steam which return JSON objects representing assets that only contain the asset's AppID, context ID, asset ID, classid, instanceid, and amount. An item's amount is how big of a stack it is. Unstackable items always have an amount of 1. Stackable items (such as Steam gems) may have a larger amount. Stacked items always have the same asset ID.

What's the difference between a classid and an instanceid? Well in a nutshell, a classid "owns" an instanceid. The classid is all you need to get a general overview of an item. For example, items with the same classid will pretty much always have the same name and image. The instanceid allows you to get finer-tuned details such as how many kills are on a strange/StatTrak weapon, or custom names/descriptions.

You can turn a classid/instanceid pair into a description using the GetAssetClassInfo WebAPI method. Notice that the instanceid is actually optional: if you only have a classid that's fine, you just won't get finer details for the item.

Do note that it's possible for a game developer to flush Steam's asset cache entirely, which would change the classid/instanceid of every item. As of the time of this posting, I'm unaware of this ever having been done.

Name? Market Name? Market Hash Name? Halp?
Every asset on Steam has a name. Period. Without a name, there's nothing to show in your inventory. The item's name is the... (wait for it...) name property of its description (shocking, I know). The item's name may be localized if the game's developer has set it up to be.

Every marketable item also has a "market name". This name may be the same as, or different from the item's regular name. The item's market name is the market_name property of its description. This is the name that's displayed in the Steam Community Market when the item is up for sale. Why the distinction? There are some items which have value-affecting data that isn't in their name. For example, CS:GO skins have 5 different tiers of "wear", which isn't in their names. The wear tier is appended to each skin's market name however, so that the different tiers of wear are separated in the market. The market name may be localized or not, and may not exist at all if the item isn't marketable. It's up to the game's developer.

Finally, every marketable item also has a "market hash name", available under the market_hash_name property. This name is supposed to be the English version of the item's market name, but in practice it may vary. For example, Steam Community items prepend the AppID of the originating app to each item's market hash name, but not to the market name. The market hash name is never localized, and may not exist if the item isn't marketable. Again, it's up to the game's developer. You can view the Community Market listings for any marketable item using this URL formula: steamcommunity.com/market/listings/appid/market_hash_name. Here's an example: https://steamcommuni...upply Crate Key

Note that the Community Market has no concept of contexts. Consequently, market [hash] names are unique for a particular "class" of items per-app (and by extension per-context). This means that for marketable items, two items with identical market hash names will be worth roughly the same (with some exceptions, like unusual TF2 items).

Ask below. I'm happy to help!

  • Mole, Andrew, trzyrazyzero and 1 other like this

#210 SteamBot Help compile and configure

Posted by Marcio Moura on 13 March 2016 - 03:54 PM

Good afternoon

I wanted to make a gambling site to csgo
Ja researched by google but not found anything to help me , it speaks to compile the code , and it does not know much

 I needed the help of someone who knew this subject , and who is willing to help me .

I hope someone help me
Have a nice day
Marcio Moura

Sorry for my bad English , but I 'm Portuguese


This is the site


  • danyaVak, Borisdip, Vasyaon and 1 other like this

#1537 Minimal code to stay logged in forever...

Posted by Dr. McKay on 06 August 2016 - 11:03 PM

That all looks fine to me. sessionExpired is only emitted when a request you make fails because you aren't logged in. It doesn't check automatically, it only checks whenever the library makes a request somewhere.


Starting a new confirmation checker without stopping the old one is just fine. It'll stop an old one if you call it while one is running.


I recommend updating to v3.23.1 if you're going to use webchat.

  • yellowish and klonaway like this

#143 TradeOfferManager v2

Posted by Dr. McKay on 03 March 2016 - 02:10 PM

Here's an idea. Three options for createOffer():

  1. manager.createOffer(steamID); // create an offer without a token. you can set it later
  2. manager.createOffer(steamID, token); // create an offer with a token
  3. manager.createOffer(tradeURL); // automatically extract the SteamID and token from the trade URL

  • Mole and PEPZ like this

#845 Receive friend requests/Adding friends

Posted by Dr. McKay on 08 May 2016 - 03:43 PM

client.on('friendRelationship', function(steamID, relationship) {
    if (relationship == SteamUser.Steam.EFriendRelationship.RequestRecipient) {


You can use getPersonas to get names and other profile data.

  • UKF likes this

#337 Use Tradeoffer Manager with Node Cluster

Posted by Dr. McKay on 23 March 2016 - 09:40 PM

Yeah making your bots separate from your site is probably your best bet.

  • Nogtail likes this

#2884 Cannot read property 'player_name' of undefined

Posted by Dr. McKay on 07 March 2017 - 08:50 AM

You're overwriting the value of steamID in your outer loop, which changes the context of the closure. This is confusing, I know. Just do this and it should work:

bot.on('friendsList', function() {
  Object.keys(bot.myFriends).forEach(function(steamID) {
    if(bot.myFriends[steamID] === 2) {
      bot.getPersonas([steamID], function(getName) {
        var friendName = getName[steamID].player_name;
	//Some code

  • T1MOXA likes this

#2876 Help me find method

Posted by Dr. McKay on 06 March 2017 - 11:54 AM


  • d4c0 likes this

#2763 There was an error sending your trade offer. Please try again later. (26)

Posted by Dr. McKay on 23 February 2017 - 08:21 AM


  • mrxbell likes this

#2565 How to get your own name in console (and other users (optional))

Posted by MrKirby on 18 January 2017 - 03:38 PM

After some time having trouble with it (as I am new), I got it to work! Thanks so much dude! for everyone else wondering.. I used this:

client.on('friendMessage', function(steamID, message) {		
    friendID = [steamID];
    client.getPersonas(friendID, function(getName) {
        var x = getName[friendID];
        var friendName = x.player_name;

        console.log("[FriendlyMessage] " + friendName + ": " + message);

Brackets could be wrong because my code didn't stop there and I am correcting it within the text editor


I do have another question and I don't know if I should ask it here?

But, what are the numbers for friendrelationships??

I know 2 is friend request send to me. But where can I find it.. because I am having trouble finding everything...  :mellow:  :mellow:


EDIT: After actually turning my brain on.. I checked within the files of your node and found a file with the numbers.... Shit I'm stupid... Thanks anyway!! GREAT SHIT DUDE!!!

  • Dr. McKay likes this

#2233 error on sending offer

Posted by Dr. McKay on 07 December 2016 - 06:31 PM

It usually helps to print out values of variables when debugging. In this case, I suspect one of appid, contextid, or assetid is undefined or not the value you are expecting.

  • Vin4er likes this

#2088 How to go from Steam64 to Steam username (the name currently used on steam)

Posted by Frost Byte on 07 November 2016 - 12:45 PM

I found out myself!


You already have the properties and methods from the steam handlers in your own steam-user library. So there I don't need a specific handler like 'friends' to send a message. I can just ask your steam-user object (in my case I called it client) and ask for the chatMessage method.


Right? Well it works for me now  ;)


Yeah, it really works. And I managed to only use your node-steam-user library with all it's functions + your node-steamcommunity library!

  • Dr. McKay likes this

#1933 Decline Trade Hold

Posted by Dr. McKay on 22 October 2016 - 01:58 AM

offer.getUserDetails(function(err, me, them) {
	if (err) {
		throw err;
	if (them.escrowDays > 0) {

  • TextDynasty likes this

#1875 bind ip to node-steam-user & node-steamcommunity

Posted by Dr. McKay on 11 October 2016 - 12:13 AM

The constructor is new SteamCommunity()

  • mtn likes this

#1780 Listening for accepted trade offer from real trade

Posted by Dr. McKay on 22 September 2016 - 10:39 AM


  • adma likes this

#1329 getReceivedItems(Empty) how to recheck ?

Posted by Dr. McKay on 09 July 2016 - 04:13 PM

You need to do it yourself.

  • Gilroy likes this

#1292 Steam Web API/IEconService [input, output]

Posted by Dr. McKay on 05 July 2016 - 09:58 AM

1. If you want to get all active offers and that's it, you'd use this:

    "get_sent_offers": 1,
    "active_only": 1,
    "time_historical_cutoff": 2147483647

2. You'd check the trade_offer_state. If they accepted it then they received the item you sent them.

3. If you want all offers from a time period you'll need to just leave out both active_only and historical_only and filter the result.

  • protz_i likes this

#1291 general node.js question

Posted by Dr. McKay on 05 July 2016 - 09:55 AM

Because you're adding a new listener every single time you request item info.


Just use the callback and you won't need to worry about it.

  • Henrykvdb likes this

#1818 itemsToGive with multiple items

Posted by adma on 29 September 2016 - 10:14 PM

If you want to get the market hash names of each item you're giving, you would probably use forEach or a for loop to cycle through the itemsToGive array ...

manager.on('newOffer', function(offer) {
	offer.itemsToGive.forEach(function(item) {
		console.log("Item to give : " + item.market_hash_name); // Items to give: Chroma 2 Case

a for ... of loop (edited from for..in loop)

manager.on('newOffer', function(offer) {
	for (var item of offer.itemsToGive) {
		console.log("Items to give : " + item.market_hash_name); // Items to give: Chroma 2 Case

a regular for loop

manager.on('newOffer', function(offer) {
	for (var i = 0; i < offer.itemsToGive.length; i++) {
		console.log("Items to give #" + i + " : " + offer.itemsToGive[i].market_hash_name); // Items to give #1 : Chroma 2 Case

Same deal will apply for itemsToReceive ... or any other array you wanted to cycle through
read here https://developer.mo...s_and_iteration

  • Melonos likes this