Webhook - HTTP Error 400

Just saying, the field “url” does not exist in the main body of the message but it does exist inside of the embeds. The URL will appear as a masked link as Discord calls it and you will be able to click on the title text to go to the link.

1 Like

You’re right. I must’ve looked at it and didn’t think much about it. I’ll fix it.

1 Like

Unless you are using a proxy, you can’t send messages from Roblox servers to Discord (as discord blocks it).

Make sure you are using a proxy when firing the webhook otherwise it won’t work, regardless of how you format it.

1 Like

I’m using this:

HttpService:PostAsync(EthicsWebhook, HttpService:JSONEncode(Data))

Is this correct?

HttpService:PostAsync(EthicsWebhook, HttpService:JSONEncode(Data))

I fixed the “content” bit earlier and still received the error unfortunately.

What do you mean by the keys being used wrong as well? That is how they are coded in this person’s code which I tested and it worked for them: How do you make a discord webhook send an embed message?

I’m using a proxy so that’s not the issue.

Hey,
First off, its important not to use the default webhook directly. Instead, you should use a proxy, because in Studio, the standard Discord webhook API should work. Your JSON encoding seems correct, but if errors occur ingame, it might be because Discord doesnt allow Roblox to send webhooks directly. In that case, you should use a proxy like webhook.lewisakura.moe.
Additionally, Im unable to see what the player picture is it could be nil or something else causing errors. I recommend printing out the value to check. The same goes for the Titles variable try printing it as well to debug.

1 Like

This bit of data is inside of [embeds] = {} but when the message is sent to Discord, there is no thumbnail? What am I doing wrong here?

["thumbnail"] = {
["url"] = "https://www.roblox.com/headshot-thumbnail/image?userId="..UserID.."&width=420&height=420&format=png"
},

When I print out the PlayerPicture, I get this in the output:

This is not a URL and this asset is only valid for Roblox’s user not Discord. You should be using a proxy to send a get request to the Roblox APIs to get the actual avatar thumbnail URL. Here is how I would be getting the avatar thumbnail:

local thumbnailURL:string = "https://thumbnails.roproxy.com/v1/users/avatar-headshot?userIds=%s&size=150x150&format=Png&isCircular=false"

local function getThumbnail(player:Player)
	local userId:number = player.UserId
	local response:string = nil

	local success:boolean, errorMessage:string = pcall(function()
		response = HTTPService:GetAsync(thumbnailURL:format(userId))
	end)

	if not success then
		error(errorMessage)
	else
		return HTTPService:JSONDecode(response).data[1].imageUrl
	end
end
1 Like

That API endpoint has been removed since 2021. Also, you should be using a proxy to access the Roblox APIs from inside Roblox servers because Roblox does not allow you to directly access them. Please use the URL I have provided above.

1 Like

You need to use: https://thumbnails.roproxy.com/v1/users/avatar-headshot?userIds=" .. UserId .. "&size=420x420&format=Png&isCircular=false this returns you an imageUrl that u can use

function getProfileImageUrl(UserId)
local success, response = pcall(function()
return HttpService:RequestAsync({
Url = “https://thumbnails.roproxy.com/v1/users/avatar-headshot?userIds=” … UserId … “&size=420x420&format=Png&isCircular=false”,
Method = “GET”,
})
end)

if not success or not response.Success then
	return "8.8.8.8"
end

local successDecode, data = pcall(function()
	return HttpService:JSONDecode(response.Body)
end)

if not successDecode or not data.data or not data.data[1] or not data.data[1].imageUrl then
	return "8.8.8.8"
end

return data.data[1].imageUrl

end

1 Like

I got this error
Screenshot 2025-04-11 233648

local ThumbnailURL:string = “https://thumbnails.roproxy.com/v1/users/avatar-headshot?userIds=%s&size=150x150&format=Png&isCircular=false

local function getThumbnail()
	local Response:any = nil

	local Success:boolean, ErrorMessage:string = pcall(function()
		Response = HttpService:GetAsync(ThumbnailURL:format(UserID))
	end)

	if not Success then
		error(ErrorMessage)
	else
		return HttpService:JSONDecode(Response).data[1].imageUrl
	end
end

local Thumbnail = getThumbnail()

Try this should you return the image Url correctly:

local function getProfileImageUrl(UserId)
	local success, response = pcall(function()
		return HttpService:RequestAsync({
			Url = "https://thumbnails.roproxy.com/v1/users/avatar-headshot?userIds=" ..UserId.. "&size=420x420&format=Png&isCircular=false",
			Method = "GET",
		})
	end)

	if not success or not response.Success then
		return "google.com"
	end

	local successDecode, data = pcall(function()
		return HttpService:JSONDecode(response.Body)
	end)

	if not successDecode or not data.data or not data.data[1] or not data.data[1].imageUrl then
		return "google.com"
	end

	return data.data[1].imageUrl
end
1 Like

I’m getting a HTTP error 400 again when I use this

Thanks for all the help by the way

local function getProfileImageUrl()
		local success, response = pcall(function()
			return HttpService:RequestAsync({
				Url = "https://thumbnails.roproxy.com/v1/users/avatar-headshot?userIds="..UserID.."%s&size=150x150&format=Png&isCircular=false",
				Method = "GET"
			})
		end)

		if not success or not response.Success then
			return "google.com"
		end

		local successDecode, data = pcall(function()
			return HttpService:JSONDecode(response.Body)
		end)

		if not successDecode or not data.data or not data.data[1] or not data.data[1].imageUrl then
			return "google.com"
		end

		return data.data[1].imageUrl
	end
	
	local Thumbnail = getProfileImageUrl()
	
	local Data = 
		{
			["content"] = Mentions;
			["embeds"] = {{
				["title"] = Titles;
				["color"] = 8856607;
				["url"] = "https://www.roblox.com/users/"..UserID.."/profile";
				["thumbnail"] = {
					["url"] = Thumbnail;
				},
				["fields"] = {
					{
						["name"] = "**"..QuestionOne.."**";
						["value"] = AnswerOne;
					},
					{
						["name"] = "**"..QuestionTwo.."**";
						["value"] = AnswerTwo;
					},
					{
						["name"] = "**"..QuestionThree.."**";
						["value"] = AnswerThree;
					},
					{
						["name"] = "**"..QuestionFour.."**";
						["value"] = AnswerFour;
					},
					{
						["name"] = "**"..QuestionFive.."**";
						["value"] = AnswerFive;
					}
				}
			}}
		}

I checked what it was printing and it was the google.com link so the decode didn’t work

I think roproxy might be down right now. Take that with a grain of salt though but I think it might be down because (unless I am remembering this wrong) roproxy.com should take you directly to roblox.com but it says the site can’t be reached.

1 Like

It’s taking me to roblox.com when I click on it

The site has just regained connection for me but I have got this pop-up. Never seen this before, a bit odd. (Nevermind I got it to redirect to roblox.com again)

1 Like

I dont know for me it works fine. Maybe the userID might be wrong also i found a solution!:

local HttpService = game:GetService("HttpService")
local webhookUrl = "https://discord.com/api/webhooks/1360251591604834495/oxuXlpxl1Vkxdj41bgvjFT3QuoNd_7tYESblB1GSb5_RDI2bNymXzEXL6IXItKLWd-wG"
function sendApplication(player, question1, answer1, question2, answer2)
	local function getProfileImageUrl(userId)
		local success, response = pcall(function()
			return HttpService:RequestAsync({
				Url = "https://thumbnails.roproxy.com/v1/users/avatar-headshot?userIds=" .. userId .. "&size=420x420&format=Png&isCircular=false",
				Method = "GET",
			})
		end)

		if not success or not response.Success then
			return "google.com"
		end

		local decodeSuccess, data = pcall(function()
			return HttpService:JSONDecode(response.Body)
		end)

		if not decodeSuccess or not data.data or not data.data[1] or not data.data[1].imageUrl then
			return "google.com"
		end

		return data.data[1].imageUrl
	end

	local mentions = "<@1356282230967635969> <@1356282232746283140> <@1356282230577692854>"
	local title = player.Name .. "'s Level 0 Application"
	local thumbnailUrl = getProfileImageUrl(player.UserId)

	local payload = {
		["contents"] = mentions,
		["embeds"] = {{ --TWO brackets DONT FORGET
			["title"] = title,
			["description"] = "???",
			["color"] = tonumber(0xA333FF),
			["thumbnail"] = {
				["url"] = thumbnailUrl
			},
			["fields"] = {
				{
					name = "**" .. question1 .. "**",
					value = answer1,
					inline = false
				},
				{
					name = "**" .. question2 .. "**",
					value = answer2,
					inline = false
				}
			}
		}}
	}

	HttpService:PostAsync(webhookUrl, HttpService:JSONEncode(payload))
end


game.Players.PlayerAdded:Connect(function(plr)
	sendApplication(plr, "Age", "100", "Does it work?", "Yes it does")
end)
1 Like

Oh, I figured it out! I accidentally had “%s” in the URL link but I removed it and it’s fixed now. Thank you so much to everyone who helped!