Shirt not changing to ID

To change the shirt id and display on the character?

It just displays as blank ive tried everything rbx:// method and whole link still the same outcome not sure why even though when i check it has updated the id just shows it as blank even though when i change manually it works

local Data = {}

local DataStoreService = game:GetService("DataStoreService")
local PlayerDataStore = DataStoreService:GetDataStore("Player_Data")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

Data.DefaultData = {
	ShirtId = 198988028,
	PantsId = 218739358,
	FaceId = 1655546022,
	BodyColor = {R = 0, G = 0, B = 255}
}

function Data:InitializePlayer(player)
	print("Player initialized: " .. player.Name)
end

function Data:CloneAndApplyAttributes(player, data)
	local characterTemplate = ReplicatedStorage.Kids:FindFirstChild("Default")
	if not characterTemplate then
		warn("Default character template not found in ReplicatedStorage")
		return
	end

	local spawnedKidsFolder = workspace:FindFirstChild("SpawnedKids") or Instance.new("Folder", workspace)
	spawnedKidsFolder.Name = "SpawnedKids"

	local existingModel = spawnedKidsFolder:FindFirstChild(player.Name)
	if existingModel then
		existingModel:Destroy()
	end

	local clone = characterTemplate:Clone()
	clone.Name = player.Name
	clone.Parent = spawnedKidsFolder
	clone:SetPrimaryPartCFrame(player.Character.PrimaryPart.CFrame * CFrame.new(5, 0, 0))

	if clone:FindFirstChild("Shirt") then
		clone.Shirt.ShirtTemplate = "http://www.roblox.com/asset/?id=" .. (data.ShirtId or 0)
	end

	if clone:FindFirstChild("Pants") then
		clone.Pants.PantsTemplate = "http://www.roblox.com/asset/?id=" .. (data.PantsId or 0)
	end

	if clone:FindFirstChild("Head") and clone.Head:FindFirstChild("Face") then
		clone.Head.Face.Texture = "http://www.roblox.com/asset/?id=" .. (data.FaceId or 0)
	end
end

function Data:SavePlayerData(player)
	local success, err = pcall(function()
		local dataToSave = {
			ShirtId = Data.DefaultData.ShirtId,
			PantsId = Data.DefaultData.PantsId,
			FaceId = Data.DefaultData.FaceId,
			BodyColor = Data.DefaultData.BodyColor
		}

		PlayerDataStore:SetAsync(tostring(player.UserId), dataToSave)
		print("Player data saved for userId " .. tostring(player.UserId))
	end)

	if not success then
		warn("Failed to save data for player " .. tostring(player.UserId) .. ": " .. tostring(err))
	end
end

function Data:LoadPlayerData(player)
	local success, err = pcall(function()
		local savedData = PlayerDataStore:GetAsync(tostring(player.UserId)) or Data.DefaultData
		self:CloneAndApplyAttributes(player, savedData)
	end)

	if not success then
		warn("Failed to load data for player " .. tostring(player.UserId) .. ": " .. tostring(err))
	end
end

function Data:UpdateCharacter(player, newData)
	self:CloneAndApplyAttributes(player, newData)
end

return Data

1 Like

Hey there, are you sure that the template is a decal? The ShirtId does not convert to template if you change it from a script

Also, you can get the Shirt template from the ShirtId with InsertService:

print(game:GetService("InsertService"):LoadAsset(data.ShirtId).Shirt.ShirtTemplate) -- Output: http://www.roblox.com/asset/?id=11580144116

make sure that the ID is a shirt

and change the shirt’s template to that.

clone.Shirt.ShirtTemplate = game:GetService("InsertService"):LoadAsset(data.ShirtId).Shirt.ShirtTemplate

Hope this helps!

Edit: Either Roblox changed something, or I have lost my sanity. Probably both.
Anyway, the first answer should be your solution.

I faced this very same exact problem around a month ago, and here’s your answer: there is actually no way to do this properly (and likely how you intend) without requiring some kind of proxy server. This is because to get the template ID from a clothing ID, you need to make a request to Roblox’s assetdelivery API to get the actual clothing asset to then extract the template ID, and as we all know you can’t make Roblox API requests from Roblox. Which is absurd.

Anyway, I suggest you make a proxy server for this. I wrote my own a while back because I had this same exact issue, and I’m pretty sure it still works, so if you know a little bit of Node and know how to host something, here’s the repo: GitHub - Strixial/RbxAssetApi

Generally though, here’s what to do:

  • Make a GET request to https://assetdelivery.roblox.com/v2/asset/?id={clothingid}, and you’ll get a JSON response.
  • Decode that into a table, and you’ll find a URL (something like response.locations[1].location, assuming response is your json data) inside with the location of the asset you want to find.
  • Make another GET request to that URL you got, except this time it will be an XML response, which will not be easy to decode.
  • Assuming response is your decoded XML data as a table, it will be in response.roblox.Item.Properties.Content.url
    • Alternatively, just search the string for something like "rbxassetid://*" or the full asset URL. It’s important you do both because I’ve seen both exist in clothing assets.

I mean, you could use roproxy to do this too. But people have mixed opinions on it, so I only mentioned this at the end.

And finally, regarding the existing answer from @0utputt:

That only works if the game owner either owns the shirt, or if the shirt is from Roblox. Welp. I guess Roblox is powering imaginations to learn how to do HTTP requests to REST APIs.

Anyway, I came here for an IK controller module. I’ll be on my way now.

1 Like

But doesn’t it work on any catalog item and not work on Models if the game owner does not own it?
Because for me, It works

1 Like

Interesting. For me that does not work at all, neither in Studio nor in game.
Can you try this asset id? It’s 478775827. It refused to work for me for me until I made my proxy.

1 Like


It worked on it too :thinking:

1 Like

Yeah, it works for me too now, so I don’t know if something’s changed (as usual) or if I was just schizo.

Sorry @HIN38. Go with the first answer as that seems to work now.

1 Like

it works thank you very much for the help, saved a lot of time

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.