---
name: StudioDeviceSimulatorService
last_updated: 2026-06-11T23:11:57Z
inherits:
  - Instance
  - Object
type: class
memory_category: Instances
tags:
  - NotCreatable
  - Service
  - NotReplicated
summary: "Service allowing you to control Studio's Device Simulator."
---

# Class: StudioDeviceSimulatorService

> Service allowing you to control Studio's Device Simulator.

## Description

Provides programmatic control over Studio's Device Simulator. Use this service
to switch between device presets, override resolution and pixel density,
control orientation and scaling, and manage custom device profiles from a
plugin or from an external tool connected through the MCP server.

All methods are asynchronous and yield the calling coroutine. The service is
available in **Edit mode** and **Play Client**. Methods that modify the active
simulation state are blocked in **PlayServer** mode.

##### Limitations

- All methods are asynchronous and yield the calling coroutine.
- Methods that modify the active simulation state (`SetDeviceAsync`,
  `StopSimulationAsync`, `SetOrientationAsync`, `SetResolutionAsync`,
  `SetPixelDensityAsync`, `SetScalingModeAsync`) error in PlayServer mode.
  They work in Edit mode and Play Client.
- `UpdateDeviceAsync` and `RemoveDeviceAsync` error when called on built-in
  presets.
- Resolution, DPI, and scaling mode methods require an active device and error
  when `GetDeviceAsync()` returns "default".
- Resolution and DPI overrides are session-level. They are not persisted and
  are cleared on `SetDeviceAsync`.
- Built-in presets are immutable.

## Methods

### Method: StudioDeviceSimulatorService:CreateDeviceAsync

**Signature:** `StudioDeviceSimulatorService:CreateDeviceAsync(config: Dictionary): string`

Creates a custom device and returns its newly assigned ID. Custom devices
are persisted to disk and appear in the Device Simulator UI.

Errors if any required field is missing or out of range.

*Yields · Security: PluginSecurity · Thread Safety: Unsafe*

**Parameters:**

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `config` | `Dictionary` |  |  |

**Returns:** `string` — string

**Create Device example**

Example of CreateDeviceAsync method

```lua
local id = Simulator:CreateDeviceAsync({
    Name = "My Custom Tablet",
    Width = 2560,
    Height = 1600,
    PixelDensity = 300,
    DeviceForm = Enum.DeviceForm.Tablet,
})
```

### Method: StudioDeviceSimulatorService:GetDeviceAsync

**Signature:** `StudioDeviceSimulatorService:GetDeviceAsync(): string`

Returns the ID of the currently active device, or `"default"` if no device
is active.

*Yields · Security: PluginSecurity · Thread Safety: Unsafe*

**Returns:** `string` — string

### Method: StudioDeviceSimulatorService:GetDeviceInfoAsync

**Signature:** `StudioDeviceSimulatorService:GetDeviceInfoAsync(deviceId: string): Dictionary`

Returns a `DeviceConfiguration` for the specified device without
activating it. Useful for inspecting presets before choosing one to switch
to.

The returned dictionary contains the following fields:

| Field | Type | Create/Update | Description |
| --- | --- | --- | --- |
| `DeviceId` | string | Read-only | Unique identifier assigned by the service. |
| `Name` | string | Required | Display name. 1 to 200 characters. Cannot be `"default"`. |
| `Width` | number | Required | Screen width in pixels. Range: 1 to 7680. |
| `Height` | number | Required | Screen height in pixels. Range: 1 to 4320. |
| `PixelDensity` | number | Required | Pixel density in DPI. Range: 72 to 10000. |
| `DeviceForm` | [DeviceForm](/docs/reference/engine/enums/DeviceForm.md) | Optional (default: Phone) | One of Phone, Tablet, Desktop, Console, VR. |
| `IsCustom` | boolean | Read-only | `true` if the device was user-created. |
| `ResolutionScale` | number | Optional (default: 1.0) | Resolution scaling factor. Must be greater than 0, max 10.0. |
| `PortraitKeyboardHeight` | number | Optional (default: 0) | Virtual keyboard height in portrait mode. |
| `LandscapeKeyboardHeight` | number | Optional (default: 0) | Virtual keyboard height in landscape mode. |

*Yields · Security: PluginSecurity · Thread Safety: Unsafe*

**Parameters:**

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `deviceId` | `string` |  |  |

**Returns:** `Dictionary` — A dictionary containing the device configuration and passed to
`CreateDeviceAsync` and `UpdateDeviceAsync`.

### Method: StudioDeviceSimulatorService:GetDeviceListAsync

**Signature:** `StudioDeviceSimulatorService:GetDeviceListAsync(): Array`

Returns an array of device IDs for all available presets, including
built-in and custom devices.

*Yields · Security: PluginSecurity · Thread Safety: Unsafe*

**Returns:** `Array` — An array of device IDs.

**Get device list example**

Example of GetDeviceListAsync method

```lua
local Simulator = game:GetService("StudioDeviceSimulatorService")
local devices = Simulator:GetDeviceListAsync()

for _, deviceId in devices do
    print(deviceId)
end
```

### Method: StudioDeviceSimulatorService:GetOrientationAsync

**Signature:** `StudioDeviceSimulatorService:GetOrientationAsync(): ScreenOrientation`

Returns the current simulated orientation.

*Yields · Security: PluginSecurity · Thread Safety: Unsafe*

**Returns:** `ScreenOrientation` — ScreenOrientation

### Method: StudioDeviceSimulatorService:GetPixelDensityAsync

**Signature:** `StudioDeviceSimulatorService:GetPixelDensityAsync(): float`

Returns the current simulated pixel density.

*Yields · Security: PluginSecurity · Thread Safety: Unsafe*

**Returns:** `float` — number

### Method: StudioDeviceSimulatorService:GetResolutionAsync

**Signature:** `StudioDeviceSimulatorService:GetResolutionAsync(): Vector2`

Returns the current simulated resolution.

*Yields · Security: PluginSecurity · Thread Safety: Unsafe*

**Returns:** `Vector2` — Vector2

### Method: StudioDeviceSimulatorService:GetScalingModeAsync

**Signature:** `StudioDeviceSimulatorService:GetScalingModeAsync(): DeviceSimulatorScalingMode`

Returns the current scaling mode.

*Yields · Security: PluginSecurity · Thread Safety: Unsafe*

**Returns:** `DeviceSimulatorScalingMode` — DeviceSimulatorScalingMode

### Method: StudioDeviceSimulatorService:RemoveDeviceAsync

**Signature:** `StudioDeviceSimulatorService:RemoveDeviceAsync(deviceId: string): ()`

Removes a custom device.

Errors if the target is a built-in preset.

*Yields · Security: PluginSecurity · Thread Safety: Unsafe*

**Parameters:**

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `deviceId` | `string` |  |  |

**Returns:** `()`

### Method: StudioDeviceSimulatorService:SetDeviceAsync

**Signature:** `StudioDeviceSimulatorService:SetDeviceAsync(deviceId: string): ()`

Activates the specified device. Passing `"default"` stops simulation and
is equivalent to calling `StopSimulationAsync`.

Errors in PlayServer mode. Errors if the device ID does not exist.

*Yields · Security: PluginSecurity · Thread Safety: Unsafe*

**Parameters:**

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `deviceId` | `string` |  |  |

**Returns:** `()`

### Method: StudioDeviceSimulatorService:SetOrientationAsync

**Signature:** `StudioDeviceSimulatorService:SetOrientationAsync(orientation: ScreenOrientation): ()`

Sets or gets the simulated screen orientation. Accepts Portrait,
LandscapeLeft, or LandscapeRight. Other values will error.

Errors in PlayServer mode.

*Yields · Security: PluginSecurity · Thread Safety: Unsafe*

**Parameters:**

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `orientation` | `ScreenOrientation` |  |  |

**Returns:** `()`

### Method: StudioDeviceSimulatorService:SetPixelDensityAsync

**Signature:** `StudioDeviceSimulatorService:SetPixelDensityAsync(density: float): ()`

Overrides or returns the simulated pixel density in DPI. Session-level;
cleared on device switch.

This method requires an active device. `SetPixelDensityAsync` also errors
in PlayServer mode.

*Yields · Security: PluginSecurity · Thread Safety: Unsafe*

**Parameters:**

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `density` | `float` |  |  |

**Returns:** `()`

### Method: StudioDeviceSimulatorService:SetResolutionAsync

**Signature:** `StudioDeviceSimulatorService:SetResolutionAsync(width: int, height: int): ()`

Overrides the simulated viewport resolution or returns the current
resolution as a Vector2. Overrides are session-level and cleared when you
switch devices.

Coordinates are in landscape space: the first parameter maps to the
horizontal axis in landscape, the second to the vertical axis. In
portrait, axes are swapped automatically.

Both methods require an active device. They error if `GetDeviceAsync()`
returns `"default"`. `SetResolutionAsync` also errors in PlayServer mode.

*Yields · Security: PluginSecurity · Thread Safety: Unsafe*

**Parameters:**

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `width` | `int` |  |  |
| `height` | `int` |  |  |

**Returns:** `()`

### Method: StudioDeviceSimulatorService:SetScalingModeAsync

**Signature:** `StudioDeviceSimulatorService:SetScalingModeAsync(mode: DeviceSimulatorScalingMode): ()`

Controls how the simulated resolution maps to the Studio viewport.

- `ScaleToPhysicalSize` scales the viewport to approximate physical device
  size.
- `ActualResolution` renders at exact pixel resolution.
- `FitToWindow` scales to fill the viewport.

Both methods require an active device. `SetScalingModeAsync` also errors
in PlayServer mode.

*Yields · Security: PluginSecurity · Thread Safety: Unsafe*

**Parameters:**

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `mode` | `DeviceSimulatorScalingMode` |  |  |

**Returns:** `()`

### Method: StudioDeviceSimulatorService:StopSimulationAsync

**Signature:** `StudioDeviceSimulatorService:StopSimulationAsync(): ()`

Stops the active simulation. Prefer this over `SetDeviceAsync("default")`
for clarity.

Errors in PlayServer mode.

*Yields · Security: PluginSecurity · Thread Safety: Unsafe*

**Returns:** `()`

### Method: StudioDeviceSimulatorService:UpdateDeviceAsync

**Signature:** `StudioDeviceSimulatorService:UpdateDeviceAsync(deviceId: string, config: Dictionary): ()`

Updates a custom device's configuration.

Errors if the target is a built-in preset.

*Yields · Security: PluginSecurity · Thread Safety: Unsafe*

**Parameters:**

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `deviceId` | `string` |  |  |
| `config` | `Dictionary` |  |  |

**Returns:** `()`

**Update Device example**

Example of UpdateDeviceAsync method

```lua
Simulator:UpdateDeviceAsync(id, {
    Name = "My Custom Tablet",
    Width = 2732,
    Height = 2048,
    PixelDensity = 264,
    DeviceForm = Enum.DeviceForm.Tablet,
})
```

## Events

### Event: StudioDeviceSimulatorService.ConfigurationChanged

**Signature:** `StudioDeviceSimulatorService.ConfigurationChanged()`

Fires when the active simulation state changes: device switch,
orientation, resolution, pixel density, scaling mode, or user interaction
with the Device Simulator UI. Does not fire for catalog-only operations
such as `CreateDeviceAsync`, `UpdateDeviceAsync` on a non-active device,
`RemoveDeviceAsync` on a non-active device, or `GetDeviceInfoAsync`.

Getter calls inside the handler are async and will yield.

*Security: PluginSecurity*

**Configuration changed example**

Example of ConfigurationChanged event

```lua
Simulator.ConfigurationChanged:Connect(function()
    local deviceId = Simulator:GetDeviceAsync()
    if deviceId ~= "default" then
        local res = Simulator:GetResolutionAsync()
        print(string.format("Active: %s @ %dx%d", deviceId, res.X, res.Y))
    end
end)
```

## Inherited Members

### From [Instance](/docs/reference/engine/classes/Instance.md)

- **Property `Archivable`** (`boolean`): Determines if an Instance and its descendants can be cloned using
- **Property `archivable`** (`boolean`):  *(deprecated, hidden)*
- **Property `Capabilities`** (`SecurityCapabilities`): The set of capabilities allowed to be used for scripts inside this
- **Property `Name`** (`string`): A non-unique identifier of the Instance.
- **Property `Parent`** (`Instance`): Determines the hierarchical parent of the Instance.
- **Property `PredictionMode`** (`PredictionMode`): 
- **Property `RobloxLocked`** (`boolean`): A deprecated property that used to protect CoreGui objects. *(hidden)*
- **Property `Sandboxed`** (`boolean`): When enabled, the instance can only access abilities in its `Capabilities`
- **Property `UniqueId`** (`UniqueId`): A unique identifier for the instance.
- **Method `AddTag(tag: string): ()`**: Applies a tag to the instance.
- **Method `children(): Instances`**: Returns an array of the object's children. *(deprecated)*
- **Method `ClearAllChildren(): ()`**: This method destroys all of an instance's children.
- **Method `Clone(): Instance`**: Create a copy of an instance and all its descendants, ignoring instances
- **Method `clone(): Instance`**:  *(deprecated)*
- **Method `Destroy(): ()`**: Sets the Instance.Parent property to `nil`, locks the
- **Method `destroy(): ()`**:  *(deprecated)*
- **Method `FindFirstAncestor(name: string): Instance?`**: Returns the first ancestor of the Instance whose
- **Method `FindFirstAncestorOfClass(className: string): Instance?`**: Returns the first ancestor of the Instance whose
- **Method `FindFirstAncestorWhichIsA(className: string): Instance?`**: Returns the first ancestor of the Instance for whom
- **Method `FindFirstChild(name: string, recursive?: boolean): Instance?`**: Returns the first child of the Instance found with the given name.
- **Method `findFirstChild(name: string, recursive?: boolean): Instance`**:  *(deprecated)*
- **Method `FindFirstChildOfClass(className: string): Instance?`**: Returns the first child of the Instance whose
- **Method `FindFirstChildWhichIsA(className: string, recursive?: boolean): Instance?`**: Returns the first child of the Instance for whom
- **Method `FindFirstDescendant(name: string): Instance?`**: Returns the first descendant found with the given Instance.Name.
- **Method `GetActor(): Actor?`**: Returns the Actor associated with the Instance, if any.
- **Method `GetAttribute(attribute: string): Variant`**: Returns the value which has been assigned to the given attribute name.
- **Method `GetAttributeChangedSignal(attribute: string): RBXScriptSignal`**: Returns an event that fires when the given attribute changes.
- **Method `GetAttributes(): Dictionary`**: Returns a dictionary of the instance's attributes.
- **Method `GetChildren(): Instances`**: Returns an array containing all of the instance's children.
- **Method `getChildren(): Instances`**:  *(deprecated)*
- **Method `GetDebugId(scopeLength?: int): string`**: Returns a coded string of the debug ID used internally by Roblox.
- **Method `GetDescendants(): Instances`**: Returns an array containing all of the descendants of the instance.
- **Method `GetFullName(): string`**: Returns a string describing the instance's ancestry.
- **Method `GetStyled(name: string, selector: string?): Variant`**: Returns the styled or explicitly modified value of the specified property,
- **Method `GetStyledPropertyChangedSignal(property: string): RBXScriptSignal`**: 
- **Method `GetTags(): Array`**: Gets an array of all tags applied to the instance.
- **Method `HasTag(tag: string): boolean`**: Check whether the instance has a given tag.
- **Method `IsAncestorOf(descendant: Instance): boolean`**: Returns true if an Instance is an ancestor of the given
- **Method `IsDescendantOf(ancestor: Instance): boolean`**: Returns `true` if an Instance is a descendant of the given
- **Method `isDescendantOf(ancestor: Instance): boolean`**:  *(deprecated)*
- **Method `IsPropertyModified(property: string): boolean`**: Returns `true` if the value stored in the specified property is not equal
- **Method `QueryDescendants(selector: string): Instances`**: Returns an array containing all descendants of the instance that match the
- **Method `Remove(): ()`**: Sets the object's `Parent` to `nil`, and does the same for all its *(deprecated)*
- **Method `remove(): ()`**:  *(deprecated)*
- **Method `RemoveTag(tag: string): ()`**: Removes a tag from the instance.
- **Method `ResetPropertyToDefault(property: string): ()`**: Resets a property to its default value.
- **Method `SetAttribute(attribute: string, value: Variant): ()`**: Sets the attribute with the given name to the given value.
- **Method `WaitForChild(childName: string, timeOut: double): Instance`**: Returns the child of the Instance with the given name. If the
- **Event `AncestryChanged`**: Fires when the Instance.Parent property of this object or one of
- **Event `AttributeChanged`**: Fires whenever an attribute is changed on the Instance.
- **Event `ChildAdded`**: Fires after an object is parented to this Instance.
- **Event `childAdded`**:  *(deprecated)*
- **Event `ChildRemoved`**: Fires after a child is removed from this Instance.
- **Event `DescendantAdded`**: Fires after a descendant is added to the Instance.
- **Event `DescendantRemoving`**: Fires immediately before a descendant of the Instance is removed.
- **Event `Destroying`**: Fires immediately before (or is deferred until after) the instance is
- **Event `StyledPropertiesChanged`**: Fires whenever any style property is changed on the instance, including

### From [Object](/docs/reference/engine/classes/Object.md)

- **Property `ClassName`** (`string`): A read-only string representing the class this Object belongs to.
- **Property `className`** (`string`):  *(deprecated)*
- **Method `GetPropertyChangedSignal(property: string): RBXScriptSignal`**: Get an event that fires when a given property of the object changes.
- **Method `IsA(className: string): boolean`**: Returns true if an object's class matches or inherits from a given class.
- **Method `isA(className: string): boolean`**:  *(deprecated)*
- **Event `Changed`**: Fires immediately after a property of the object changes, with some