Roblox Discord Webhook Proxy Server

Discord no longer bans webhooks coming from Roblox. The Discord proxy server has shutdown. Please, switch your -based URLs to use Discord instead.


How can i send an embed.

1 Like

You know this can and will get your Discord account banned right?

This is awesome! Thank you for sharing!


I remember jake…

Then I made a new Discord account – he is scary.


Thanks a lot for this!

1 Like

Thanks for using it! Let me know if you have any issues with the service or there’s any functionality I’m missing.

Pushed an update which will ban webhooks for abusing rate limits.
(You have to send requests very frequently for this to happen)

If you do get banned, just make a new webhook and send less requests. :+1:


I can’t thank you enough for this :smile:

1 Like

Thank you so much! I can finally re-add my mod call feature which we’ve been needing for a long time. :stuck_out_tongue:


Thanks bud, you saved my business! :slight_smile:

1 Like

New Roblox API provides appropriate information for scripts to abide by Discord’s rate limits.
If Discord lifts the Roblox user-agent ban, I will be shutting down this proxy.

In the event of the proxy shutting down, I’ll provide a library for you to use webhooks in your scripts.


I used this before Roblox got banned from Discord

While there are existing Discord libraries, none of them abide by Discord’s dynamic rate limits.

You could edit or provide a new script that abide by Discord’s dynamic rate limits, if Roblox get’s unban from Discord.

I made one pretty similar to yours at around the same time! It’s a bit of a bummer that it wasn’t advertised enough.


Running into a problem where embeds aren’t being posted when I send to the discord server. They all worked fine until around yesterday.

For example, if I run the following code in the command bar…

local HttpService = game:GetService("HttpService")

local suggestion_webhook = "" --removed the ID I used

local options = {}
options.timestamp = "2018-05-14T05:30:08Z"
options.description = "Test"
options.footer = {
    icon_url = "",
    text = "Test"
} = {
    name = "WrathOfTheElvhen",
    url = "",
    icon_url = game.Players:GetUserThumbnailAsync(

local HookData = {
    ["embed"] = options,
    ["content"] = "Test"

HookData = HttpService:JSONEncode(HookData)

HttpService:PostAsync(suggestion_webhook, HookData)

It would only post the following:


Running the JSON in the Embed Visualizer works fine, so I have no idea what the problem is…

JSON Encoding
      "footer": {
        "icon_url": "",
        "text": "Test"
      "description": "Test",
      "timestamp": "2018-05-14T05:30:08Z",
      "author": {
        "icon_url": "",
        "name": "WrathOfTheElvhen",
        "url": ""
  "content": "Test"

I’m pretty sure the rate limits are all good and that you didn’t ban anything. I even tested it in other servers and nothing…Do you perhaps have any idea what happened @Osyris?

1 Like

Webhooks are

{ "embeds":[
{ embed content }, { second embed content }
], "content":"Test"}

In your case, just do

local HookData = {
    ["embeds"] = {options},
    ["content"] = "Test"

The proxy server just forwards your POST payload to Discord, the only thing I change is your headers (which shouldn’t matter).

Seems like something on Discord’s end changed. Does @Semaphorism’s advice fix your problem?

1 Like

Ah, yeah, I see the problem. I was using [“embeds”] = {options} before, but I changed it because, while trying to find the problem, an embed visualizer stated that it should be “embed” not embeds. And when I did that, it would send (just not the embed). Changing it like @Semaphorism suggested still wouldn’t work in game, however a POST request using the JSON string I posted above would post just fine. Which I really should have tested first.

What I didn’t realize is that problem came about from the function I used to generate the timestamp, and that’s why it never posted. I must have done a bad job debugging it, because I completely missed that was the original problem.

Timestamp function
local function getCurrentTime()
	local currentTime ="!*t")

	local hour = currentTime.hour
	local minute = currentTime.min
	local second = currentTime.sec

	local day =
	local month = currentTime.month
	local year = currentTime.year

	-- ISO8601 support
	if hour <= 10 then
		hour = 0 .. hour
	if minute <= 10 then
		minute = 0 .. minute
	if second <= 10 then
		second = 0 .. second
	if day <= 10 then
		day = 0 .. day
	if month <= 10 then
		month = 0 .. month
	if year <= 10 then
		year = 0 .. year

	return ("%s-%s-%sT%s:%s:%sZ"):format(year, month, day, hour, minute, second)

If you look you can probably see the problem. If the day was <= 10, then it’d add a leading zero. Well, today is the 10th, so it gave an incorrect timestamp format (“2018-08-010T00:00:00Z”) lol.

Sorry for the trouble! And thanks for the help and quick responses @Osyris and @Semaphorism