How would I count all badges a user has?

Assuming you’re talking about all of the badges the user has on Roblox, you’re unfortunately going to have to do a chain of http requests to their badges API (make sure to switch to v1), which may take a while depending on how many badges a given user has (for example my account at the time of writing has 1590 badges, so it takes at least 16 GET requests to count the number of badges I have).

You basically need to keep doing the get request with the returned nextPageCursor. The following is a translated version of the code that wrote to get my own badge count. An important caveat is that you need to use a proxy to get this information, as HttpService is not allowed to request resources from Roblox itself. Look into ProxyService if this is something you want to set up yourself. The code here is just an example of how it would work if HttpService could access Roblox resources.

local Http = game:GetService("HttpService")
local userId = ...
local baseUrl = `https://badges.roblox.com/v1/users/{userId}/badges?limit=100`

local badgeCount = 0
local cursor = nil
repeat
    -- cautionary wait; this may be unnecessary,
    -- but I didn't want to get rate-limited myself lol
    wait(1)
    local url = if cursor then baseUrl .. `?cursor={cursor}` else baseUrl
    local response = Http:RequestAsync({
        Url = url,
        Method = "GET",
    })
    if response.Success then
        local body = Http:JSONDecode(response.Body)
        badgeCount += #body.data
        cursor = body.nextPageCursor
        print("Current badge count:", badgeCount)
    else
        print(response.StatusCode)
        print(response.StatusMessage)
        -- Going to assume we got rate limited
        wait(30)
    end
until cursor == nil

print(badgeCount)
Original Code

Original code that I ran using Lune.

local net = require "@lune/net"
local task = require "@lune/task"

local USER_ID = 143432
local baseUrl = `https://badges.roblox.com/v1/users/{USER_ID}/badges?limit=100`

local badge_count = 0
local next_page_cursor: string? = nil
repeat
    task.wait(1)
    local response = net.request({
        url = baseUrl,
        method = "GET",
        query = {
            ["limit"] = "100",
            ["cursor"] = next_page_cursor
        },
    })

    if response.ok then
        local body = net.jsonDecode(response.body)
        badge_count += #body.data
        next_page_cursor = body.nextPageCursor
        print("Badge count:", badge_count)
    else
        print("Error in response:")
        print(response.statusCode)
        print(response.statusMessage)
        task.wait(10)
    end
until next_page_cursor == nil

print(`Number of badges: {badge_count}`)

If you try running this code you’ll notice, even with the waits removed, it takes a while to complete, so I’d advise dropping the idea unless strictly necessary, especially with all the extra effort you need to go through of setting up a proxy.

Assuming that you do go forward with it, I’d strongly suggest implementing some sort of system that will only need to do this once, store a reference to the latest badge the user has been awarded and the number badges the user has to your own data store, and update it only when the user has gotten new badges.

4 Likes