> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rbxweb.net/llms.txt
> Use this file to discover all available pages before exploring further.

# UGC Scanner

> Scan your Roblox catalog (your own UGC items + items sold by groups you own) and export to CSV.

The **UGC Scanner** lets an authenticated Discord user scan the Roblox catalog for items they sell — either under their own account or under a group they own — and export the result as a CSV.

It's available at **Dashboard → UGC Scanner**, in the same user-level menu group as [Roblox Authorization](/features/roblox-verification). You don't need a Discord server to use it.

## Prerequisites

You must link at least one Roblox account via [Roblox Authorization](/features/roblox-verification). If you haven't, the UGC Scanner page shows a card pointing you there.

By default the scanner reads from public Roblox endpoints, so you don't grant the bot any special permission to your account — it only needs to know which Roblox account is "yours" so it can show you the groups you own.

If you want the scanner to also discover **groups where you don't own but have the `Spend Community Funds` permission** (the Roblox role permission that gates access to **Creator Hub → Community → Revenue**, including the monthly Sales CSV the scanner ingests), click **Reauthorize with group access** on the UGC Scanner page. That re-runs the Roblox OAuth flow and asks you to grant the additional `group:read` permission — which only the UGC Scanner uses, and which basic verification never asks for.

<Note>
  This permission must be set under the role's **Legacy permissions** in Creator Hub — not the new Roles set introduced with the Communities redesign. Roblox's public API does not yet expose the new permission system (including multi-role assignments per member), so if you only grant access via the new system the scanner can't see it. Set the legacy *Spend Community Funds* toggle on the role too.
</Note>

## Flow

<Steps>
  <Step title="Open UGC Scanner">
    Sidebar → **UGC Scanner**.
  </Step>

  <Step title="Pick a Roblox account">
    If you've linked multiple accounts, tabs at the top let you switch between them. Each account has its own scan history.
  </Step>

  <Step title="Refresh groups">
    Click **Refresh groups** the first time. The scanner fetches the list of groups you own (and, if you've reauthorized with group-read access, groups where you have economy admin permissions) and shows them as cards alongside your own profile.
  </Step>

  <Step title="Select a target">
    Click a card — your user (your own catalog), any group you own, or any group where you have admin permissions. The selected card glows blue. Admin-permission groups are tagged with a small "Admin" chip on the card icon.
  </Step>

  <Step title="Start Scan">
    Click **Start Scan**. The status panel shows live progress (items scanned). A scan completes when the catalog cursor runs out of pages.
  </Step>

  <Step title="Generate CSV">
    Once a target has scanned items, an **Existing Scans** card appears with a per-target row. Click **Generate CSV**, pick which columns to include (ID / Name / Description are always included), and you get a 1-hour download link.
  </Step>
</Steps>

## Targets

Each Roblox account shows two kinds of targets:

| Type                      | What it scans                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **User** (always present) | Items sold under your own Roblox account                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| **Group**                 | Items sold by a group where your role's rank is `255` (owner). One card per owned group.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| **Group · Admin**         | Items sold by a group where you're NOT the owner but your role has the **Spend Community Funds** permission (under the role's *Legacy permissions* in Creator Hub) — the same Roblox permission required to access the group's Revenue page and download the monthly Sales CSV. Only shown after you click **Reauthorize with group access** on the UGC Scanner page (grants the bot's `group:read` OAuth scope). The new Roles set in Creator Hub (multi-role assignments and granular permissions) is not yet exposed by Roblox's public API, so it doesn't count toward this check. |

If a group's icon doesn't appear, the bot's batched icon fetch hit a transient error — try **Refresh groups** again.

## Scan controls

* **Start Scan** — enabled when a target is selected and no scan is currently running for your account.
* **Stop** — enabled while a scan is `pending`, `active`, or `stop_requested`. Clicking stops the scan at the next page boundary; items scanned so far are kept.
* **Status panel** — shows a spinner and the running item count while a scan is alive. The total isn't known up front because Roblox's catalog endpoint doesn't return a total.

Scans run **one at a time per bot process**. If another user starts a scan while yours is queued, both run in order. This keeps each scan running at the full per-IP rate-limit budget against Roblox.

## Scan credits

Every Discord user gets **3 free scans per week**. Each scan costs **1 credit per selected target** — scanning a group counts as 1 regardless of how many items inside, and scanning your own catalog is another 1.

Credits refill weekly. The reset day is **the same weekday you first authorized your Roblox account** — so a user who authorized on a Wednesday refills every Wednesday, and a user who authorized on a Friday refills every Friday. Re-authorizing the same Roblox account, or adding a second / third / fourth Roblox account on the same Discord, does not reset the anchor — your first-ever auth date is what counts.

**Surplus carry-over:** if you have unspent credits at the end of a week (from a future tier-up promotion, for example), they roll over. The refill never reduces an existing surplus — it only tops up if your remaining count is below the cap.

**Paid scans** (top-ups) are reserved for a future feature and are **currently not available**. The dashboard shows a "Paid scans: 0 (currently not available)" row as a placeholder. Once paid scans ship, the deduction order will be **free first, then paid** — so you don't accidentally burn through a paid top-up while you still have free credits sitting on the counter.

**Over-quota selection:** if you select more targets than you can afford, the extra cards light up red and the Start button disables with a "Need N more credits" label. Deselect enough to fit your remaining count, or wait for the next refill.

## Earning extra free scans — vote on Top.gg

The **Scan balance** card has a green **Vote & top up** button inside the Free track. Clicking it opens RBX ToolBot's [Top.gg vote page](https://top.gg/bot/1480454192358228102/vote) in a new tab. Once you vote, the bot's webhook adds **+2 free scans and +4 free parses** to your remaining balance.

After a successful vote the button greys out and shows `Vote again in Xd Yh` — you can vote again once every **3 days** (the per-user cooldown). Replays inside that window are no-ops, so refreshing or re-voting won't double-credit. The added credits stack on top of your existing balance and are kept by the weekly refill (the cycle never reduces a surplus).

## CSV export

Click **Generate CSV** on an Existing Scans row to open the field-selection modal.

* **Required (always included):** `id`, `name`, `description`. Greyed out and pre-checked — you can't remove them.
* **Optional:** `price`, `lowestPrice`, `lowestResalePrice`, `favoriteCount`, `itemCreatedUtc`, `itemType`, `assetType`, `url`, `saleStatus`, `saleLocationType`, `lastScannedAt`. All pre-checked; uncheck what you don't want.
* **Per-month sales columns:** for every month you've uploaded sales data for this target, a `<year>_<month>` column (e.g. `2026_april`) holding that asset's **quantity sold that month** (no per-month profit). Chronological order; blank for assets with no sales that month. Only appear when sales data exists.
* **Sales columns (always last two):** `Total Sales Qty` (all-time units sold) and `Sales Profit` (all-time R\$) — populated from uploaded Roblox sales CSVs (see [Sales Data upload](#sales-data-upload)). Both are **blank** until you upload sales data for that target.

Excel-friendly tricks built in:

* The CSV is written with a **UTF-8 BOM**, so emoji / Cyrillic / CJK render correctly (no `ðŸ¥¶` mojibake).
* The `id` column is wrapped as `="<digits>"`, so Excel keeps it as text instead of converting long IDs to scientific notation (`1.23E+13`).
* The `url` column is wrapped as `=HYPERLINK(...)`, so URLs are clickable in Excel and Google Sheets.

### Download link

After clicking **Generate**, the page shows a green download card. The link is valid for **1 hour**. After that:

* The link returns `410 Gone` if you try to use it.
* A background task on the bot deletes the file from disk so it doesn't linger.
* The cleanup also runs on bot startup, so even if the bot was offline the entire hour, the file is removed when it comes back up.

You can generate a new CSV (with different columns, for example) any time — every download has its own token and 1-hour window.

## Delete data

The **Delete data** button on an Existing Scans row wipes all scanned items for that target. Use this if you re-scan and want a fully clean slate. It doesn't affect any other target on the same Roblox account.

## Sales Data upload

Per-item sales counts and revenue are **not** in the public catalog — Roblox only exposes them as a monthly **Sales CSV** in your Creator Hub. The UGC Scanner lets you upload those monthly files; the bot parses them in the background and tallies each sale onto your scanned items.

Every row in the **Existing Scans** card has a **Sales Data** strip with one pill per year (newest first, scrollable left/right). Click a year to open the month popup.

<Steps>
  <Step title="Download the monthly Sales CSV from Roblox">
    Creator Hub → your group/account → **Analytics → Sales** → export a month. The file is named `Sales_Group<id>_<YYYY-MM>.csv` (or `Sales_User<id>_<YYYY-MM>.csv` for your own account).
  </Step>

  <Step title="Do not open it in Excel, do not rename it">
    Opening the CSV in Excel rewrites large Asset IDs into scientific notation (`8.74441E+13`) — those rows can no longer be matched and are skipped. Renaming the file breaks the group/month check. Upload it exactly as Roblox named it.
  </Step>

  <Step title="Pick the month">
    Click a year pill, then a month tile. Months with no data are greyed; months with data show the sale count and profit and a red **×** to delete that month.
  </Step>

  <Step title="Upload">
    Choose the CSV. The filename's group/user id must match the card you opened it from (and the month must match the slot you clicked) — otherwise it's rejected. Parsing happens in the background; the pill recolours when it completes.
  </Step>

  <Step title="Bulk upload (optional)">
    The **Bulk upload** button at the bottom of the popup accepts multiple months at once. Every file must be for the same group/user as the card — a file for a different target rejects the whole batch.
  </Step>
</Steps>

**Kept columns.** Only `Date and Time`, `Location`, `Location Id`, `Asset Id`, `Asset Name`, `Asset Type`, and `Revenue` are stored. `Id`, `Buyer User Id`, `Universe Id`, `Universe`, `Hold Status`, and `Price` are dropped at parse time and never saved.

**Re-uploading a month replaces it.** Uploading the same month again wipes that month's stored rows and re-inserts them, so totals never double-count. Use this to correct a bad upload — just upload the correct file again.

**How it tallies.** For each Asset ID in the file:

* If the item is already in your scan for that target → its `Sales Qty` (units sold) and `Sales Profit` (sum of `Revenue`) are recomputed across **all** uploaded months.
* If the item was sold but never scanned → a sales-only row is added so it still appears in the export.

These two totals are the `Sales Qty` / `Sales Profit` columns in every CSV export.

**Parse quota.** Sales upload isn't tier-gated, but it has its own weekly allowance separate from scans: **6 free parses per week**, where **1 uploaded CSV file = 1 parse credit** (a bulk upload of 12 files costs 12). Parse credits refill on the **same weekly day as your scan credits** (your first-authorization anchor). A failed parse is refunded. If you don't have enough parse credits for the files you selected, the upload is rejected — wait for the weekly refill or upload fewer files. Both counters are shown in the **Free** card below "Scan my UGC" (Scans + Parsing rows).

## Sales Analytics

Once you've uploaded sales data, a **Sales Analytics** card appears directly below Existing Scans. It turns the raw monthly CSVs into responsive charts and tables. Not tier-gated — available to every authorized account, the same as the sales upload.

The card is **collapsed by default** — it shows a single **Load analytics** button. Click it and the data is crunched (this also resolves the Roblox experience names, which can take a moment): a spinner with a progress bar shows below the button, then the full dashboard renders. The aggregation runs the panel queries **in parallel** on the database so even a large seller loads in roughly one query's worth of time. The card stays collapsed until you ask for it so a normal UGC Scanner visit isn't slowed down.

Scopes you've already viewed this session are **cached in the browser**, so flipping back to a target you've already looked at is instant; the common targets are also prefetched in the background after the first load. The **Refresh** button (top-right of the card) clears that cache and re-fetches fresh data for the current view — your Target and each panel's filters are kept, only the data is reloaded. The cache is also dropped automatically when you switch Roblox accounts or upload new sales data.

**Top controls:**

* **Target** — defaults to **All targets** (every scanned user/group on the selected Roblox account combined). Narrow it to any single scanned target to drill down. Changing the target reloads the card and resets every panel's filters.
* **Panels** — a checkbox per panel. Untick one to hide that panel; the choice is remembered in your browser across visits.
* **Refresh** — clears the session cache and re-fetches fresh data for every panel, keeping your current Target and per-panel filters.

**Per-panel time filter.** Each chart panel header has a compact **filter button** (📅) showing the current range ("All dates" by default). Click it to open a small popover with two chip groups — **Years** and **Months** — all selected by default; click a chip to **deselect/exclude** that year or month from *that panel only*, or use **Select all** / **Clear selection** at the bottom of the popover. The button label updates to summarise the active filter and highlights when narrowed. Panels filter **independently**, so you can look at this year's Top Items while the By-month chart still shows everything. Deselecting refetches just that panel (a small spinner shows in it); results are cached so toggling back is instant. Click anywhere outside the popover to close it.

**Panels:**

* **KPI tiles** — total sales and total revenue (R\$) for the loaded target (the KPI row reflects the Target, not the per-panel chip filters). Hover either tile for a one-line explanation of exactly what it counts.
* **Sales by month** — a line chart with a dot per month and the value above every point, and the months as a labelled grid along the bottom. Toggle between **R\$** (revenue) and **Qty** (units). With **All targets** selected a **Split by target** button appears — turn it on to draw a separate coloured line per scanned target (each line's values are labelled in that line's colour, with a colour legend); turn it off to merge back to one line.
* **Top items** — your best sellers by revenue (top 15) as a compact, table-aligned list: rank, full item name, a short revenue bar, units sold, and revenue — every row's columns line up. Hover a row for the asset type. No separate data table.
* **Sales by location** — the top **15** places your items sold, ranked, with a donut chart and a clickable legend (units sold + revenue per row). Roblox's CSV only records a generic location ("Game" / "Website") plus a numeric id, so the dashboard **resolves in‑experience ids to the actual Roblox experience name** (e.g. "Brookhaven 🏡 RP") — names are looked up once and cached. Each in‑experience row has an **↗ open** button that opens that game on Roblox in a new tab; the **Website** row's ↗ opens the Roblox catalog. Everything past the top 15 is folded into a single **Other (N locations)** row so the totals still add up.
* **Sales by asset type** — a donut chart with a clickable legend, one row per asset type (PantsAccessory, Hat, …).

For both donut panels, **click a legend entry to filter that location/type in or out**; the donut and the panel's subtotal recalculate live so you can isolate or exclude a slice.

The card refreshes automatically a few seconds after a new sales CSV finishes parsing or after you delete a month — no reload needed.

## Paid top-up

When you run out of free scans/parses you can buy more from the **Paid** card (right below the "Paid" title). Pick a quantity with the **− / +** stepper; the button shows the **live total price drawn from Whop** and a preview of exactly what you'll get:

* **1 unit = 4 paid scans + 8 paid parses.** The per-unit price comes straight from Whop (so it always reflects current pricing). Buying *N* units costs *N ×* the unit price and grants `4N` scans + `8N` parses.
* Click **Buy** → a Whop checkout opens in a new tab. After you pay, your Paid balance updates automatically (within a few seconds).
* **Free is always spent before paid** — paid credits only start being consumed once your weekly free allowance is exhausted, so a top-up never goes to waste.
* Paid credits **do not expire** and are **not** reset by the weekly refill.
* This is a **personal** purchase tied to your Discord account. It is **not** a server upgrade and has nothing to do with Premium/VIP tiers.

If the Paid card shows *"top up (not yet ready)"*, top-ups aren't configured for the current environment yet.

## Limits & notes

* **Sales data comes from your uploaded monthly CSVs**, not the public catalog — see [Sales Data upload](#sales-data-upload). The scanner additionally shows favorites count (a popular-item proxy) and resale floor price (for Limiteds), both of which are public.
* **Favorite counts come from the catalog response directly** — no separate fan-out call, so a 10k-item scan completes in roughly the same wall-clock time whether or not you include the favorites column.
* **Anonymous calls only.** The scanner uses Roblox's public catalog endpoints with no auth, so its throughput is capped at the per-IP anonymous rate limit (community-empirical \~60 req/min). The scanner stays at 50 req/min to leave headroom.
