Tuya DP ID List: How to Find DP IDs for Smart Plug, Bulb, and Camera
Step-by-step guide to finding Tuya DP IDs using the IoT Cloud API Explorer. Includes DP ID reference tables for smart plugs, bulbs, IP cameras, and IR blasters - useful for LocalTuya and Home Assistant integrations.
If you’re setting up LocalTuya or any local Tuya integration in Home Assistant, you’ll need the exact DP IDs for each device. The problem is that DP IDs are not standardized - they vary by device type, brand, and sometimes even firmware version. The only reliable source is Tuya’s own cloud platform.
Here’s how to look them up.
Getting the Device ID
First you need the device ID. Go to iot.tuya.com, then:
- Cloud -> Project -> select your project
- Go to the Devices tab
- Find the device you want to inspect and copy its Device ID
The device ID looks something like bf3a9c... - a long hex string. Keep it handy.
Querying Properties via API Explorer
Once you have the device ID:
- Cloud -> API Explorer
- Under Device Control, find Query Properties
- Paste in the device ID and run the query
You’ll get back a JSON response listing every DP (Data Point) the device supports, along with its current value.
Reading the Response
Here’s what a typical smart plug response looks like:
{
"result": {
"properties": [
{ "code": "switch_1", "dp_id": 1, "type": "bool", "value": true },
{ "code": "countdown_1", "dp_id": 9, "type": "value", "value": 0 },
{ "code": "add_ele", "dp_id": 17, "type": "value", "value": 22 },
{ "code": "cur_current", "dp_id": 18, "type": "value", "value": 398 },
{ "code": "cur_power", "dp_id": 19, "type": "value", "value": 667 },
{ "code": "cur_voltage", "dp_id": 20, "type": "value", "value": 2188 },
{ "code": "voltage_coe", "dp_id": 22, "type": "value", "value": 571 },
{ "code": "electric_coe", "dp_id": 23, "type": "value", "value": 29558 },
{ "code": "power_coe", "dp_id": 24, "type": "value", "value": 15928 },
{ "code": "relay_status", "dp_id": 38, "type": "enum", "value": "memory" },
{ "code": "child_lock", "dp_id": 41, "type": "bool", "value": false }
]
},
"success": true
}
Each entry tells you:
code- the human-readable function namedp_id- the numeric ID used in local API callstype- data type:bool,value,enum,string,bitmapvalue- current reading
The Calibration Coefficients
The raw values for power monitoring DPs are not in standard units. They need to be divided by a calibration coefficient before they make sense.
For this device:
| DP | Code | Raw Value | Coefficient (dp_id) | Actual Value |
|---|---|---|---|---|
| 20 | cur_voltage | 2188 | voltage_coe = 571 (dp 22) | ~220V |
| 18 | cur_current | 398 | electric_coe = 29558 (dp 23) | ~398mA |
| 19 | cur_power | 667 | power_coe = 15928 (dp 24) | ~66.7W |
The formula is roughly raw / coefficient * scale, but the exact scale depends on the device firmware. In practice, for voltage: 2188 / 10 = 218.8V is close enough. For power: 667 / 10 = 66.7W. The coefficients (dp 22-25) are calibration constants baked in at the factory - you read them once and use them as divisors.
If you’re setting up a LocalTuya integration in Home Assistant, these coefficient DPs are what you put in the “coefficient” fields for each sensor entity.
What the Other DPs Mean
A few non-obvious ones worth noting:
| DP | Code | Notes |
|---|---|---|
| 21 | test_bit | Factory test flag. Read-only, ignore it. |
| 26 | fault | Fault status register (bitmap). 0 = no faults. |
| 38 | relay_status | Behavior after power cut: "memory" = restore last state, "on" = always on, "off" = always off. |
| 39 | overcharge_switch | Overcharge protection toggle. Leave this alone. |
| 40 | light_mode | Indicator LED behavior: "relay" = follows switch state, "pos" = always on, "none" = always off. |
Different Devices, Different DPs
Even two devices of the same type can have slightly different coefficients. Here’s a second smart plug from the same setup:
{ "code": "cur_voltage", "dp_id": 20, "value": 2215 },
{ "code": "cur_current", "dp_id": 18, "value": 422 },
{ "code": "cur_power", "dp_id": 19, "value": 614 },
{ "code": "voltage_coe", "dp_id": 22, "value": 560 },
{ "code": "electric_coe", "dp_id": 23, "value": 27054 },
{ "code": "power_coe", "dp_id": 24, "value": 14536 }
Same DP IDs, but different coefficient values. This confirms you need to query each device individually - you can’t copy coefficients from one plug to another even if they look identical.
Also notice switch_inching (dp 44) has value "AAAA" on this device but was empty on the first one. Inching mode is a timed relay feature - "AAAA" is a base64-encoded config. If you’re not using it, ignore it.
Smart Bulb DPs
A smart bulb looks completely different from a plug. Here are two bulbs from the same setup:
Bulb A (currently off, last set to dim warm white):
{ "code": "switch_led", "dp_id": 20, "type": "bool", "value": false },
{ "code": "work_mode", "dp_id": 21, "type": "enum", "value": "white" },
{ "code": "bright_value", "dp_id": 22, "type": "value", "value": 10 },
{ "code": "temp_value", "dp_id": 23, "type": "value", "value": 0 },
{ "code": "colour_data", "dp_id": 24, "type": "string", "value": "00300014008c" },
{ "code": "scene_data", "dp_id": 25, "type": "string", "value": "00280d0000000000000000c80000" },
{ "code": "rhythm_mode", "dp_id": 30, "type": "raw", "value": "AAAAAAA=" },
{ "code": "sleep_mode", "dp_id": 31, "type": "raw", "value": "AAA=" },
{ "code": "wakeup_mode", "dp_id": 32, "type": "raw", "value": "AAA=" },
{ "code": "power_memory", "dp_id": 33, "type": "raw", "value": "AAEAAAPoA+gD6AAA" }
Bulb B (also off, last set to brighter warm white):
{ "code": "switch_led", "dp_id": 20, "value": false },
{ "code": "work_mode", "dp_id": 21, "value": "white" },
{ "code": "bright_value", "dp_id": 22, "value": 700 },
{ "code": "temp_value", "dp_id": 23, "value": 40 },
{ "code": "colour_data", "dp_id": 24, "value": "003003e80064" }
Key DPs for a bulb:
| DP | Code | Notes |
|---|---|---|
| 20 | switch_led | On/off. |
| 21 | work_mode | "white" = tunable white, "colour" = RGB, "scene" = presets. |
| 22 | bright_value | Brightness, range 10-1000. |
| 23 | temp_value | Color temperature: 0 = warmest, 1000 = coolest. Bulb A is at 0 (full warm), Bulb B is at 40 (slightly cooler). |
| 24 | colour_data | HSV color as hex string in colour mode. Format: HHHHSSSSVVVV (4 hex digits each). 003003e80064 = H:48, S:1000, V:100. |
| 25 | scene_data | Encoded scene config, only relevant in scene mode. |
| 30-32 | rhythm/sleep/wakeup_mode | Schedule features. All zeros = disabled. |
| 33 | power_memory | Stores last brightness/color state for restore after power cut. |
Notice that dp 20-25 on the bulb are completely different from dp 20-25 on the smart plug. The DP numbering is not standardized across device categories - it’s per-device-type.
IP Camera DPs
IP cameras have the most DPs of any device category. Here are two cameras from the same setup - a PTZ outdoor camera and an indoor camera.
PTZ Outdoor Camera (Dings):
{ "code": "basic_indicator", "dp_id": 101, "type": "bool", "value": true },
{ "code": "basic_flip", "dp_id": 103, "type": "bool", "value": true },
{ "code": "basic_private", "dp_id": 105, "type": "bool", "value": false },
{ "code": "motion_sensitivity", "dp_id": 106, "type": "enum", "value": "2" },
{ "code": "basic_nightvision", "dp_id": 108, "type": "enum", "value": "0" },
{ "code": "sd_storge", "dp_id": 109, "type": "string", "value": "61023120|60914000|109120" },
{ "code": "sd_status", "dp_id": 110, "type": "value", "value": 1 },
{ "code": "ptz_control", "dp_id": 119, "type": "enum", "value": "6" },
{ "code": "motion_switch", "dp_id": 134, "type": "bool", "value": true },
{ "code": "record_switch", "dp_id": 150, "type": "bool", "value": true },
{ "code": "record_mode", "dp_id": 151, "type": "enum", "value": "1" },
{ "code": "motion_tracking", "dp_id": 161, "type": "bool", "value": false },
{ "code": "humanoid_filter", "dp_id": 170, "type": "bool", "value": true },
{ "code": "onvif_switch", "dp_id": 241, "type": "bool", "value": true },
{ "code": "onvif_ip_addr", "dp_id": 243, "type": "string", "value": "192.168.0.x" }
Indoor PTZ Camera (Eyesec):
{ "code": "basic_indicator", "dp_id": 101, "type": "bool", "value": true },
{ "code": "basic_flip", "dp_id": 103, "type": "bool", "value": false },
{ "code": "basic_osd", "dp_id": 104, "type": "bool", "value": true },
{ "code": "basic_wdr", "dp_id": 107, "type": "bool", "value": true },
{ "code": "sd_storge", "dp_id": 109, "type": "string", "value": "61023120|32|61023088" },
{ "code": "sd_format_state", "dp_id": 117, "type": "value", "value": 100 },
{ "code": "ipc_auto_siren", "dp_id": 120, "type": "bool", "value": false },
{ "code": "siren_switch", "dp_id": 159, "type": "bool", "value": true },
{ "code": "zoom_control", "dp_id": 163, "type": "enum", "value": "0" },
{ "code": "zoom_value", "dp_id": 231, "type": "value", "value": 10 },
{ "code": "onvif_switch", "dp_id": 237, "type": "bool", "value": true },
{ "code": "onvif_ip_addr", "dp_id": 240, "type": "string", "value": "192.168.0.x" }
Key camera DPs worth knowing:
| DP | Code | Notes |
|---|---|---|
| 101 | basic_indicator | Status LED on/off. |
| 103 | basic_flip | Flip image vertically. Outdoor camera has this on (mounted upside down), indoor is off. |
| 104 | basic_osd | On-screen timestamp display. |
| 105 | basic_private | Privacy mode, disables video feed. |
| 107 | basic_wdr | Wide dynamic range for high-contrast scenes. |
| 108 | basic_nightvision | "0" = auto, "1" = on, "2" = off. |
| 109 | sd_storge | SD card info: total_kb|used_kb|free_kb. 61023120|60914000|109120 = ~58GB total, ~58GB used, ~106MB free. |
| 110 | sd_status | 1 = SD card present and normal. |
| 119 | ptz_control | PTZ direction: 0=up, 1=down, 2=left, 3=right, 4=upper-left, 5=upper-right, 6=lower-left, 7=lower-right. |
| 134 | motion_switch | Motion detection on/off. |
| 150 | record_switch | Recording on/off. |
| 151 | record_mode | "1" = continuous, "2" = event-only. |
| 159 | siren_switch | Siren/alarm on/off (Eyesec only). |
| 161 | motion_tracking | Auto-follow moving subjects. |
| 163 | zoom_control | Zoom in/out (Eyesec only). |
| 170 | humanoid_filter | Only trigger alerts for humans, ignore animals/cars. |
| 212 | initiative_message | Base64-encoded JSON with latest motion event data and cloud image path. |
| 237/241 | onvif_switch | ONVIF on/off. DP number differs between brands - 241 on Dings, 237 on Eyesec. |
| 240/243 | onvif_ip_addr | Camera’s local IP as reported by the device. |
The initiative_message DP (212) contains base64-encoded JSON with the latest motion event data including a cloud storage path to the captured image. This is what triggers push notifications.
Note that onvif_switch is dp 241 on the Dings camera but dp 237 on the Eyesec. Same function, different DP number - another reminder that you can’t assume DP IDs are consistent even for the same feature across brands.
Smart IR Blaster DPs
An IR blaster is the simplest device type - it’s essentially a one-way transmitter:
{ "code": "control", "dp_id": 1, "type": "enum", "value": "send_ir" },
{ "code": "study_code", "dp_id": 2, "type": "raw", "value": "<base64 IR signal>" },
{ "code": "ir_code", "dp_id": 3, "type": "string" },
{ "code": "key_code", "dp_id": 4, "type": "string" },
{ "code": "key_study", "dp_id": 7, "type": "raw" },
{ "code": "delay_time", "dp_id": 10, "type": "value", "value": 0 }
| DP | Code | Notes |
|---|---|---|
| 1 | control | Action: "send_ir" to transmit, "study" to learn a new code. |
| 2 | study_code | Learned IR signal in base64 raw format. Stored when you teach the blaster a new button. |
| 3-6 | ir_code / key_code | Predefined IR codes from Tuya’s cloud library for known devices. |
| 7-9 | key_study | Raw slots for custom learned codes. |
| 10 | delay_time | Delay in ms before sending, for sequenced commands. |
The IR blaster has no readable state - you can’t query “what was the last thing sent”. It’s write-only in practice.
Why DP IDs Matter
The code field is what Tuya’s cloud API uses. But local integrations like LocalTuya, tinytuya, and some Home Assistant integrations communicate directly with the device over the local network using the numeric dp_id. The cloud and local protocols are different, and the mapping between code and dp_id is device-specific - it’s not standardized across manufacturers or even across firmware versions of the same device.
This is why you can’t just look up a DP table online and trust it. The API Explorer gives you the ground truth for your specific device.
Summary
The Tuya IoT platform’s API Explorer is the most reliable way to inspect what a device actually exposes. The flow is straightforward: get the device ID from the Devices tab, run Query Properties in the API Explorer, and you get a complete map of every DP with its current value and data type.
For power monitoring devices, pay attention to the coefficient DPs (typically in the 22-25 range) - the raw sensor values are meaningless without them. And for local integrations, the dp_id numbers are what you actually need, not the human-readable codes.
Smart home setup giving you grief?
I integrate Tuya, Home Assistant, and ESPHome devices into reliable local-first smart homes. If you want yours to actually work, let's chat.
Get in touch