Getting players profile picutre into webhook

I want to get the players profile picture headshot as the webhooks avatar url.

The issue is that the profile picuture is not there when I check in discord. The message is there and everything is working but not the profile picture.

I have tried looking for answers but everyone just says to use thumbnail API and I dont know how to do that. Also I have tried to publish the game and go into a live server but it still didnt work.

Anything helps, thank you!

game.Players.PlayerAdded:Connect(function(plr)
	if plr.UserId == 4359107419 then
		plr:Kick()
		
		local data = {
			["embeds"] = {
				{["title"] = "Kicked Player!",
				["description"] = `{plr} has been kicked`,
				["color"] = 16619520
				},
			},
			["username"] = "Test",
			["avatar_url"] = "https://thumbnails.roblox.com/v1/users/avatar-headshot?userIds="..  plr.UserId .."&size=48x48&format=Png"

		}

		HttpService:PostAsync(webhook_url, HttpService:JSONEncode(data))
	end
end)
1 Like

Hi, you’re using the Roblox thumbnails API URL directly as the avatar_url in your discord webhook. But, https://thumbnails.roblox.com/v1/users/avatar-headshot?userIds= is not a direct image link. This actually returns JSON data, with the real image URL inside. Discord expects your avatar_url to be a direct image (like https://tr.rbxcdn.com/....png). Thats why nothing shows up. You need to get the direct CDN link using Roblox’s Players:GetUserThumbnailAsync, not the web API.

So you mean I would do something like this:

local image = game.Players:GetUserThumbnailAsync(plr.UserId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size48x48)

And then

["avatar_url"] = image

but then I’ll get the error: HTTP 400 (Bad Request)

local Players = game:GetService("Players")

local webhook_url = "YOUR_DISCORD_WEBHOOK_URL_HERE"

game.Players.PlayerAdded:Connect(function(plr)
	if plr.UserId == 4359107419 then
		plr:Kick()

		-- getting the actual headshot URL
		local image = Players:GetUserThumbnailAsync(
			plr.UserId,
			Enum.ThumbnailType.HeadShot,
			Enum.ThumbnailSize.Size48x48
		)

		-- here we build  the JSON payload
		local data = {
			["embeds"] = {
				{
					["title"] = "Kicked Player!",
					["description"] = plr.Name .. " has been kicked",
					["color"] = 16619520
				}
			},
			["username"] = "Test",
			["avatar_url"] = image -- MUST be a string URL
		}

		-- here is where we post to discord
		HttpService:PostAsync(
			webhook_url,
			HttpService:JSONEncode(data), -- encode this to JSON string
			Enum.HttpContentType.ApplicationJson -- we have to set content type
		)
	end
end)

You must be doing something wrong, try this code?

Heres my code:

local Players = game:GetService("Players")
local HttpService = game:GetService("HttpService")

local webhook_url = "Webhook_Url"

game.Players.PlayerAdded:Connect(function(plr)
	if plr.UserId == 4359107419 then
		plr:Kick()

		local image = Players:GetUserThumbnailAsync(
			plr.UserId,
			Enum.ThumbnailType.HeadShot,
			Enum.ThumbnailSize.Size48x48
		)

		local data = {
			["embeds"] = {
				{
					["title"] = "Kicked Player!",
					["description"] = plr.Name .. " has been kicked",
					["color"] = 16619520
				}
			},
			["username"] = "Test",
			["avatar_url"] = image 
		}

		HttpService:PostAsync(
			webhook_url,
			HttpService:JSONEncode(data),
			Enum.HttpContentType.ApplicationJson
		)
	end
end)

still getting HTTP 400 (Bad Request) on line 28( HttpService:PostAsync )
Also the webhook_url variable is set to the actual url when I tested

Try doing local image, isReady = Players:GetUserThumbnailAsync(....

Also, I just remembered something.

By default, HttpService:PostAsync() posts as text/plain. But, Discord expects application/json. You did add Enum.HttpContentType.ApplicationJson, but Discord also requires the request not to be URL-encoded. That would mean that you would have to pass false as the third argument of PostAsync().

isReady is true when I set the data of the webhook

Try this and see if that works.

It should be like:

    webhook_url,
    HttpService:JSONEncode(data),
    Enum.HttpContentType.ApplicationJson,
    false
)

I tried that but still getting the same error. Maybe because GetUserThumbnailAsync generates a link that only roblox can fetch. which means discord can’t?

Oh yeah, you’re kinda right about that one.. :grimacing:

So, uhm, I have kind of edited your code here.. we could try fetching the image from the thumbnail API like this:

local HttpService = game:GetService("HttpService")

local webhook_url = "Webhook_Url"

game.Players.PlayerAdded:Connect(function(plr)
	if plr.UserId == 4359107419 then
		plr:Kick()

		local apiUrl =
			"https://thumbnails.roblox.com/v1/users/avatar-headshot?userIds=" ..
			plr.UserId .. "&size=48x48&format=Png&isCircular=true"

		local success, response = pcall(function()
			return HttpService:GetAsync(apiUrl)
		end)

		local imageUrl = nil
		if success then
			local data = HttpService:JSONDecode(response)
			if data and data.data and data.data[1] and data.data[1].imageUrl then
				imageUrl = data.data[1].imageUrl
			end
		end


		local data = {
			["embeds"] = {
				{
					["title"] = "Kicked Player!",
					["description"] = plr.Name .. " has been kicked",
					["color"] = 16619520
				}
			},
			["username"] = "Test",
			["avatar_url"] = imageUrl
		}

		HttpService:PostAsync(
			webhook_url,
			HttpService:JSONEncode(data),
			Enum.HttpContentType.ApplicationJson,
			false
		)
	end
end)

I’m not 100% certain if this will work or not.

Im not getting any errors now but still the profile picture on the webhook is just the discord logo.

Could you try this please?
Add this right after you JSONDecode(response).
print("Webhook avatar URL: ", imageUrl)

It should return a link, try to search that link up and see if it does show a headshot image or not. If it does, then the issue is Discord caching. If it shows nothing or JSON, then we might be feeding the wrong URL.

I can’t give any solution without the answer to my question.

I added it but it prints nothing.

Also, this is not running so imageUrl is nil the whole time:

if data and data.data and data.data[1] and data.data[1].imageUrl then
	imageUrl = data.data[1].imageUrl
end

It’s because none of the thumbnail API’s v1 endpoints are whitelisted by Roblox for use within HttpService so the Http request never succeeds to begin with. You should be using /cloud/v2/users/{user_id}:generateThumbnail instead which is whitelisted for use.

You can find a list of supported Roblox API endpoints within HttpService here.

I dont know what you mean. Or like should I just replace the avatar_url with “https://apis.roblox.com/cloud/v2/users/” .. plr.UserId .. “:generateThumbnail”?

you’d have to create your own API key for it to work, then request the image from roblox APIS

https://thumbnails.roproxy.com/v1/users/avatar-headshot?userIds=1&size=48x48&format=Png