Social
It is common for entertainment apps and games to include social features for interactions between players. Each user on Jest can set up their profile with a username and a customizable avatar. This is an optional feature and some users may not have a profile yet and guest users will not have one. You should always account for that, and use reasonable fallbacks for displaying player info in your app.
For player identity and registration state, see Player.
User profile
After the SDK is initialized, you can get the current user's profile. See SDK initialization for HTML5 or Unity for more information.
The method will work for both registered and guest users. For guest players or players who haven't set their profile up yet, the profile or parts of it will be null.
The placeholder avatar.
To ensure a good experience for users, the requested avatar can be 64x64, 128x128, 256x256, 512x512, or 1000x1000 pixels. Use the size that best fits your UI for the least amount of network traffic and the best visual quality.
Get the profile
- HTML5
- Unity
JestSDK.social.getProfile(options?)
Calling getProfile() before the SDK is initialized throws an error.
function exampleGetProfile() {
const profile = JestSDK.social.getProfile();
return {
username: profile?.username ?? "You",
avatarUrl:
profile?.avatarUrl ??
"https://jest.com/public/avatar/avatar-placeholder.webp",
};
}
Pass avatarSize to request a specific avatar size:
JestSDK.social.getProfile({ avatarSize: 128 });
getProfile(options?: {
avatarSize: 64 | 128 | 256 | 512 | 1000
}): {
username: string;
avatarUrl: string | null;
} | null;
Options:
| Name | Type | Description |
|---|---|---|
avatarSize | 64 | 128 | 256 | 512 | 1000 | The size of the avatar to fetch. Defaults to 1000. |
Returns:
| Name | Type | Description |
|---|---|---|
username | string | The username of the currently logged in user. |
avatarUrl | string | null | The URL of the avatar of the currently logged in user. |
JestSDK.Instance.Social.GetProfile(avatarSize)
Returns both the username and a resized avatar URL formatted for Unity texture loading. Unity's UnityWebRequestTexture only natively decodes PNG and JPEG, and the underlying avatar file can be WebP, so the helper routes through Cloudflare Image Resizing to return a format Unity can decode at the size that fits your UI.
private IEnumerator LoadPlayerProfile(RawImage target, TMPro.TextMeshProUGUI nameLabel)
{
Social.PlayerProfile profile = JestSDK.Instance.Social.GetProfile(128);
if (profile == null) yield break; // guest or no profile set
if (nameLabel != null)
nameLabel.text = profile.Username;
if (profile.AvatarUrl != null)
{
using var request = UnityWebRequestTexture.GetTexture(profile.AvatarUrl);
yield return request.SendWebRequest();
if (request.result == UnityWebRequest.Result.Success)
target.texture = ((DownloadHandlerTexture)request.downloadHandler).texture;
}
}
public Social.PlayerProfile GetProfile(int avatarSize = 1000);
Parameters:
| Name | Type | Description |
|---|---|---|
avatarSize | int | Optional. One of 64, 128, 256, 512, or 1000. Defaults to 1000. Other values bucket down to the next supported size. |
Returns a Social.PlayerProfile instance, or null when the player has no profile:
public class Social.PlayerProfile
{
public string Username; // The player's display name
public string AvatarUrl; // Cloudflare-proxied PNG/JPEG URL, or null
}
JestSDK.Instance.Social.GetPlayerAvatar() (deprecated)
GetPlayerAvatar() is deprecated. Use GetProfile(avatarSize).AvatarUrl instead, which also provides the player's username in a single call.
[Obsolete("Use GetProfile(avatarSize).AvatarUrl instead.")]
public string GetPlayerAvatar(int size = 1000);
Parameters:
| Name | Type | Description |
|---|---|---|
size | int | Optional. One of 64, 128, 256, 512, or 1000. Defaults to 1000. Other values bucket down to the next supported size. |
Returns:
| Type | Description |
|---|---|
string | A Cloudflare-proxied URL for the current player's avatar, or null when the player has no avatar. PNG/JPEG-decodable. |
Bots
When apps need to fill in some user slots with bots, we recommend using bot avatars. There are 1000 unique bot avatars, enough to ensure that it's unlikely for two usernames to have the same avatar. They are generated deterministically, so the same username will always return the same avatar.
The avatar sizes are the same as for player avatars: 64x64, 128x128, 256x256, 512x512, and 1000x1000 pixels. It is recommended to request the smallest size that fits your UI for the best performance, as this will minimize network traffic and improve loading times.
| 512x512 | 256x256 | 128x128 | 64x64 |
|---|---|---|---|
The mapping from username to avatar is deterministic and identical across game engines, so the same username yields the same avatar whether your app uses the Unity, Godot, or HTML5 SDK.
Get a bot avatar
- HTML5
- Unity
JestSDK.social.getBotAvatar(opts)
function getBots(usernames: string[]) {
const avatars = [];
for (const username of usernames) {
avatars.push({
username,
avatar: JestSDK.social.getBotAvatar({ username, size: 128 }),
});
}
return avatars;
}
getBots(["Hello", "Jest", "Bots"]);
getBotAvatar(
opts: {
username: string;
size?: 64 | 128 | 256 | 512 | 1000;
}
): string;
Options:
| Name | Type | Description |
|---|---|---|
username | string | Required. The username of the bot. |
size | 64 | 128 | 256 | 512 | 1000 | Optional. The size of the avatar. Defaults to 1000. |
Returns:
| Type | Description |
|---|---|
string | The URL of the bot avatar. |
JestSDK.Instance.Social.GetBotAvatar(username, size)
List<(string username, string avatarUrl)> GetBots(IEnumerable<string> usernames)
{
var bots = new List<(string, string)>();
foreach (var username in usernames)
{
bots.Add((username, JestSDK.Instance.Social.GetBotAvatar(username, 128)));
}
return bots;
}
GetBots(new[] { "Hello", "Jest", "Bots" });
public string GetBotAvatar(string username, int size = 1000);
Parameters:
| Name | Type | Description |
|---|---|---|
username | string | Required. Used as a seed for the avatar — the same username always returns the same avatar. |
size | int | Optional. One of 64, 128, 256, 512, or 1000. Defaults to 1000. Other values bucket down to the next supported size. |
Returns:
| Type | Description |
|---|---|
string | The URL of the bot avatar. |
Custom screenshots
The platform can ask your app for a screenshot. Players trigger this with the camera button in the Jest footer, then caption the capture and post it to chat, share it to another app, or download it.
Register a screenshot provider
- HTML5
- Unity
JestSDK.social.setScreenshotProvider(provider)
By default the SDK captures your app's main canvas automatically, which works for most apps. If automatic capture doesn't produce good results (or you want control over what's shown), register a custom screenshot provider:
JestSDK.social.setScreenshotProvider(() => {
// Return the screenshot as a base64-encoded PNG. Both raw base64 and
// data URLs (e.g. from canvas.toDataURL("image/png")) are accepted.
return myRenderer.captureFrameAsBase64Png();
});
Return null when no screenshot is available — for example while the game is still loading, or on a screen you don't want captured:
JestSDK.social.setScreenshotProvider(() => {
if (game.state !== "playing") {
return null;
}
return game.captureScreenshot();
});
Providers may be async. Pass null to setScreenshotProvider to unregister your provider and restore the SDK's automatic canvas capture.
To preview a capture locally, open the JestSDK debug menu, expand Screenshots (collapsed by default), and click Capture Screenshot. See Test screenshot capture.
setScreenshotProvider(
provider: (() => string | null | Promise<string | null>) | null
): void;
Options:
| Name | Type | Description |
|---|---|---|
provider | function | null | Required. Called when the platform requests a screenshot. Return a base64 PNG (raw or data URL), or null when no screenshot is available. Pass null to restore automatic capture. |
Not available in the Unity SDK yet.
Sharing images
Share an image
- HTML5
- Unity
JestSDK.social.shareImage(options?)
Opens the platform's share sheet for an image — the same sheet the platform's own screenshot button shows, offering chat, the native share sheet and download. Use it behind your own button: a "share my build", "brag about this score" or "send a coupon" action.
await JestSDK.social.shareImage({
image: couponCanvas.toDataURL("image/png"),
entryPayload: { coupon: "SPRING25" },
});
The player picks where it goes and writes the caption themselves, so your app never shares on their behalf without a tap. Every call opens the same sheet the footer's screenshot button shows:
const { canceled } = await JestSDK.social.shareImage();
if (!canceled) {
game.onImageShared();
}
Omit image and the platform captures your app's canvas, or your registered screenshot provider, the same way the platform's own screenshot button does.
When you pass an entryPayload, the platform appends a link to your app to the posted message. Opening that link launches your app with the payload in the entry payload, so a code or coupon travels with the share and is redeemable from chat.
canceled is false only when the image was posted to chat. A share to another app, a download, or a dismissed sheet all report canceled: true. A failed post is reported to the player in the sheet; the promise rejects only when the image is rejected or capture fails before the sheet opens.
canceled: true is not proof that nothing was posted: a player who leaves the page while a post is still landing is reported as cancelled even though the message arrives. Re-sharing on canceled can duplicate the message.
shareImage(options?: {
image?: string;
entryPayload?: Record<string, unknown>;
}): Promise<{ canceled: boolean }>;
Options:
| Name | Type | Description |
|---|---|---|
image | string | Optional. Base64 PNG, raw or as a data URL, at most 2 MB. Omit it to let the platform capture your canvas. |
entryPayload | object | Optional. Handed back to your app when a player opens the shared message. The platform appends a link carrying it to the post. |
JestSDK.Instance.Social.ShareImage(image, entryPayload)
Opens the platform's share sheet for an image — the same sheet the platform's own screenshot button shows, offering chat, the native share sheet and download. Use it behind your own button: a "share my build", "brag about this score" or "send a coupon" action.
string image = JestUtils.TextureToDataUrl(couponTexture);
await JestSDK.Instance.Social.ShareImage(
image,
new Dictionary<string, object> { { "coupon", "SPRING25" } }
);
The player picks where it goes and writes the caption themselves, so your game never shares on their behalf without a tap. Every call opens the same sheet the footer's screenshot button shows:
Social.ShareImageResponse result = await JestSDK.Instance.Social.ShareImage();
if (!result.Canceled)
{
OnImageShared();
}
Omit image and the platform captures your WebGL canvas, the same way the platform's own screenshot button does.
When you pass an entryPayload, the platform appends a link to your game to the posted message. Opening that link launches your game with the payload in the entry payload, so a code or coupon travels with the share and is redeemable from chat.
Canceled is false only when the image was posted to chat. A share to another app, a download, or a dismissed sheet all report Canceled: true. A failed post is reported to the player in the sheet; the task faults only when the image is rejected or capture fails before the sheet opens.
Canceled: true is not proof that nothing was posted: a player who leaves the page while a post is still landing is reported as cancelled even though the message arrives. Re-sharing on Canceled can duplicate the message.
public JestSDKTask<Social.ShareImageResponse> ShareImage(string image = null, Dictionary<string, object> entryPayload = null);
Parameters:
| Name | Type | Description |
|---|---|---|
image | string | Optional. Base64 PNG, JPEG, WebP or GIF, raw or as a data URL, at most 2 MB. Omit it to let the platform capture your canvas. |
entryPayload | Dictionary<string, object> | Optional. Handed back to your game when a player opens the shared message. The platform appends a link carrying it to the post. |
Returns a Social.ShareImageResponse:
public class Social.ShareImageResponse
{
public bool Canceled;
}
Use JestUtils.TextureToDataUrl(texture) (or JestUtils.SpriteToDataUrl(sprite)) to build the data URL. They render the source into an uncompressed copy first, so GPU-compressed (crunched/DXT) or non–Read/Write textures encode correctly — calling Texture2D.EncodeToPNG() on such a texture directly throws an "unsupported texture format" error.