Yes.
or
Yes.
or
You can use the GetProductInfo method from the MarketplaceService, it returns a dictionary of all the information related to a product/asset. Including the AssetId.
https://developer.roblox.com/api-reference/function/MarketplaceService/GetProductInfo
OP is looking for a thumbnail, so that they can use this endpoint to retrieve its image. (At least that’s what I think they’re doing)
e.g.
https://www.roblox.com/asset-thumbnail/image?assetId=1127072005&width=420&height=420&format=png
Is the thumbnail for this shirt:
You can use the URL above in an ImageLabel in-game:
Since OP just wants to display what the player character is wearing, they can just retrieve the asset id that the character is wearing directly by reading the applied HumanoidDescription.
-- Assume that this is a script that's inside the player's character...
local Humanoid = script.Parent.Humanoid
local descriptionClone = Humanoid:GetAppliedDescription()
print(descriptionClone.Shirt) -- this is the asset id of the shirt that the player is wearing.
I did not read.
I believe the first thread can be ignored in that case, though wouldn’t IconImageAssetId from GetProductInfo also get the appropriate image as opposed to using the endpoint?
edit: wow i can’t see?
It’s not possible. There was a feature request for something similar a while ago (decal asset id to image id) here:
One method is to keep subtracting the shirt template id by 1 until you get to its asset id… But this can take a lot of requests and the distance between the template to the asset id can be large (there are also more issues with this, read the feature request for more info).
Follow up: Is there any reason why using HumanoidDescriptions would be inconvenient?
I have to rewrite my character customization module to use only HumanoidDescriptions
Edit: I just remembered that you can’t issue HTTP requests to Roblox from in-game. I made a proxy for small batches of calls to this service. If this is for a small scale service, I can show you how to make a free proxy on Google Cloud Platform.
Assuming I understand the goal, it actually is possible. You have the Shirt Asset ID, and you want the Image Asset ID. Here’s what you do:
Issue an HTTP GET request to https://assetgame.roblox.com/asset/?id=SHIRT_ID
This will return XML for a Shirt Instance that you can parse to find the Image ID. For example:
http://assetgame.roblox.com/assets/?id=2551557116
will return:
<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.roblox.com/roblox.xsd" version="4"> <External>null</External> <External>nil</External> <Item class="Shirt" referent="RBX0"> <Properties> <Content name="ShirtTemplate"> <url>http://www.roblox.com/asset/?id=2551557110</url> </Content> <string name="Name">Shirt</string> <bool name="archivable">true</bool> </Properties> </Item> </roblox>
The line with the tag is what you are looking for. A simple string.match(responseBody, "<url>(.+)</url>")
ought to do the trick.
This also works for Pants and Decals.
So the reverse, get a Shirt ID from an Image ID?
This is getting confusing. OP only has this to work with (let’s call this the ShirtTemplateId
)
The ShirtTemplateId
is 1127071991
OP wants to get the AssetId
, which is 1127072005
How do you get from 1127071991
to 1127072005
? It’s not possible without brute-forcing it. https://assetgame.roblox.com/asset/?id=1127071991 will get the image itself, not an xml.
I see. It’s still possible with a simple web app, in fact I already have one on GCP that does exactly this. It works somewhat like you are saying. It takes the as input a ShirtTemplateId. It increments it and uses Marketplace API (except the external version) and checks whether the asset is a Shirt. If it is, it uses the method I mentioned before to request that shirt’s corresponding ShirtTemplateId. If it matches, it returns the current incremented ID. If not, it continues incrementing.
… That’s brute-forcing it, which is literally the method I mentioned a few posts ago. Brute-forcing has some pitfalls that were mentioned in the feature request I mentioned, too. You don’t even need to use an external service for this, just use GetProductInfo.
You never described how to brute force it, and you also described it as “impossible”. It’s very possible.
Please don’t cherry-pick my wording…
“until you get its asset id”
I guess what was missing is that you never described how you know when you’ve found the correct ID.
Just thought I’d reply to this thread cause I found myself with a similar problem and managed to find a solution. Posting this incase anyone in the future would be wondering the same thing.
local clothing_type = "Shirt" -- or "Pants"
local clothing_parent -- define this
local item_url = clothing_parent:FindFirstChildOfClass(clothing_type)[clothing_type .."Template"]
local ItemID = string.match(item_url, "%d+")
Roblox (Clothing) Asset URL’s come in two variants:
http://www.roblox.com/asset/?id=4979758466
rbxassetid://4979758466
the thing they have in common is that they both have numbers only at the end. So this method would be valid.
You could change the string manipulation used to define the ItemID
, maybe to check for numbers in a different order, in case you want to apply this for other asset types.
Although, I think at that point there would be better API available to suit your goal.
Here’s something I wrote earlier that performs the reverse of what you’re trying to achieve (asset ID to catalog ID).
You should be able to repurpose the script for your particular use case.
I decided to modify the linked resource for you.
local marketplace = game:GetService"MarketplaceService"
local getProductInfo = marketplace.GetProductInfo
local assetTypeIds = {2, 11, 12, 13, 21} --T-Shirt, Shirt, Pants, Decal, Badge.
local maxTries = 5 --Maximum retries per catalog ID.
local maxHeight = 100 --Maximum height to search for.
local function getCatalogIdFromAssetId(assetId : number) : number
local success, result = pcall(getProductInfo, marketplace, assetId)
if success then
if result then
if result.AssetTypeId == 1 then
local cache, success2, result2 = table.create(100), nil, nil
repeat
task.wait()
assetId += 1
if assetId - result.AssetId > maxHeight then
return
end
if cache[assetId] then
cache[assetId] += 1
else
cache[assetId] = 1
end
if cache[assetId] > maxTries then
continue
end
success2, result2 = pcall(getProductInfo, marketplace, assetId)
if not success2 then
warn(result2)
assetId -= 1
end
until result2 and table.find(assetTypeIds, result2.AssetTypeId) and result2.Creator.CreatorType == result.Creator.CreatorType and result2.Creator.CreatorTargetId == result.Creator.CreatorTargetId
return result2.AssetId
end
end
else
warn(result)
end
end
local assetId = getCatalogIdFromAssetId(14417331)
print(assetId) --14417332
The following image was used for testing purposes.
https://www.roblox.com/badges/14417332/John-Loved-of-Muses
tonumber(string.sub(ShirtTemplate,32,99))