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:
- Catalog APIs that don’t scale cleanly with concurrent players
- Commerce APIs that lie or under-specify for bundles vs assets
- No cheap 2D path for arbitrary avatar looks (grids stay 3D-heavy and slow on cold open)
- Descriptions lose product identity (assets stay; bundle provenance dies)
- 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/rbxthumbAvatar*) → current platform avatar by userId - Asset/bundle thumbs → single products
- Outfit
rbxthumbneeds 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 openedPromptCreateOutfitsaves into the caller’s avatar editor (wrong for public grids)MeshPart.RenderFidelitywrite (PluginSecurity)
Request (any one would unlock a generation of avatar UIs):
CreateTemporaryOutfitFromDescription(description) → outfitIdusable withrbxthumbOutfitGetDescriptionThumbnailAsync(humanoidDescription, size, pose?)→ content URL- Rate-limited ViewportFrame snapshot for experiences
- Open CreateThumbnailPlayer / PerformCreateOutfitWithDescription for experience use
- 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
bundleIdis 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)
- Recommendation page-size control — official limit instead of “whatever count came back.”
- Emote short audio preview as a first-class asset representation for emote browsers.
- Documented
ClearCachedAvatarAppearanceguidance after wear/try-on so clients don’t show sticky looks. - Keep
ConformToAvatarRulesAsync/ default clothing checks as the blessed apply path; document common failure modes. - Text filter path for non-interactive server pipelines — bulk import / moderation jobs that don’t have a connected player session.
- Continued investment in UI selection / clipping edge cases that dense product grids hit on gamepad and mobile.
- 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.
