In short
HTTP 429 (Too Many Requests) is the answer from the web service you called: a webhook, an analytics API, your own server. It accepts only so many requests per second or minute, and you went over. Number of requests exceeded limit is different: it comes from Roblox, which allows each game server 500 HTTP requests a minute (and 2,500 Open Cloud requests). Either way the fix is to send fewer, bigger requests, space them out, and wait longer after each failure.
- Never send one request per event (per kill, per chat message, per player each second). Collect them and send one batch every few seconds.
- Wrap every request in
pcall. A 429 is an error that stops the script if you do not catch it. - After a failure, wait 2 seconds, then 4, then 8, before trying again (exponential backoff, as Roblox's HTTP docs recommend).
What the message means
ServerScriptService.DiscordLog:12: HTTP 429 (Too Many Requests)
Other forms of the same message:
Number of requests exceeded limitNumber of Open Cloud requests exceeded limit
HttpService turns any reply that is not a success into an error with the status code and its name, so a 429 from the far side shows up in Output exactly like a Roblox error. The line number is the GetAsync, PostAsync or RequestAsync call.
Going over Roblox's own limit can make request methods stall for around 30 seconds, per the docs, so a burst of requests can freeze the script that sends them as well as fail.
Causes and fixes
Three things cause this error in practice. Each one below has the smallest code that triggers it, then the fix.
- One request for every event
- Retrying straight away after a failure
- Polling the same address over and over
One request for every event
Logging each kill or each purchase to a webhook sends as many requests as there are events. A busy server, or one exploiter firing the event that triggers it, goes over any limit within seconds. Every server of your game also shares the same webhook limit.
local HttpService = game:GetService("HttpService")
local Players = game:GetService("Players")
local LOG_URL = "https://example.com/api/log"
Players.PlayerAdded:Connect(function(player: Player)
player.Chatted:Connect(function(message: string)
-- one POST per chat message: HTTP 429 (Too Many Requests)
HttpService:PostAsync(LOG_URL, HttpService:JSONEncode({ user = player.UserId, text = message }))
end)
end)
Add each event to a list, and send the whole list in one request every few seconds. Cap the list so a flood of events cannot build an endless queue.
local HttpService = game:GetService("HttpService")
local Players = game:GetService("Players")
local LOG_URL = "https://example.com/api/log"
local SEND_EVERY = 10 -- seconds between batches
local MAX_QUEUED = 200 -- drop the oldest beyond this
local queue: { { [string]: any } } = {}
Players.PlayerAdded:Connect(function(player: Player)
player.Chatted:Connect(function(message: string)
table.insert(queue, { user = player.UserId, text = message, at = os.time() })
if #queue > MAX_QUEUED then
table.remove(queue, 1)
end
end)
end)
while true do
task.wait(SEND_EVERY)
if #queue > 0 then
local batch = queue
queue = {}
local ok, err = pcall(function()
HttpService:PostAsync(LOG_URL, HttpService:JSONEncode(batch))
end)
if not ok then
warn("[ChatLog] batch not sent:", err)
end
end
end
Logging what players type to an outside service has privacy rules of its own. Roblox's own analytics (AnalyticsService) and the Creator Hub dashboards need no HTTP at all for most game metrics.
Retrying straight away after a failure
A loop that retries as soon as a request fails turns one 429 into dozens, which keeps the limit hit and can also use up Roblox's own 500 a minute, so the error changes to Number of requests exceeded limit.
local HttpService = game:GetService("HttpService")
local function fetchConfig(): string
while true do
local ok, body = pcall(function()
return HttpService:GetAsync("https://example.com/api/config")
end)
if ok then
return body
end
-- retries with no wait: more 429s, then Number of requests exceeded limit
end
end
print(fetchConfig())
Wait between attempts and double the wait each time, give up after a few tries, and fall back to defaults so the game still runs.
local HttpService = game:GetService("HttpService")
local DEFAULT_CONFIG = "{}"
local function fetchConfig(): string
local delay = 2
for _ = 1, 4 do
local ok, body = pcall(function()
return HttpService:GetAsync("https://example.com/api/config")
end)
if ok then
return body
end
warn("[RemoteConfig] request failed, retrying in", delay, "seconds:", body)
task.wait(delay)
delay *= 2 -- 2, 4, 8, 16
end
return DEFAULT_CONFIG
end
print(fetchConfig())
Polling the same address over and over
Checking a web service every second for news (a ban list, an event schedule) is 60 requests a minute from every server. Twenty servers make that 1,200 a minute to the same service.
local HttpService = game:GetService("HttpService")
while true do
-- every second, from every server: HTTP 429 (Too Many Requests)
local body = HttpService:GetAsync("https://example.com/api/event-status")
workspace:SetAttribute("EventActive", body == "on")
task.wait(1)
end
Ask much less often, cache the answer, and keep the old value when a request fails. For news that every server needs at once, MessagingService can push it to all servers of your game without polling.
local HttpService = game:GetService("HttpService")
local CHECK_EVERY = 60 -- seconds
while true do
local ok, body = pcall(function()
return HttpService:GetAsync("https://example.com/api/event-status")
end)
if ok then
workspace:SetAttribute("EventActive", body == "on")
else
warn("[EventStatus] keeping the last value:", body)
end
task.wait(CHECK_EVERY)
end
Fix it in your place
Paste the error, RoCode fixes it in your place
Copy the line from Output and paste it here. RoCode opens the script it names in the place you have open in Studio, works out which of the causes above it is, and edits the code there instead of handing you a snippet to paste.
RoCode is an AI agent for Roblox Studio: it reads the scripts in the place you have open, finds the line and edits it there, and every change is an undo point. It runs on Windows or macOS with a desktop browser. Free to start, with free credits every day.
How to find the line that causes it
- Click the red line in Output to open the script at the request that was refused.
- Ask how often that line runs: once per event, once per player, in a loop? Add
print("request", os.clock())above it and press Play to count. - Open the Observability Dashboard in Creator Hub to see your game's HttpService request counts and status codes, including 429s, across live servers.
Questions
What is the HttpService limit in Roblox?
500 HTTP requests a minute per game server for ordinary requests, and a separate 2,500 a minute for Open Cloud requests, according to Roblox's In-game HTTP requests page. The service you call has its own limits on top.
What is the difference between HTTP 429 and Number of requests exceeded limit?
HTTP 429 is sent by the web service you called. Number of requests exceeded limit comes from Roblox when one game server goes over its own HttpService limit.
How do I stop Discord webhook rate limits?
Batch messages and send at most one request every few seconds per server, and back off after a 429. Remember that every server of your game uses the same webhook. Check the service's own rules too: some do not want game traffic at all.
Does pcall stop the 429?
No, it stops the error from crashing your script so you can wait and retry. Sending fewer requests is what stops the 429.
Can RoCode fix it?
Yes. Paste the line into RoCode. It reads the script in your open place and rewrites the requests to batch, cache and back off.
Sources and further reading
- Roblox Creator Docs: In-game HTTP requests. the 500 and 2,500 a minute limits, stalls, backoff and batching
- Roblox Creator Docs: HttpService. GetAsync, PostAsync and RequestAsync
- Roblox Creator Docs: MessagingService. sending news to every server
- MDN: 429 Too Many Requests
How the code was checked: every block marked Fixed passes Luau's strict type checker against Roblox's API definitions (luau-lsp, 5 November 2026), and every block marked Breaks compiles and fails only when it runs. The message wording was checked against the message strings in Roblox Studio itself (macOS build installed 2 November 2026), and the limits against the In-game HTTP requests docs page, on 5 November 2026. A type check catches misspelt APIs and wrong types, not game logic, so playtest in Studio before you publish.