Avatar catalog / try-on engine wishlist (AES, commerce, outfits, thumbnails, ownership)

Avatar catalog / try-on engine wishlist

Hi Roblox,

This is a consolidated engine / API feature wishlist for experiences that do avatar work at scale: catalog browse, try-on, outfit grids, bulk buy, wear/apply, emotes, and social hangouts where avatars are the product.

These come from building and operating avatar-heavy experiences — not theory. The goal isn’t one game’s roadmap; it’s platform surface that every avatar catalog / dress-up / UGC fashion experience ends up reinventing.

If something below already exists as a supported public API, please point to the docs and I’ll update the list.


Why this matters across avatar games

Avatar experiences repeatedly hit the same walls:

  1. Catalog APIs that don’t scale cleanly with concurrent players
  2. Commerce APIs that lie or under-specify for bundles vs assets
  3. No cheap 2D path for arbitrary avatar looks (grids stay 3D-heavy and slow on cold open)
  4. Descriptions lose product identity (assets stay; bundle provenance dies)
  5. Ownership / privacy results that are hard to turn into honest UI

Improving these helps dress-up games, catalog browsers, runway/fashion games, roleplay outfit systems, and any experience with try-on + buy.


Priority if only a few ship

# Request Who it helps
1 Temporary outfit id / description → thumbnail (or experience Viewport snapshot) Outfit grids, history, shop UIs
2 AES budget scales with CCU or split buckets (search / details / favorites / recs) Every catalog browser
3 Honest commerce data for bundle members (SoldAsBundleOnly + parent ids — not fake “off sale”) Buy All / cart totals
4 Bulk purchase >20 lines or official multi-chunk session + server completion signal Full-outfit carts
5 Ownership result enum: Owned / NotOwned / PrivacyBlocked / Error Owned badges without lying
6 Optional bundle provenance on descriptions (or “applied products” snapshot) Wear, strip, re-buy, equip UI
7 Cheaper static/preview assembly for card-size avatars (LOD / skip full layered cage) Cold first-open feel
8 Batch item details always keyed by request id (no silent drops) Product grids
9 IsPurchaseSimulated callable from experiences Safe analytics / economy gating
10 Package-level apply/remove (not forced per-part loops under apply rate limits) Wear / unequip packages

1) Avatar looks as images + cold preview cost (highest UX impact)

1.1 Thumbnail from arbitrary appearance

Today:

  • User thumbnails (GetUserThumbnailAsync / rbxthumb Avatar*) → current platform avatar by userId
  • Asset/bundle thumbs → single products
  • Outfit rbxthumb needs a native Roblox outfit id
  • Arbitrary in-experience looks (HumanoidDescription, saved outfits, community fits, try-on states) → must build 3D models in ViewportFrames

There is no supported “render this description to a 2D image” path for experiences.

Related surfaces locked or unusable from experiences in practice:

  • ViewportFrame:CaptureSnapshotAsync (RobloxScriptSecurity)
  • Players:CreateThumbnailPlayer (RobloxScriptSecurity)
  • AvatarEditorService:PerformCreateOutfitWithDescription (RobloxScriptSecurity) — could mint outfit ids for thumbs if opened
  • PromptCreateOutfit saves into the caller’s avatar editor (wrong for public grids)
  • MeshPart.RenderFidelity write (PluginSecurity)

Request (any one would unlock a generation of avatar UIs):

  1. CreateTemporaryOutfitFromDescription(description) → outfitId usable with rbxthumb Outfit
  2. GetDescriptionThumbnailAsync(humanoidDescription, size, pose?) → content URL
  3. Rate-limited ViewportFrame snapshot for experiences
  4. Open CreateThumbnailPlayer / PerformCreateOutfitWithDescription for experience use
  5. Supported Open Cloud “render description → image” pipeline for live games

Use cases: outfit history grids, shop mannequin rails, try-on comparison strips, saved fits lists, match/pairing UIs — without paying full 3D build cost per card.

1.2 Cold CreateHumanoidModelFromDescriptionAsync is assembly-bound

On real layered/UGC outfits, cold builds often cost hundreds of ms to well over a second each, even when the ContentProvider queue is empty. Layered clothing cage solve, accessories, and dynamic heads dominate — not only CDN download.

Repeat views can be cheap via Clone caches; first open stays skeleton-heavy.

Request:

  • Faster static/preview assembly path for card-size previews
  • Optional preview LOD (skip full layered cage at grid size)
  • Documented concurrent preview-build guidance (raising parallel builds hitch frames when multiple assemblies resume on one frame)

1.3 Official “static preview rig” helpers

Games already freeze pose / disable state machines so Viewport avatars don’t re-render every frame.

Request: First-class preview helpers: no animator tick, no locomotion state, stable for static catalog poses.


2) AvatarEditorService / catalog scale

2.1 Scale or split the shared AES catalog budget

Today: Search, details, batch details, recommendations, and favorites effectively share a small experience-wide request ceiling (~100 r/s class), independent of CCU and server count.

Pain: One heavy browse session can starve unrelated players in the same experience. Quiet and full servers share the same hard cap.

Request:

  • Scale the catalog bucket with concurrent users (even modestly), or
  • Split search vs details vs favorites vs recommendations into separate budgets, or
  • Publish official per-endpoint quotas + recommended client patterns for catalog-scale games.

2.2 “Card-complete” search results

Today: Games often search, then re-hydrate details for price, restrictions, ownership hints, etc. — double-spending the same budget.

Request: A search mode/flag that returns display-ready fields for product cards so a second details pass is optional, not required.

2.3 Stable batch-details alignment

Today: GetBatchItemDetailsAsync can return fewer rows than requested and omit ids without a stable map.

Request: One result per request id (success | notFound | moderated | error), keyed by id.

2.4 One payload shape for search vs recommendations

Today: Recommended endpoints often nest Creator / Item / Product / Items differently from search/details.

Request: Same item-details shape everywhere (or an official normalization table in docs).

2.5 Document the free fields that already appear in payloads

Especially:

  • UserBasePriceInRobux (sometimes the only usable price on bundles/UGC)
  • Timed/limited: expiration / off-sale deadline / restrictions / resale floors
  • TimedOptions, ItemStatus, premium pricing
  • Bundle composition + ownership hints when privacy allows

Request: An official product card schema: guaranteed vs optional vs privacy-gated fields.

2.6 First-class timed / limited sales support

Request: Stable filters + display contract for timed options / limiteds so “ends in X” and floor prices don’t require reverse-engineering mixed price fields.

2.7 More flexible page sizes

CatalogSearchParams.Limit only allows a fixed set (e.g. 10/28/30/60/120). UI grids often want other page sizes.

Request: Broader limits (or “up to N”) aligned to common grid layouts.

2.8 Favorites shouldn’t compete as hard with browse

Request: Separate quota (or cheaper read path) for favorite get/set so starring items doesn’t contend with search/details under load.

2.9 Always return item kind + normalized type

Catalog rows often carry type labels that belong to AvatarAssetType or BundleType. Games soft-resolve enums and swallow failures.

Request: Every catalog payload includes:

  • ItemType (Asset | Bundle)
  • normalized type enum/string

so UI never has to guess.

2.10 Inventory “All” reliability

GetInventoryAsync / multi-type inventory reads can fail with opaque errors (e.g. 400 across many types) without a clear contract for count limits vs invalid types.

Request: Stable inventory contract, chunking guidance, valid type lists, and clear error codes.


3) Marketplace product honesty

3.1 Stop ProductInfo lying for bundle child assets

Today: Many animation-pack / body-package member assets report IsForSale = false and missing price even when the bundle is the real shoppable product.

Pain: Cart totals, owned labels, and “buy missing pieces” flows go wrong if games trust asset ProductInfo alone.

Request: For members sold only via bundle:

  • explicit SoldAsBundleOnly (or equivalent), and
  • parent bundle id(s),
    instead of a fake “not for sale” signal.

3.2 “Off sale” member assets still sold via a parent bundle

Member assets often look unpurchasable while the bundle is the real product. Games reverse-resolve parent packages and re-price manually.

Request: First-class “commercial parent product(s)” field on details/ProductInfo.

3.3 Commerce identity must be (itemType, id), never id alone

Asset ids and bundle ids can numerically collide. Bulk purchase results, ownership caches, and analytics need an official product key contract (Asset/Bundle + id) in docs and completion payloads.

3.4 Document quotas for Marketplace + description APIs

AES is relatively documented; GetProductInfoAsync, humanoid-description fetches, GetBundleDetailsAsync, etc. still surprise with HTTP 429 under load.

Request: Experience / server / client budgets documented like DataStores.

3.5 Stable dead / moderated id errors

Request: Distinct, stable codes for not found / moderated / deleted vs transient throttle — for ProductInfo and item details. Games invent permanent failure caches to stop retry storms.

3.6 Batch APIs for bundle composition

GetBundleDetailsAsync is easy to 429 when dressing many characters/animation packs.

Request: Batch composition API (or much clearer quotas), similar spirit to GetBatchItemDetailsAsync.


4) Purchases & bulk buy

4.1 Raise bulk line limit or support multi-chunk sessions

Today: PromptBulkPurchase caps around 20 lines. Full avatars often exceed that → sequential prompts; cancel mid-sequence abandons the rest.

Request:

  • Higher avatar-item cap, or
  • Official multi-chunk bulk session (one player UX, one completion report spanning chunks).

4.2 Server-authoritative bulk completion

Today: Bulk finished is easy to observe on the client and hard to treat as durable server truth. Experiences reconcile client-forwarded results against in-flight carts.

Request:

  • Server signal: player + cart/session id + per-line results, and/or
  • Receipt-style confirmation for avatar bulk lines (ownership can remain platform-owned).

4.3 Make IsPurchaseSimulated callable from experiences

Today: Present in the engine surface but RobloxScriptSecurity / uncallable from game scripts in practice.

Request: Allow experiences to detect simulated purchases so Studio/QA doesn’t poison live analytics or economy side effects.

4.4 Richer purchase preflight reasons

PlayerCanMakePurchases is useful. Still missing structured reasons for disabled Buy UI (policy, marketplace disabled, region, etc.) so games can show accurate copy instead of a silent failed prompt.

4.5 Restricted marketplace signal matrix

Which Prompt*Finished / purchase signals are:

  • server-only
  • client-only
  • restricted / can throw on Connect

Request: A single official matrix to prevent entire classes of purchase bugs and flaky Studio probes.


5) Ownership & inventory privacy

5.1 Explicit ownership result enum

Today: Privacy-aware ownership means false / error / empty is ambiguous — “not owned,” “can’t tell,” and “permission denied” look similar in UI.

Request: Owned | NotOwned | PrivacyBlocked | Unknown/Error (or equivalent) on ownership APIs.

5.2 Lightweight “local player commerce ownership” path

Full inventory grant via PromptAllowInventoryReadAccess is correct security, but many games only need honest Owned badges for the local player’s buy UI.

Request: A minimal permission + query path for “can show owned state for catalog cards” without implying full inventory browsing.

5.3 Bundle vs asset ownership hard to misuse

Request: Docs + APIs that make it difficult to:

  • “verify” a bundle by only checking child assets, or
  • prompt decomposed pieces when a bundleId is known.

5.4 Document server vs client ownership budgets

Moving owned-labels client-side is common because server ownership checks don’t scale cleanly under catalog load.

Request: Document server vs client ownership budgets and recommend the intended architecture for “Buy / Owned” UI.


6) Descriptions, bundles, and provenance

6.1 Optional bundle provenance on HumanoidDescription

Today: Descriptions store applied asset ids, not bundle ids. After wear, product identity (character package, animation pack, shoe bundle, dynamic head) is lost unless the experience maintains its own provenance store and reverse-resolve logic.

Request: Optional provenance metadata, e.g. bundle id → applied member assets, or an “applied products” snapshot including bundles.

6.2 Reverse asset → bundle: document multi-parent behavior

GetBundlesByAssetIdAsync is a major win. Remaining pain:

  • multi-parent assets still need a “best commerce bundle” pick
  • reverse misses must not be cached as permanent “no bundle”

Request: Official multi-parent ranking guidance + negative-cache rules.

6.3 BundleType naming consistency

Payloads still mix aliases (e.g. animation bundle naming variants).

Request: One canonical string/enum across search, details, bundle details, and ProductInfo.

6.4 Resolve playable animation ids from catalog animation assets

Catalog animation assets are often packages/wrappers; experiences still unwrap via InsertService to find a playable Animation.AnimationId.

Request: Official resolve API (or always return a playable id in item details).

6.5 Safer package remove semantics (scales/colors)

A common footgun: removing a body/dynamic-head package in a way that zeroes scale/color props and collapses the avatar.

Request: Documented / safer APIs for “clear package part slots only; preserve player scales and body colors.”

6.6 Package-level apply / remove under rate limits

Avatar apply paths are rate-limited. Bulk “remove a whole package” as N per-asset calls fails mid-way (half the body stays on). Games must force one package op.

Request: First-class apply/remove package APIs with package-level rate limits, not forced per-part loops.


7) Social APIs for avatar hangouts

Avatar games are often social surfaces (inspect players, wear looks, block, chat).

7.1 Public, complete block-list APIs

GetCore("GetBlockedUserIds") is a weak foundation (CoreGui, client-only, historically capped).

Request:

  • Reliable live-player block checks callable from experiences (HasBlockedPlayer-class APIs — confirm callability)
  • Offline IsBlockedUserId(userId) for filtering content by creator when that creator isn’t in the server

7.2 Chatability helpers for empty states

APIs that distinguish “nobody here to chat with” vs “chat restricted” improve social lobby UX.


8) UGC load reliability + preview performance

8.1 Mesh / PBR / animation fetch reliability + permanent-bad signals

Dense avatar UIs (many ViewportFrames / try-on rigs) amplify:

  • MeshContentProvider / SurfaceAppearance / PBR failures
  • dead or private animation loads

Request:

  • Clearer per-asset fetch failure reasons for UI (“moderated / private / CDN / timeout”)
  • Permanent-bad classifications so clients don’t retry storms
  • Better behavior under multi-viewport load

8.2 AnimationTrack limits for emote / try-on browsers

The track cap and destroy semantics are easy to hit when previewing emotes and outfits.

Request: Higher limits and/or safer engine helpers for one-shot preview tracks.

8.3 ContentProvider failure detail for gray cards

Request: Usable detail for “why is this card gray?” (moderated vs CDN vs timeout).

8.4 Studio vs live profiling for ViewportFrames

GPU cost often only shows above 60Hz; hard to validate in Studio alone.

Request: Documented guidance so avatar UI work isn’t mis-measured in Studio.


9) Data & caching tools avatar systems use

Not asking to remove budgets — asking for tools to design within them:

Request Why avatar games care
Widely available, documented multi-key / batch get for DataStores Outfit pages, hydrate batches
Usable client local storage API when it ships (Get/Set) Session caches for catalog/outfits without custom disk hacks
Better visibility into experience-wide vs per-server throttle pressure Catalog + feed + bulk jobs share pools
Stronger invalidation patterns for cross-server caches Messaging is best-effort; avatar content caches need TTL + truth rebuild
Clear same-key write cadence as a hard design constraint Hot counters / snapshots

10) Finish shipping “almost there” APIs to experiences

Please either open these to normal experience scripts or document them as internal-only so docs stop teasing them:

API / surface Today Ask
IsPurchaseSimulated RobloxScriptSecurity / uncallable Open to experiences
CreateThumbnailPlayer RobloxScriptSecurity Open or replace with description thumbs
ViewportFrame snapshot RobloxScriptSecurity Rate-limited for experiences
PerformCreateOutfitWithDescription RobloxScriptSecurity Temp/experience outfit ids for thumbs
ClientStorageService Exists / incomplete / not usable Ship real Get/Set
DataStore multi-get Rolling out / ordered-focused Document + expand where useful

11) Smaller quality-of-life (still real)

  1. Recommendation page-size control — official limit instead of “whatever count came back.”
  2. Emote short audio preview as a first-class asset representation for emote browsers.
  3. Documented ClearCachedAvatarAppearance guidance after wear/try-on so clients don’t show sticky looks.
  4. Keep ConformToAvatarRulesAsync / default clothing checks as the blessed apply path; document common failure modes.
  5. Text filter path for non-interactive server pipelines — bulk import / moderation jobs that don’t have a connected player session.
  6. Continued investment in UI selection / clipping edge cases that dense product grids hit on gamepad and mobile.
  7. BillboardGui / SurfaceGui click reliability guidance (Active, parent, Adornee) as official avatar-world UI docs.

12) Platform investments that already helped (thank you)

Please keep going on these — they made modern avatar games viable:

  • Async catalog / details / inventory APIs
  • PromptBulkPurchase (even with the line cap)
  • Reverse asset → bundle (GetBundlesByAssetIdAsync)
  • Makeup types + MakeupDescription
  • GetBatchItemDetailsAsync
  • Inventory privacy model (right direction; richer result enums would complete it)
  • Accessibility: PreferredTextSize / ReducedMotion / transparency

Closing

Avatar games don’t need Roblox to ship a full fashion product. They need:

  • a cheap way to show looks as images (or much cheaper cold previews),
  • catalog APIs that scale with real multiplayer load,
  • commerce data that matches how items are actually sold (especially bundles),
  • descriptions that remember products, not only mesh ids,
  • ownership results that UI can trust under privacy,
  • package-level apply/remove that doesn’t fight apply rate limits.

Happy to provide minimal repros, example payloads, or re-prioritize for a specific engine squad (Avatar, Marketplace, UI, Data).

Thanks for reading.

4 Likes

I would really like to see a lot more support and care go towards AvatarEditorService. It feels far too restrictive at the moment, and even with attempts to cache data, it regularly hits limits even in relatively small experiences. It feels like something that is more meant for very small (~20-50 players). There used to be an instruction about making a feature request if your specific game required higher limits, but that has since been removed from the documentation.

I specifically really wish we had per user limits. It would be perfect to have an idea on how many calls a user could be making to the methods. Right now, I completely opt out of including any of the above functions except SearchCatalogAsync. As even with caching and cooldowns on using the catalog, a game with ~300-400 ccu still triggers the catalog limit at times. Why waste budget on the other functions when searching is just far more important? The service has so many features and yet it feels so incomplete due to its limits.

I want to let players browse their favourites or recents with up-to-date info using GetBatchItemDetailsAsync. I want to show recomended items when they look at a specific item. I want them to be able to do so without constantly hitting limits and sharing a budget with people across every server.

Besides the 100 limit per second call cross-experience, I have no idea what other limits exist. I would like it to be more clear, and for the 100 limit to be raised or even just removed. Why does this service have such hard limits in the first place? Is there a reason why a user browsing the catalog in-game is a lot more taxing on the servers than doing it through the app or website?

1 Like

Trying to read this, it feels a lot like AI generated request. There is way too much stuff crammed into single request and it’s hard for me to understand what exact features you need.

Should be easy enough to follow if you’re familiar with the avatar APIs.