---
metadata:
  - name: generator
    content: Diplodoc Platform v5.52.0
alternate:
  - https://yandex.com/dev/games/doc/en/sdk/sdk-player.md
  - https://yandex.com/dev/games/doc/hi/sdk/sdk-player.md
  - https://yandex.com/dev/games/doc/ko/sdk/sdk-player.md
  - https://yandex.com/dev/games/doc/ru/sdk/sdk-player.md
  - https://yandex.com/dev/games/doc/tr/sdk/sdk-player.md
  - https://yandex.com/dev/games/doc/vi/sdk/sdk-player.md
  - https://yandex.com/dev/games/doc/zh/sdk/sdk-player.md
  - href: en/sdk/sdk-player.md
    type: text/markdown
    title: Markdown version
  - href: ../llms.txt
    type: text/markdown
    title: llms.txt
---
> **Documentation Index:** Fetch the complete configuration index at https://yandex.com/dev/games/doc/en/llms.txt

# Player data

<!-- source: en/_includes/script-common.md -->
<!-- source: en/_includes/script/index-js.md -->

<!-- endsource: en/_includes/script/index-js.md -->

<!-- source: en/_includes/script/requirements-js.md -->

<!-- endsource: en/_includes/script/requirements-js.md -->

<!-- source: en/_includes/script/image-modal-js.md -->

<!-- endsource: en/_includes/script/image-modal-js.md -->
<!-- endsource: en/_includes/script-common.md -->

You can:

- Save game data (completed levels, experience, in-app purchases, etc.) on Yandex servers using SDK methods or transfer it to your own server. Cloud saves allow users to continue playing on different devices.
- Personalize the game using data from the user's Yandex profile, such as their name.

To work with user data, use the `Player` object.

## Initialization {#getplayer}

To initialize the `Player` object, use the `ysdk.getPlayer()` method:

```javascript showLineNumbers
const ysdk = await YaGames.init();

try {
    const player = await ysdk.getPlayer();
} catch (e) {
    // Error initializing the Player object.
}
```

When initializing a `Player` object, the following data is passed:

- User ID — for all players.
- Avatar and name — for authorized players.
- Platform purchase data (only for games with [in-app purchases](https://yandex.com/dev/games/doc/en/console/purchases.md)) — for players from Russia.

For more information about these parameters, see [User profile data](#profile-data).

Access to user data depends on settings in their [profile](https://yandex.com/games/user){.external}. If a player restricts access to personal data, only the ID will be included in the response.

To authorize a user and save game state data on your server, use the optional `{ signed: true }` parameter and the `fetch()` method. This allows you to verify player authenticity using a [secret key](https://yandex.com/dev/games/doc/en/sdk/sdk-purchases.md#key-example) and prevent potential fraud. The key becomes available after [connecting in-app purchases](https://yandex.com/dev/games/doc/en/console/purchases.md#connect).

```javascript showLineNumbers
const ysdk = await YaGames.init();

try {
    const player = await ysdk.getPlayer({ signed: true });

    // Use player.signature for authorization on your server.
    const authData = await fetch('https://your.game.server/auth', {
        method: 'POST',
        headers: { 'Content-Type': 'text/plain' },
        body: player.signature
    });
} catch (e) {
    // Error initializing the Player object or during authorization.
}
```

The `signature` parameter of the request sent to the server contains user data from the Yandex profile and the signature. The parameter represents two strings in `base64` encoding:

```text
<signature>.<profile data>
```

For more information, see [Fraud prevention](https://yandex.com/dev/games/doc/en/sdk/sdk-purchases.md#signature).

{% note info %}

Requests can be sent no more than 20 times within 5 minutes, otherwise they will be rejected with an error.

{% endnote %}


## User authorization {#auth}

### Verifying authorization {#auth-check}

To check if a player is authorized in Yandex, use the `Player` object method `player.isAuthorized()`. The method returns `true | false`.

{% note alert %}

The `player.getMode(): 'lite' | ''` method is deprecated and will be removed from the interface later.

{% endnote %}


### Calling the authorization dialog box {#open-auth-dialog}

To call the authorization window, use the `ysdk.auth.openAuthDialog()` method.

{% note warning %}

Inform the user about the advantages of authorization. If the user doesn't understand why it's needed, they will most likely refuse to authorize and exit the game.

For more information, see [Authorization Offer](https://yandex.com/dev/games/doc/en/requirements/1/2.md#auth-offer).

{% endnote %}


```javascript showLineNumbers
const ysdk = await YaGames.init();

try {
    let player = await ysdk.getPlayer();

    // Player is not authorized.
    if (!player.isAuthorized()) {
        try {
            // Opening the authorization window.
            await ysdk.auth.openAuthDialog();

            const authorizedPlayer = await ysdk.getPlayer();

            player = authorizedPlayer;
        } catch (e) {
            // Error during player authorization or re-initialization of the Player object.
        }
    }
    // Player successfully authorized.
} catch (err) {
    // Error initializing the Player object.
}
```

## In-game data {#ingame-data}

To work with the user's in-game data, use the `Player` object methods.

### player.setData(data, flush) {#setdata}

Saves the user data. The maximum data size per player is 200&nbsp;KB.

**Method signature**

```typescript
function setData(data: object, flush: boolean) => Promise<void> {}
```

Accepts parameters:

<div class="table-25 table-2c25">

#|
|| **Parameter** | **Type** | **Description** ||
||`data` | `object` | An object containing key-value pairs. ||
|| `flush` | `boolean` | Determines the order of data transmission:
- `true` — data will be sent to the server immediately.
- `false` (default value) — the data transmission request will be queued. ||
|#

</div>

The method returns a `Promise` that indicates whether the data was saved or not.

At `flush: false`, the returned result only shows the data validity (the data has been queued and will be sent later). At the same time, the `player.getData()` method will return the data set by the last `player.setData()` call, even if it has not been sent yet.

{% note info %}

Requests can be sent no more than 100 times within 5 minutes, otherwise they will be rejected with an error.

{% endnote %}

#### Example {#example-setdata}

```javascript showLineNumbers
const ysdk = await YaGames.init();

const player = await ysdk.getPlayer();

await player.setData({
    achievements: ['trophy1', 'trophy2', 'trophy3'],
})

console.log('data is set');
```

### player.getData(keys) {#getdata}

Asynchronously returns in-game user data stored in the Yandex database.

**Method signature**

```typescript
function getData(keys?: Array<string>) => Promise<object> {}
```

Accepts parameter:

<div class="table-25 table-2c25">

#|
|| **Parameter** | **Type** | **Description** ||
|| `keys` | `Array<string>` | A list of keys to be returned. If the `keys` parameter is missing, the method returns all in-game user data. ||
|#

</div>

The method returns `Promise<object>`, which contains key-value pairs.

{% note info %}

Requests can be sent no more than 100 times within 5 minutes, otherwise they will be rejected with an error.

{% endnote %}

### player.setStats(stats) {#setstats}

Saves the user's numeric data. The maximum numeric data size per player is 10&nbsp;KB.

{% note tip %}

Use this method for frequently changing numeric values (points, experience, in-game currency) instead of [player.setData()](#ingame-data).

{% endnote %}

**Method signature**

```typescript
function setStats(stats?: object) => Promise<void> {}
```

Accepts parameter:

<div class="table-25 table-2c25">

#|
|| **Parameter** | **Type** | **Description** ||
|| `stats` | `object` | An object containing key-value pairs, where each value must be a number. ||
|#

</div>

The method returns a `Promise` that indicates whether the data was saved or not.

{% note info %}

Requests can be sent no more than 60 times per minute, otherwise they will be rejected with an error.

{% endnote %}

### player.incrementStats(increments) {#incrementstats}

Changes the user's numeric data. The maximum numeric data size per player is 10&nbsp;KB.

**Method signature**

```typescript
function incrementStats(increments: object) => Promise<object> {}
```

Accepts parameter:

<div class="table-25 table-2c25">

#|
|| **Parameter** | **Type** | **Description** ||
|| `increments` | `object` | An object containing key-value pairs, where each value must be a number. ||
|#

</div>

The method returns `Promise<object>`, which contains modified and added key-value pairs.

{% note info %}

Requests can be sent no more than 60 times per minute, otherwise they will be rejected with an error.

{% endnote %}

### player.getStats(keys) {#getstats}

Asynchronously returns the user's numeric data.

**Method signature**

```typescript
function getStats(keys?: Array<string>) => Promise<object> {}
```

Accepts parameter:

<div class="table-25 table-2c25">

#|
|| **Parameter** | **Type** | **Description** ||
|| `keys` | `Array<string>` | A list of keys to be returned. If the `keys` parameter is missing, the method returns all numerical user data. ||
|#

</div>

The method returns `Promise<object>`, which contains key-value pairs.

{% note info %}

Requests can be sent no more than 60 times per minute, otherwise they will be rejected with an error.

{% endnote %}


## User profile data {#profile-data}

To get data from the user's Yandex profile, use the `Player` object methods.

### player.getUniqueID() {#getuniqueid}

Returns the user's permanent unique ID.

**Method signature**

```typescript
function getUniqueID() => string {}
```

{% note info %}

The `player.getID()` method is deprecated but will continue to work with a warning in the error console.

The values of `player.getID()` and `player.getUniqueID()` generally do not match for the same `Player` object, but they might be the same for some users. If the values differ and the game previously linked any data to the `player.getID()` value, migrate this data by linking it to the value of `player.getUniqueID()`. To migrate the data for all users at once, contact [support](https://yandex.com/dev/games/doc/en/concepts/troubleshooting.md).

{% endnote %}


### player.getIDsPerGame() {#getidspergame}

{% note alert %}

The request is available only for authorized users. For information on how to check authorization status and call the login dialog, see [User authorization](#auth).

Before sending the request, check method availability using `ysdk.isAvailableMethod('player.getIDsPerGame')`. The method returns `Promise<Boolean>`.

{% endnote %}

The method returns an array of objects with user IDs for all of the developer's games in which the user has explicitly granted access to their personal data.

**Method signature**

```typescript
function getIDsPerGame() => Promise<Array<{ appID: number, userID: string }>> {}
```

### player.getName() {#getname}

Returns the user's name.

**Method signature**

```typescript
function getName() => string {}
```

### player.getPhoto() {#getphoto}

Returns the URL of the user's avatar depending on the requested image size.

**Method signature**

```typescript
function getPhoto(size: 'small' | 'medium' | 'large') => string {}
```

### player.getPayingStatus() {#getpayingstatus}

Returns a value depending on the user's purchase frequency and amount.

**Method signature**

```typescript
function getPayingStatus() => EPayingStatus {}
```

`EPayingStatus` takes one of the following values:

#|
|| **Value** | **Description** ||
|| `paying` | The user has purchased platform currency for more than 500&nbsp;rubles in the last month. ||
|| `partially_paying` | The user has made at least one purchase of platform currency with real money in the last year. ||
|| `not_paying` | The user has not made any purchases of platform currency with real money in the last year. ||
|| `unknown` | The user is not from Russia or has not allowed such information to be shared with the developer. ||
|#

#### Example {#example-status}

```javascript showLineNumbers
const ysdk = await YaGames.init(); // Initialize the SDK.
const player = await ysdk.getPlayer(); // Get the player.
const payingStatus = player.getPayingStatus(); // Get the user's payment activity status on the platform.

if (payingStatus === 'paying' || payingStatus === 'partially_paying') {
    // Offer in-app goods at startup or instead of ads.
}
```

## Method limitations {#limits}

#|
|| **Method** | **Description** | **Limit** ||
|| `ysdk.getPlayer()` | [Initializes the `Player` object](#getplayer) |::{align="center"} 20 requests per 5 minutes ||
|| `player.setData()` | [Saves the user data](#setdata) |::{align="center"} 100 requests per 5 minutes ||
|| `player.getData()` | [Asynchronously returns in-game user data](#getdata) | ^ ||
|| `player.setStats()` | [Saves the numerical user data](#setstats) |::{align="center"} 60 requests per 1 minute ||
|| `player.getStats()` | [Asynchronously returns the numerical user data](#getstats) | ^ ||
|| `player.incrementStats()` | [Changes the numerical user data](#incrementstats) | ^ ||
|#

## Progress loss on iOS {#progress-loss}

If you use your own domain for game integration, `localStorage` may often reset on new iOS versions, causing players to lose their progress. To avoid this, use `safeStorage`, which has the same interface as `localStorage`:

```javascript showLineNumbers
const ysdk = await YaGames.init();

const safeStorage = await ysdk.getStorage();

safeStorage.setItem('key', 'safe storage is working');
console.log(safeStorage.getItem('key'));
```

To avoid manually changing the code, override `localStorage` globally.

{% note alert %}

Make sure that `localStorage` isn't used before you override it.

{% endnote %}


```javascript showLineNumbers
const ysdk = await YaGames.init();

const safeStorage = await ysdk.getStorage();

Object.defineProperty(window, 'localStorage', { get: () => safeStorage });

localStorage.setItem('key', 'safe storage is working');
console.log(localStorage.getItem('key'));
```

If you are uploading the source code as an archive, you don't need to do anything: a special wrapper in the SDK automatically makes `localStorage` reliable.


## Troubleshooting {#faq}

#### What to do if the save size exceeds SDK limits? {#large-saves}

SDK methods have limits on the maximum data size per player:

#|
|| **Method** | **Description** | **Limit** ||
|| `player.setData()` | [User data](#setdata) | 200 KB ||
|| `player.setStats()` | [Statistics (numerical values)](#setstats) | 10 KB ||
|#

If your game needs to save more data (for example, in strategies with a large number of units or complex world state), use your own server to store progress. For more information about data storage methods, see [Where to save progress](https://yandex.com/dev/games/doc/en/requirements/1/9.md#save-location).

#### How to reset player progress via code? {#reset-progress}

To clear player data, write empty progress using the [player.setData()](#setdata) and [player.setStats()](#setstats) methods.

For testing progress reset, you can also use the ☁️ **Clear cloud data** button on the [debug panel](https://yandex.com/dev/games/doc/en/console/debug-panel.md#cloud-icon).


---

<!-- source: en/_includes/sdk-support.md -->
{% note info %}

Our support team can help publish finished games on Yandex Games. If you have any questions about development or testing, ask them in the [Discord channel](https://discord.com/invite/wU4p3whr4T){.external}.

{% endnote %}

If you are facing an issue or have a question regarding the use of Yandex Games SDK, please contact support:

<!-- source: en/_includes/button-chat.md -->
<a href="https://yandex.com/chat/#/user/a4fa5c06-75db-9b38-6eea-b1673785f7d5">
  <span class="button">Write to chat</span>
</a>
<!-- endsource: en/_includes/button-chat.md -->
<!-- endsource: en/_includes/sdk-support.md -->
